aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Christoph Steiner <eighthave@users.sourceforge.net>2005-11-10 05:52:11 +0000
committerHans-Christoph Steiner <eighthave@users.sourceforge.net>2005-11-10 05:52:11 +0000
commitceac394c2133d44e81db2eb633ff54a9ad6ce7c5 (patch)
treeadc534407af80a976263c907897907cb13ef1c82
This commit was generated by cvs2svn to compensate for changes in r3865,svn2git-root
which included commits to RCS files with non-trunk default branches. svn path=/trunk/extensions/gripd/; revision=3866
-rw-r--r--.xvpics/joystickA.xpmbin0 -> 337 bytes
-rw-r--r--.xvpics/midiA.xpmbin0 -> 337 bytes
-rw-r--r--README.txt181
-rw-r--r--connect.xpm27
-rw-r--r--connectX.xpm24
-rw-r--r--examples/clickme.jpgbin0 -> 2798 bytes
-rw-r--r--examples/fmlogo.gifbin0 -> 6459 bytes
-rw-r--r--examples/fmsynth.gpd442
-rw-r--r--examples/gripd.gpd380
-rw-r--r--examples/gripd.pd73
-rw-r--r--examples/gripdExamples.pd247
-rw-r--r--examples/gripdFM.pd135
-rw-r--r--examples/poof.jpgbin0 -> 2065 bytes
-rw-r--r--examples/scale.gifbin0 -> 2240 bytes
-rw-r--r--examples/scale2.gifbin0 -> 2296 bytes
-rw-r--r--examples/screw.gifbin0 -> 1181 bytes
-rwxr-xr-xgripd42
-rw-r--r--gripd.opt2
-rw-r--r--gripd.py43
-rw-r--r--gripd.spec16
-rw-r--r--gripdControls.py1675
-rw-r--r--gripdFunctions.py191
-rw-r--r--gripdMain.py2337
-rw-r--r--icon.picbin0 -> 3774 bytes
-rw-r--r--joystick.xpm68
-rw-r--r--joystickA.xpm45
-rw-r--r--joystickX.xpm57
-rw-r--r--log.txt0
-rw-r--r--midi.xpm24
-rw-r--r--midiA.xpm24
-rw-r--r--midiX.xpm26
-rw-r--r--src/Makefile.Linux48
-rw-r--r--src/Makefile.NT86
-rw-r--r--src/Makefile.midiioLibrary.ALSA205
-rw-r--r--src/Makefile.midiioLibrary.NT462
-rw-r--r--src/Makefile.midiioLibrary.OSS205
-rw-r--r--src/gripd.c1031
-rw-r--r--src/gripd.h227
-rw-r--r--src/joystick.c296
-rw-r--r--src/joystick_wrap.c692
-rw-r--r--src/makefile44
-rw-r--r--src/midi.cpp146
-rw-r--r--src/midi_wrap.c723
-rw-r--r--src/midiio/include/Array.cpp378
-rw-r--r--src/midiio/include/Array.h67
-rw-r--r--src/midiio/include/CircularBuffer.cpp291
-rw-r--r--src/midiio/include/CircularBuffer.h66
-rw-r--r--src/midiio/include/Collection.cpp355
-rw-r--r--src/midiio/include/Collection.h70
-rw-r--r--src/midiio/include/FileIO.h148
-rw-r--r--src/midiio/include/MidiFile.h108
-rw-r--r--src/midiio/include/MidiFileWrite.h61
-rw-r--r--src/midiio/include/MidiIO.h58
-rw-r--r--src/midiio/include/MidiInPort.h98
-rw-r--r--src/midiio/include/MidiInPort_alsa.h107
-rw-r--r--src/midiio/include/MidiInPort_alsa05.h107
-rw-r--r--src/midiio/include/MidiInPort_linux.h94
-rw-r--r--src/midiio/include/MidiInPort_oss.h105
-rw-r--r--src/midiio/include/MidiInPort_unsupported.h89
-rw-r--r--src/midiio/include/MidiInPort_visual.h114
-rw-r--r--src/midiio/include/MidiInput.h53
-rw-r--r--src/midiio/include/MidiMessage.h78
-rw-r--r--src/midiio/include/MidiOutPort.h92
-rw-r--r--src/midiio/include/MidiOutPort_alsa.h79
-rw-r--r--src/midiio/include/MidiOutPort_linux.h80
-rw-r--r--src/midiio/include/MidiOutPort_oss.h75
-rw-r--r--src/midiio/include/MidiOutPort_unsupported.h71
-rw-r--r--src/midiio/include/MidiOutPort_visual.h75
-rw-r--r--src/midiio/include/MidiOutput.h140
-rw-r--r--src/midiio/include/MidiPort.h49
-rw-r--r--src/midiio/include/Options.h106
-rw-r--r--src/midiio/include/Options_private.h73
-rw-r--r--src/midiio/include/Sequencer_alsa.h139
-rw-r--r--src/midiio/include/Sequencer_oss.h92
-rw-r--r--src/midiio/include/SigTimer.h104
-rw-r--r--src/midiio/include/Voice.h70
-rw-r--r--src/midiio/include/gminstruments.h251
-rw-r--r--src/midiio/include/midichannels.h42
-rw-r--r--src/midiio/include/mididefines.h34
-rw-r--r--src/midiio/include/midiiolib.h57
-rw-r--r--src/midiio/include/notenames.h219
-rw-r--r--src/midiio/include/sigConfiguration.h100
-rw-r--r--src/midiio/src/FileIO.cpp761
-rw-r--r--src/midiio/src/MidiFile.cpp1200
-rw-r--r--src/midiio/src/MidiFileWrite.cpp259
-rw-r--r--src/midiio/src/MidiIO.cpp283
-rw-r--r--src/midiio/src/MidiInPort_alsa.cpp1038
-rw-r--r--src/midiio/src/MidiInPort_alsa05.cpp995
-rw-r--r--src/midiio/src/MidiInPort_linux.cpp491
-rw-r--r--src/midiio/src/MidiInPort_oss.cpp1036
-rw-r--r--src/midiio/src/MidiInPort_unsupported.cpp487
-rw-r--r--src/midiio/src/MidiInPort_visual.cpp1267
-rw-r--r--src/midiio/src/MidiInput.cpp224
-rw-r--r--src/midiio/src/MidiMessage.cpp406
-rw-r--r--src/midiio/src/MidiOutPort_alsa.cpp469
-rw-r--r--src/midiio/src/MidiOutPort_linux.cpp381
-rw-r--r--src/midiio/src/MidiOutPort_oss.cpp462
-rw-r--r--src/midiio/src/MidiOutPort_unsupported.cpp402
-rw-r--r--src/midiio/src/MidiOutPort_visual.cpp532
-rw-r--r--src/midiio/src/MidiOutput.cpp1082
-rw-r--r--src/midiio/src/MidiPort.cpp189
-rw-r--r--src/midiio/src/Options.cpp887
-rw-r--r--src/midiio/src/Options_private.cpp358
-rw-r--r--src/midiio/src/Sequencer_alsa.cpp643
-rw-r--r--src/midiio/src/Sequencer_alsa05.cpp518
-rw-r--r--src/midiio/src/Sequencer_oss.cpp809
-rw-r--r--src/midiio/src/SigTimer.cpp498
-rw-r--r--src/midiio/src/Voice.cpp334
108 files changed, 30630 insertions, 0 deletions
diff --git a/.xvpics/joystickA.xpm b/.xvpics/joystickA.xpm
new file mode 100644
index 0000000..4b12dd6
--- /dev/null
+++ b/.xvpics/joystickA.xpm
Binary files differ
diff --git a/.xvpics/midiA.xpm b/.xvpics/midiA.xpm
new file mode 100644
index 0000000..9865cba
--- /dev/null
+++ b/.xvpics/midiA.xpm
Binary files differ
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..d00f577
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,181 @@
+GrIPD: Graphical Interface for Pure Data
+----------------------------------------
+
+v0.1.1
+
+-What is GrIPD-
+GrIPD is a cross-platform extension to Miller Puckette's Pure Data
+software that allows the one to design custom graphical user
+interfaces for Pd patches. GrIPD is not a replacement for the Pd
+Tcl/Tk GUI, but instead is intended to allow one to create a front end
+to a Pd patch. The concept is to create your PD patch normally and
+then your GUI using GrIPD. You can then lauch Pd using the -nogui
+command line argument (although this is certainly not necessary) so
+only your custom front end will be displayed. GrIPD, itself, consists
+of two parts: the "gripd" Pd object and an external GUI
+window/editor. The Pd object was written in C and the external GUI was
+written in Python using the wxWindows. GrIPD is released under the
+GNU General Public License.
+
+
+-How GrIPD works-
+The two parts of GrIPD communicate via TCP/IP sockets so they can run
+on one machine or on separate machines over a network; so, for
+example, the GUI could be on a laptop on stage controlling or
+displaying info from the Pd audio engine in the house next to the
+mixer. The communication works through Pd's implimentation of
+"send" and "receive" objects. Basically, each GrIPD control object has
+a send and receive symbol associated with it.
+
+
+-Supported platforms-
+GrIPD is currently available for Linux/GTK+ and MS Windows
+platforms. It may work on other Unix's, but as of yet it has not been
+tested. Since wxPython and C are both highly portable, most of GrIPD
+is as well. The only issues should be the C socket and multi-process
+code.
+
+
+-Requirements-
+ For Win32:
+ * Pd
+ For Linux:
+ * Pd
+ * GTK+
+
+ To compile under Win32:
+ * Python (v2.2 or later)
+ * wxPython- wxWindows for Python (v2.4.0 or later)
+ * a C/C++ compiler
+ * to make a stand-alone .exe file you'll also need
+ py2exe v0.3.1 (http://starship.python.net/crew/theller/py2exe/)
+
+ To compile under Linux:
+ * Python (v2.2 or later)
+ * wxPython- wxWindows for Python (v2.4.0 or later)
+ * GTK+ and wxGTK
+ * C/C++ compiler
+ * to make a stand-alone binary executable you'll also need
+ Installer v5b4 (http://www.mcmillan-inc.com/install5_ann.html)
+
+All of the above are, of course, free.
+For Windows: the package includes compiled binaries of the gripd.dll Pd object
+ and the gripd.exe GUI executeable.
+For Linux: stand-alone binary packages are available for x86 the architecture
+ with either OSS or ALSA MIDI support.
+
+
+-Installation-
+
+Windows:
+ 1) Unzip contents of gripd-*.zip to .\pd\gripd\
+ 2) Put gripd.dll where Pd can find it
+ To compile from source
+ 1) In .\pd\gripd\src:
+ a) edit makefile
+ b) run: nmake gripd_nt
+ 2) gripd.exe is included, but to recompile run:
+ python gripdSetup.py py2exe -w -O2 --icon icon.pic
+
+Linux:
+ 1) Ungzip/untar contents of gripd-*.tar.gz to ./pd/gripd/
+ 2) Put gripd.pd_linux where Pd can find it
+ To compile from source:
+ 2) In ./pd/gripd/src
+ a) edit makefile
+ b) run: make gripd_linux
+ 3) to build a stand-alone binary executable of the GrIPD GUI run:
+ python -OO Build.py gripd.spec (Build.py is part of Installer v5b4)
+
+Be sure to have gripd.dll or gripd.pd_linux in your Pd path
+
+-Using GrIPD-
+To use GrIPD, launch Pd with the -lib gripd command line
+argument, and put the gripd Pd object on your patch; it's scope will be
+global throughout all canvases. Then send it an "open <optional
+filename>" message to launch the GUI (gripd.exe or gripd.py).
+You can also send a "open_locked <filename>" message which will open the
+GUI in locked mode. This will prevent any changes from being made to
+the GUI itself.
+
+You may need to set the path to gripd.py or gripd.exe by sending a
+"set_path <path>" message to the gripd Pd object. For Windows users not using
+gripd.exe, you may also have to set the path to python.exe by sending a
+"set_python_path <path>" message.
+
+You may also send a "connect" message to set the gripd Pd object to wait for
+an incomming connection and launch gripd.exe or gripd.py separately.
+
+If the path supplied to either an "open" message or a "set_path" message
+is relative (i.e. begins with ./ or ../) they will be considered relative
+to the directory containing the Pd executable file (pd.exe for Windows and
+pd for Linux). This keeps behavior consistent no matter where Pd is launched
+from.
+
+If the GUI is launched from PD, When the GUI window is closed you can re-open
+it by sending the gripd Pd object a "show" message. You can also hide it by
+sending the gripd Pd object a "hide" message.
+
+The GrIPD GUI itself has two modes: "Performance Mode" and "Edit
+Mode". In "Edit Mode" you can add and remove controls using the
+"Edit" menu, move them around by selecting them and dragging them by
+their tag with the mouse or use the arrow keys (note: ctrl+<arrow key>
+will move controls a greater distance). You can edit a controls
+properties by either selecting "Edit" from the "Edit" menu or
+right-clicking the control's tab. In "Performance Mode" the controls
+properties are locked and when activated (e.g. clicked, slid, checked,
+etc.) they will send a message via their send symbol. Conversely,
+they will receive messages sent within the Pd patch using their
+receive symbol. Look at gripd.pd and gripdExamples.pd.
+
+GrIPD can forward MIDI input to Pd from up to two devices. To enable MIDI
+function, select "Enable MIDI" from the "Configure" menu. GrIPD will send
+note information via the "midi<n>note" symbol where <n> is either 0 or 1.
+It will also send controller information via "midi<n>ctl" and program change
+information via "midi<n>pgm".
+
+GrIPD also allows for the use of up to two joysticks. To enable joystick
+function, select "Enable Joystick" from the "Configure" menu. Joystick
+axis and button information are sent to Pd with the send symbols
+"joy<n>axis<m>" and "joy<n>button<m>" where <n> is 0 or 1 and ,<m> is
+0,1,... for the number of axes and buttons your joystick supports. For
+example, to read from joystick 0 axis 0, put a "r joy0axis0" object in your
+Pd patch. Axes will send integers in a range that will depend on your
+joystick, and buttons will send 1 when depressed and 0 when released.
+
+GrIPD will also catch keystrokes and send the ASCII value to Pd while in
+performance mode via a "keystroke" send symbol. Simply put a "r keystroke"
+object in your Pd patch.
+
+Note about duplicating radio buttons:
+When creating radio buttons, the first button created in a group is the
+group marker. Duplicating any of the buttons in a group other than the
+group marker button will add a button of the last group created.
+Duplicating the group marker button will start a new group.
+
+Note about image paths:
+When a path to an image is relative (i.e. begins with ./ or ../), it is
+considered relative to the .gpd file containing the image. If no file
+has been opened or saved, the path is considered relative to the directory
+containing the gripd executable file (gripd.exe for Windows and gripd.py
+for Linux). It is therefore recommended that all images used in a GUI be
+placed in a directory directly lower than the directory containing the .gpd
+file. For example if your .gpd file is in c:\pd-guis put all images in
+c:\pd-guis\images. This will make distributing GUIs much simpler.
+
+Note about MIDI and joystick input:
+If problems occur due to MIDI or joystick input, you can disable them by
+editing gripd.opt
+
+-New in 0.1.1
+Added graph control
+Added openpanel and savepanel
+added MIDI and joystick activity blinking
+Fixed zombie bug
+Fixed multiple opens bug
+Fixed checkbox and radio buttons bug
+Fixed rectangle redrawing problem
+Fixed selecting inside rectangle problem
+
+-Contact-
+Drop me a line at jsarlo@ucsd.edu
diff --git a/connect.xpm b/connect.xpm
new file mode 100644
index 0000000..34f282c
--- /dev/null
+++ b/connect.xpm
@@ -0,0 +1,27 @@
+/* XPM */
+static char * connect_xpm[] = {
+"21 16 8 1",
+" c None",
+". c #000000",
+"+ c #00FF04",
+"@ c #BFBFBF",
+"# c #FEFEFE",
+"$ c #00FEFE",
+"% c #FF0000",
+"& c #0000FE",
+" .. ........ ",
+" .+. .@@@@@@@@.",
+" .....++. .@......@.",
+" .+++++++..@.##$$.@.",
+" .+...++. .@.#%&#.@.",
+" .+. .+. .@.$#%#.@.",
+" .+. .. .@......@.",
+" ........ .@@@@@@@@.",
+".@@@@@@@@. ........ ",
+".@......@. .. .+. ",
+".@.#&$$.@. .+. .+. ",
+".@.#%&#.@. .++...+. ",
+".@.$###.@..+++++++. ",
+".@......@. .++..... ",
+".@@@@@@@@. .+. ",
+" ........ .. "};
diff --git a/connectX.xpm b/connectX.xpm
new file mode 100644
index 0000000..fd4f27b
--- /dev/null
+++ b/connectX.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char * connectX_xpm[] = {
+"21 16 5 1",
+" c None",
+". c #000000",
+"+ c #BFBFBF",
+"@ c #FF0000",
+"# c #3F3F3F",
+" ........ ",
+" .. .++++++++.",
+" ....@@. .+......+.",
+" .@@@@@. .+.####.+.",
+" .@..@@. .+.####.+.",
+" .@. .. .+.####.+.",
+" .@. .+......+.",
+" ........ .++++++++.",
+".++++++++. ........ ",
+".+......+. .@. ",
+".+.####.+. .. .@. ",
+".+.####.+. .@@..@. ",
+".+.####.+. .@@@@@. ",
+".+......+. .@@.... ",
+".++++++++. .. ",
+" ........ "};
diff --git a/examples/clickme.jpg b/examples/clickme.jpg
new file mode 100644
index 0000000..50419c3
--- /dev/null
+++ b/examples/clickme.jpg
Binary files differ
diff --git a/examples/fmlogo.gif b/examples/fmlogo.gif
new file mode 100644
index 0000000..9fe5503
--- /dev/null
+++ b/examples/fmlogo.gif
Binary files differ
diff --git a/examples/fmsynth.gpd b/examples/fmsynth.gpd
new file mode 100644
index 0000000..e6b25b4
--- /dev/null
+++ b/examples/fmsynth.gpd
@@ -0,0 +1,442 @@
+328
+467
+#c0c0c0
+localhost
+32781|1|2|5|10|0|1|FM Synth|0|0|0|0|1|5|0
+4
+
+16
+57
+294
+259
+srectangle0
+rrectangle0
+#c0c0c0
+#000080
+22
+74
+93
+90
+0
+Arial
+!END-CONTROL
+5
+Carrier Freq
+38
+105
+67
+20
+stext0
+rtext0
+#c0c0c0
+#000000
+12
+74
+90
+90
+0
+Arial
+!END-CONTROL
+2
+100
+34
+124
+24
+139
+carrier
+rslider0
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Sans Serif
+100
+5000
+1
+!END-CONTROL
+5
+Mod Freq
+141
+105
+59
+20
+stext0
+rtext0
+#c0c0c0
+#000000
+12
+74
+90
+90
+0
+Arial
+!END-CONTROL
+2
+0
+140
+124
+24
+139
+mod
+rslider0
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Sans Serif
+0
+500
+1
+!END-CONTROL
+5
+Index
+235
+105
+52
+20
+stext0
+rtext0
+#c0c0c0
+#000000
+12
+74
+90
+90
+0
+Arial
+!END-CONTROL
+2
+0
+243
+124
+24
+139
+index
+rslider0
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Sans Serif
+0
+1000
+1
+!END-CONTROL
+5
+Amplitude:
+34
+340
+73
+20
+stext2
+rtext2
+#c0c0c0
+#000000
+12
+74
+90
+90
+0
+Arial
+!END-CONTROL
+3
+0
+35
+364
+140
+24
+amp
+rslider1
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Sans Serif
+0
+100
+1
+!END-CONTROL
+14
+./fmlogo.gif
+77
+5
+180
+48
+simage3
+rimage3
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+14
+./scale.gif
+58
+124
+23
+139
+simage7
+rimage7
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+14
+./scale.gif
+164
+124
+23
+139
+simage7
+rimage7
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+14
+./scale.gif
+268
+124
+23
+139
+simage7
+rimage7
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+14
+./scale2.gif
+36
+389
+139
+23
+simage48
+rimage48
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+4
+
+16
+309
+294
+124
+srectangle10
+rrectangle10
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+9
+100
+36
+267
+34
+20
+stextbox0
+carrier
+#d6dcf8
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+9
+0
+142
+267
+34
+20
+stextbox0
+mod
+#d6dcf8
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+9
+0
+245
+267
+34
+20
+stextbox0
+index
+#d6dcf8
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+9
+0
+113
+337
+34
+20
+stextbox0
+amp
+#d6dcf8
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+14
+./screw.gif
+3
+2
+19
+19
+simage5
+rimage5
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+14
+./screw.gif
+305
+2
+19
+19
+simage5
+rimage5
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+14
+./screw.gif
+305
+438
+19
+19
+simage5
+rimage5
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+14
+./screw.gif
+3
+438
+19
+19
+simage5
+rimage5
+#c0c0c0
+#000000
+8
+74
+90
+90
+0
+MS Shell Dlg
+!END-CONTROL
+1
+Mute
+216
+381
+81
+35
+mute
+rtoggle0
+#c0c0c0
+#000000
+14
+74
+90
+90
+0
+Arial
+!END-CONTROL
+1
+On/Off
+216
+333
+81
+35
+onoff
+rtoggle0
+#c0c0c0
+#000000
+14
+74
+90
+90
+0
+Arial
+!END-CONTROL
diff --git a/examples/gripd.gpd b/examples/gripd.gpd
new file mode 100644
index 0000000..4aa7645
--- /dev/null
+++ b/examples/gripd.gpd
@@ -0,0 +1,380 @@
+493
+433
+#c3c3c3
+localhost
+3490|/dev/js0|/dev/js1|5|10|1|1|GrIPD|0|0|0|0|1|5|1
+4
+rectangle0
+15
+5
+462
+358
+srectangle0
+rrectangle0
+#828282
+#303030
+12
+74
+90
+90
+0
+
+!END-CONTROL
+0
+button0
+37
+37
+80
+22
+sbutton0
+rbutton0
+#828282
+#303030
+12
+74
+90
+90
+0
+
+!END-CONTROL
+1
+toggle0
+59
+75
+80
+22
+stoggle0
+rtoggle0
+#828282
+#303030
+12
+74
+90
+90
+0
+
+!END-CONTROL
+2
+100
+271
+31
+30
+80
+sslider0
+rslider0
+#828282
+#303030
+12
+74
+90
+90
+0
+
+0
+100
+1
+!END-CONTROL
+3
+0
+276
+110
+80
+30
+sslider1
+rslider1
+#828282
+#303030
+12
+74
+90
+90
+0
+
+0
+100
+1
+!END-CONTROL
+6
+0
+33
+225
+30
+80
+sgauge0
+rgauge0
+#a2a2a2
+#303030
+12
+74
+90
+90
+0
+
+0
+100
+0
+!END-CONTROL
+7
+0
+34
+313
+80
+30
+sgauge1
+rgauge1
+#a2a2a2
+#303030
+12
+74
+90
+90
+0
+
+0
+100
+0
+!END-CONTROL
+8
+checkbox0
+109
+232
+85
+24
+scheckbox0
+rcheckbox0
+#828282
+#303030
+12
+74
+90
+90
+0
+
+!END-CONTROL
+5
+text0
+167
+34
+79
+14
+stext0
+rtext0
+#828282
+#303030
+12
+74
+90
+90
+0
+
+!END-CONTROL
+10
+0
+96
+113
+15
+26
+sspinbutton0
+rspinbutton0
+#c3c3c3
+#000000
+12
+74
+90
+90
+0
+
+0
+100
+0
+!END-CONTROL
+9
+
+41
+183
+80
+22
+stextbox0
+rtextbox0
+#ffffff
+#000000
+12
+74
+90
+90
+0
+
+!END-CONTROL
+5
+<- "Enter" to send
+118
+185
+120
+15
+stext1
+rtext1
+#c3c3c3
+#000000
+12
+74
+90
+90
+0
+
+!END-CONTROL
+11
+
+265
+155
+100
+100
+smousearea0
+rmousearea0
+#9a9a9a
+#000000
+12
+74
+90
+90
+0
+
+!END-CONTROL
+5
+<- Left click and
+363
+170
+96
+19
+stext2
+rtext2
+#c3c3c3
+#000000
+12
+74
+90
+90
+0
+
+!END-CONTROL
+5
+drag to track
+380
+185
+80
+16
+stext4
+rtext4
+#c3c3c3
+#000000
+12
+74
+90
+90
+0
+
+!END-CONTROL
+5
+mouse position
+384
+200
+83
+22
+stext5
+rtext5
+#c3c3c3
+#000000
+12
+74
+90
+90
+0
+
+!END-CONTROL
+13
+radiobutton0
+164
+87
+93
+24
+sradiobutton0
+rradiobutton0
+#c3c3c3
+#000000
+12
+74
+90
+90
+0
+
+!END-CONTROL
+12
+radiobutton1
+164
+112
+93
+24
+sradiobutton1
+rradiobutton1
+#c3c3c3
+#000000
+12
+74
+90
+90
+0
+
+!END-CONTROL
+12
+radiobutton2
+164
+137
+93
+24
+sradiobutton2
+rradiobutton2
+#c3c3c3
+#000000
+12
+74
+90
+90
+0
+
+!END-CONTROL
+14
+./clickme.jpg
+178
+276
+192
+71
+simage0
+rimage0
+#dddddd
+#000000
+12
+74
+90
+90
+0
+
+!END-CONTROL
+15
+
+366
+26
+100
+100
+sgraph0
+rgraph0
+#000000
+#00ff00
+12
+74
+90
+90
+0
+
+-1.0
+1.0
+[100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+!END-CONTROL
diff --git a/examples/gripd.pd b/examples/gripd.pd
new file mode 100644
index 0000000..42c75ed
--- /dev/null
+++ b/examples/gripd.pd
@@ -0,0 +1,73 @@
+#N canvas 420 51 695 867 10;
+#X obj 22 747 gripd;
+#X msg 23 40 connect;
+#X msg 38 75 disconnect;
+#X msg 117 445 poll_send 5;
+#X msg 124 470 poll_receive 5;
+#X msg 126 501 set_path ../gripd;
+#X msg 89 631 set_python_path c:/program files/python;
+#X text 369 661 "c:/program files/python" by default.;
+#X text 372 678 Linux: Does nothing.;
+#X text 229 471 Time in ms to poll for info from GUI.;
+#X text 199 446 Time in ms to poll for sending info to GUI.;
+#X text 62 747 Takes one optional argument to specify a port.;
+#X text 82 15 all backslashes must be "/".;
+#X text 19 2 Windows: For paths \, spaces are ok \, but;
+#X text 120 67 Set gripd object to stop waiting for a connection.;
+#X text 121 80 Also closes gripd GUI opened by "open <filename>".;
+#X text 86 34 Set gripd object to wait for a connection (Not needed
+with "open" message.);
+#X floatatom 22 802 5 0 0 0 - - -;
+#X msg 105 376 lock;
+#X msg 115 407 unlock;
+#X msg 49 112 open ../gripd/examples/gripd.gpd;
+#X msg 52 219 open_locked ../gripd/examples/gripd.gpd;
+#X text 144 376 Set GUI to lock mode;
+#X text 164 407 Set GUI to normal (editable) mode;
+#X text 283 168 Relative paths are relative to the directory;
+#X text 283 180 containing PD executable.;
+#X text 255 568 Relative paths are relative to the directory;
+#X text 254 583 containing PD executable.;
+#X text 68 803 left outlet: 1 on connect \, 0 on disconnect;
+#X floatatom 52 780 5 0 0 0 - - -;
+#X text 96 781 right outlet: 1 when shown \, 0 when hidden;
+#X msg 59 248 show;
+#X msg 68 276 hide;
+#X text 96 249 show GUI window when hidden;
+#X text 106 275 hide GUI window when shown;
+#X text 372 645 Normally not needed (used for gripd.py);
+#X text 371 629 Windows: Path to directory containing python.exe.;
+#X text 283 108 Open gripd GUI and optional .gpd file \, and connect.
+;
+#X text 330 219 Open gripd GUI in locked mode;
+#X text 348 135 If it fails tries gripd.py via python.exe.;
+#X text 284 121 Windows: first tries to execute gripd.exe.;
+#X text 255 503 Path to directory containing gripd executable;
+#X text 255 519 "../gripd" by default;
+#X text 254 535 Windows: sets path to file gripd.exe (and gripd.py).
+;
+#X text 255 552 Linux: sets path to file gripd (symlink to gripd.py).
+;
+#X text 284 155 Linux: executes file gripd;
+#X msg 79 309 openpanel;
+#X msg 89 340 savepanel;
+#X text 156 340 open a save file dialog and send file to savepanel
+receive symbol;
+#X text 152 303 open an open file dialog and send file to openpanel
+receive symbol;
+#X connect 0 0 17 0;
+#X connect 0 1 29 0;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X connect 5 0 0 0;
+#X connect 6 0 0 0;
+#X connect 18 0 0 0;
+#X connect 19 0 0 0;
+#X connect 20 0 0 0;
+#X connect 21 0 0 0;
+#X connect 31 0 0 0;
+#X connect 32 0 0 0;
+#X connect 46 0 0 0;
+#X connect 47 0 0 0;
diff --git a/examples/gripdExamples.pd b/examples/gripdExamples.pd
new file mode 100644
index 0000000..950cfa3
--- /dev/null
+++ b/examples/gripdExamples.pd
@@ -0,0 +1,247 @@
+#N canvas 249 58 823 654 10;
+#X obj 19 198 r sbutton0;
+#X obj 19 177 s rbutton0;
+#X obj 138 176 s rtoggle0;
+#X obj 138 197 r stoggle0;
+#X msg 205 151 bang;
+#X msg 243 151 New label;
+#X msg 19 154 New label;
+#X msg 170 151 1;
+#X msg 138 151 0;
+#X obj 23 278 s rslider0;
+#X obj 23 299 r sslider0;
+#X floatatom 23 257 4 0 0 0 - - -;
+#X floatatom 23 320 4 0 0 0 - - -;
+#X floatatom 110 257 4 0 0 0 - - -;
+#X floatatom 110 320 4 0 0 0 - - -;
+#X obj 110 278 s rslider1;
+#X obj 110 299 r sslider1;
+#X floatatom 215 257 4 0 0 0 - - -;
+#X floatatom 215 299 4 0 0 0 - - -;
+#X obj 215 278 s rgauge0;
+#X obj 215 320 s rgauge1;
+#X obj 293 283 s rtext0;
+#X msg 334 262 New label;
+#X floatatom 25 361 4 0 0 0 - - -;
+#X floatatom 25 424 4 0 0 0 - - -;
+#X obj 25 382 s rspinbutton0;
+#X obj 25 403 r sspinbutton0;
+#X floatatom 152 360 4 0 0 0 - - -;
+#X obj 152 381 s rtextbox0;
+#X msg 194 360 New text;
+#X obj 152 403 r stextbox0;
+#X floatatom 286 262 4 0 0 0 - - -;
+#X obj 378 356 r smousearea0;
+#X obj 324 406 change;
+#X obj 375 405 change;
+#X floatatom 324 427 4 0 0 0 - - -;
+#X floatatom 375 426 4 0 0 0 - - -;
+#X floatatom 697 45 7 0 0 0 - - -;
+#X floatatom 698 83 5 0 0 0 - - -;
+#X obj 17 480 r sradiobutton0;
+#X obj 137 501 s rradiobutton0;
+#X msg 137 480 bang;
+#X msg 137 522 bang;
+#X msg 137 564 bang;
+#X obj 137 597 s rradiobutton2;
+#X obj 137 543 s rradiobutton1;
+#X obj 17 522 r sradiobutton1;
+#X obj 17 566 r sradiobutton2;
+#X obj 698 62 r joy0button0;
+#X floatatom 21 131 5 0 0 0 - - -;
+#X obj 697 24 r joy0axis0;
+#X obj 588 23 r keystroke;
+#X obj 616 519 s rimage0;
+#X msg 628 495 ./clickme.jpg;
+#X text 615 558 relative to directory;
+#X text 615 576 containing .gpd file;
+#X msg 616 472 ./poof.jpg;
+#X text 615 594 Must use ./ or ../ to;
+#X text 615 612 specify a relative path;
+#X text 252 6 <- click here to open GUI;
+#X text 615 539 Relative image paths are;
+#X text 256 45 relative to directory;
+#X text 256 81 Must use ./ or ../ to;
+#X text 256 99 specify a relative path;
+#X text 256 26 Relative paths are;
+#X text 255 62 containing PD executable;
+#X obj 378 377 unpack f f f f;
+#X floatatom 426 405 4 0 0 0 - - -;
+#X floatatom 503 405 4 0 0 0 - - -;
+#X text 324 442 x \, y position;
+#X text 426 421 0 - left;
+#X text 426 432 1 - middle;
+#X text 426 443 2 - right;
+#X text 504 421 1 - down;
+#X text 504 432 0 - up;
+#X floatatom 76 110 5 0 0 0 - - -;
+#X obj 588 45 unpack;
+#X floatatom 588 72 7 0 0 0 - - -;
+#X floatatom 644 72 5 0 0 0 - - -;
+#X msg 39 29 show;
+#X msg 76 29 hide;
+#X obj 532 225 r midi0note;
+#X obj 532 250 unpack f f f;
+#X floatatom 532 275 5 0 0 0 - - -;
+#X floatatom 575 275 5 0 0 0 - - -;
+#X floatatom 618 275 5 0 0 0 - - -;
+#X floatatom 659 274 5 0 0 0 - - -;
+#X floatatom 702 274 5 0 0 0 - - -;
+#X obj 659 224 r midi0ctl;
+#X floatatom 533 200 5 0 0 0 - - -;
+#X floatatom 576 200 5 0 0 0 - - -;
+#X obj 533 175 unpack;
+#X obj 533 150 r midi0pgm;
+#X text 63 131 <- connection status;
+#X text 116 108 <- shown or hidden;
+#X msg 262 360 bang;
+#X text 298 361 <- clear;
+#X obj 326 536 change;
+#X obj 377 535 change;
+#X floatatom 326 557 4 0 0 0 - - -;
+#X floatatom 377 556 4 0 0 0 - - -;
+#X obj 380 507 unpack f f f f;
+#X floatatom 428 535 4 0 0 0 - - -;
+#X floatatom 505 535 4 0 0 0 - - -;
+#X text 326 572 x \, y position;
+#X text 428 551 0 - left;
+#X text 428 562 1 - middle;
+#X text 428 573 2 - right;
+#X text 506 551 1 - down;
+#X text 506 562 0 - up;
+#X obj 380 483 r simage0;
+#X msg 21 6 open ../gripd/examples/gripd.gpd;
+#X obj 659 249 unpack f f f;
+#X floatatom 742 274 5 0 0 0 - - -;
+#X msg 549 498 show;
+#X msg 576 472 hide;
+#X msg 386 151 bang;
+#X msg 436 151 New label;
+#X msg 349 151 1;
+#X msg 319 151 0;
+#X obj 319 178 s rcheckbox0;
+#X obj 319 200 r scheckbox0;
+#X msg 17 501 0;
+#X msg 17 543 1;
+#X msg 17 587 2;
+#X floatatom 17 617 5 0 0 0 - - -;
+#X obj 19 219 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 138 221 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 319 224 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X obj 631 416 s rgraph0;
+#X floatatom 631 343 5 0 0 0 - - -;
+#X obj 631 383 pack;
+#X floatatom 674 343 5 0 0 0 - - -;
+#X floatatom 682 390 5 0 0 0 - - -;
+#X obj 21 86 gripd 3490;
+#X text 724 390 <- set size;
+#X obj 631 361 i;
+#X obj 674 364 t b f;
+#X obj 547 344 r sgraph0;
+#X obj 547 367 unpack;
+#X floatatom 547 392 5 0 0 0 - - -;
+#X floatatom 587 392 5 0 0 0 - - -;
+#X msg 124 33 openpanel;
+#X msg 124 57 savepanel;
+#X text 629 325 set data: index \, value;
+#X obj 152 425 print textbox;
+#X obj 456 71 r openpanel;
+#X obj 456 98 print openpanel;
+#X obj 458 21 r savepanel;
+#X obj 458 48 print savepanel;
+#X msg 453 263 New label;
+#X floatatom 405 263 4 0 0 0 - - -;
+#X obj 412 284 s rrectangle0;
+#X connect 0 0 126 0;
+#X connect 3 0 127 0;
+#X connect 4 0 2 0;
+#X connect 5 0 2 0;
+#X connect 6 0 1 0;
+#X connect 7 0 2 0;
+#X connect 8 0 2 0;
+#X connect 10 0 12 0;
+#X connect 11 0 9 0;
+#X connect 13 0 15 0;
+#X connect 16 0 14 0;
+#X connect 17 0 19 0;
+#X connect 18 0 20 0;
+#X connect 22 0 21 0;
+#X connect 23 0 25 0;
+#X connect 26 0 24 0;
+#X connect 27 0 28 0;
+#X connect 29 0 28 0;
+#X connect 30 0 145 0;
+#X connect 31 0 21 0;
+#X connect 32 0 66 0;
+#X connect 33 0 35 0;
+#X connect 34 0 36 0;
+#X connect 39 0 122 0;
+#X connect 41 0 40 0;
+#X connect 42 0 45 0;
+#X connect 43 0 44 0;
+#X connect 46 0 123 0;
+#X connect 47 0 124 0;
+#X connect 48 0 38 0;
+#X connect 50 0 37 0;
+#X connect 51 0 76 0;
+#X connect 53 0 52 0;
+#X connect 56 0 52 0;
+#X connect 66 0 33 0;
+#X connect 66 1 34 0;
+#X connect 66 2 67 0;
+#X connect 66 3 68 0;
+#X connect 76 0 77 0;
+#X connect 76 1 78 0;
+#X connect 79 0 134 0;
+#X connect 80 0 134 0;
+#X connect 81 0 82 0;
+#X connect 82 0 83 0;
+#X connect 82 1 84 0;
+#X connect 82 2 85 0;
+#X connect 88 0 112 0;
+#X connect 91 0 89 0;
+#X connect 91 1 90 0;
+#X connect 92 0 91 0;
+#X connect 95 0 28 0;
+#X connect 97 0 99 0;
+#X connect 98 0 100 0;
+#X connect 101 0 97 0;
+#X connect 101 1 98 0;
+#X connect 101 2 102 0;
+#X connect 101 3 103 0;
+#X connect 110 0 101 0;
+#X connect 111 0 134 0;
+#X connect 112 0 86 0;
+#X connect 112 1 87 0;
+#X connect 112 2 113 0;
+#X connect 114 0 52 0;
+#X connect 115 0 52 0;
+#X connect 116 0 120 0;
+#X connect 117 0 120 0;
+#X connect 118 0 120 0;
+#X connect 119 0 120 0;
+#X connect 121 0 128 0;
+#X connect 122 0 125 0;
+#X connect 123 0 125 0;
+#X connect 124 0 125 0;
+#X connect 130 0 136 0;
+#X connect 131 0 129 0;
+#X connect 132 0 137 0;
+#X connect 133 0 129 0;
+#X connect 134 0 49 0;
+#X connect 134 1 75 0;
+#X connect 136 0 131 0;
+#X connect 137 0 136 0;
+#X connect 137 1 131 1;
+#X connect 138 0 139 0;
+#X connect 139 0 140 0;
+#X connect 139 1 141 0;
+#X connect 142 0 134 0;
+#X connect 143 0 134 0;
+#X connect 146 0 147 0;
+#X connect 148 0 149 0;
+#X connect 150 0 152 0;
+#X connect 151 0 152 0;
diff --git a/examples/gripdFM.pd b/examples/gripdFM.pd
new file mode 100644
index 0000000..28cccf6
--- /dev/null
+++ b/examples/gripdFM.pd
@@ -0,0 +1,135 @@
+#N canvas 660 45 549 445 10;
+#X obj 202 183 *~;
+#X floatatom 202 126 0 0 0 0 - - -;
+#X obj 267 161 line~;
+#X floatatom 114 146 0 0 0 0 - - -;
+#X obj 114 268 cos~;
+#X obj 114 216 +~;
+#X floatatom 143 316 0 0 0 0 - - -;
+#N canvas 159 26 495 270 output 0;
+#X obj 338 160 t b;
+#X obj 338 110 f;
+#X obj 338 60 inlet;
+#X text 344 29 mute;
+#X obj 338 185 f;
+#X msg 425 178 0;
+#X msg 338 85 bang;
+#X obj 338 135 moses 1;
+#X obj 425 153 t b f;
+#X obj 397 117 moses 1;
+#X obj 83 148 dbtorms;
+#X obj 397 92 r master-lvl;
+#X obj 83 42 r master-lvl;
+#X obj 338 210 s master-lvl;
+#X obj 22 182 inlet~;
+#X obj 199 41 inlet;
+#X text 199 18 level;
+#X obj 199 100 s master-lvl;
+#X msg 96 65 set \$1;
+#X obj 96 89 outlet;
+#X msg 214 64 \; pd dsp 1;
+#X obj 83 194 line~;
+#X obj 22 212 *~;
+#X obj 22 241 dac~;
+#X obj 83 171 pack 0 50;
+#X text 20 159 audio;
+#X text 93 110 show level;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 6 0;
+#X connect 4 0 13 0;
+#X connect 5 0 13 0;
+#X connect 6 0 1 0;
+#X connect 7 0 0 0;
+#X connect 7 1 8 0;
+#X connect 8 0 5 0;
+#X connect 9 1 4 1;
+#X connect 10 0 24 0;
+#X connect 11 0 1 1;
+#X connect 11 0 9 0;
+#X connect 12 0 10 0;
+#X connect 12 0 18 0;
+#X connect 14 0 22 0;
+#X connect 15 0 17 0;
+#X connect 15 0 20 0;
+#X connect 18 0 19 0;
+#X connect 21 0 22 1;
+#X connect 22 0 23 0;
+#X connect 22 0 23 1;
+#X connect 24 0 21 0;
+#X restore 114 344 pd output;
+#X msg 172 316 MUTE;
+#X text 213 316 <-- output amplitude;
+#X msg 229 262 bang;
+#X text 266 263 <-- click to graph;
+#X obj 114 173 phasor~ 0;
+#X obj 202 151 osc~ 0;
+#X text 33 8 PHASE MODULATION ("FM") USING TWO OSCILLATORS;
+#X obj 229 286 tabwrite~ fm-output;
+#X obj 267 135 pack 0 50;
+#X floatatom 267 82 0 0 0 0 - - -;
+#X obj 267 109 / 100;
+#X text 263 50 modulation index;
+#X text 263 65 in hundredths;
+#X text 111 103 carrier;
+#X text 110 121 frequency;
+#X text 187 102 frequency;
+#X text 188 85 modulation;
+#X text 310 160 <-- signal with smoothed;
+#X text 312 176 modulation index to avoid clicks;
+#X text 188 345 <-- as in previous patch;
+#X text 199 205 amplitude-controlled modulation;
+#X text 200 222 oscillator output;
+#X text 37 158 carrier;
+#X text 37 173 phase -->;
+#X text 18 201 phase;
+#X text 17 216 modulation-->;
+#X text 14 252 output;
+#X text 15 268 waveform -->;
+#X obj 51 81 r carrier;
+#X obj 148 65 r mod;
+#X obj 207 30 r index;
+#X obj 129 291 r amp;
+#X obj 172 245 r mute;
+#X msg 438 85 \; pd dsp \$1;
+#X obj 438 52 r onoff;
+#X obj 27 402 gripd;
+#X text 329 377 <-- Click;
+#X text 341 402 open GUI;
+#X text 347 389 here to;
+#N canvas 132 85 450 293 array 0;
+#N canvas 0 0 450 300 graph1 0;
+#X array fm-output 100 float 0;
+#X coords 0 1 99 -1 200 140 1;
+#X restore 100 20 graph;
+#X restore 417 256 pd array;
+#X msg 27 374 open_locked ../gripd/examples/fmsynth.gpd;
+#X msg 67 402 show;
+#X msg 100 402 unlock;
+#X msg 150 402 lock;
+#X connect 0 0 5 1;
+#X connect 1 0 13 0;
+#X connect 2 0 0 1;
+#X connect 3 0 12 0;
+#X connect 4 0 15 0;
+#X connect 4 0 7 0;
+#X connect 5 0 4 0;
+#X connect 6 0 7 1;
+#X connect 7 0 6 0;
+#X connect 8 0 7 2;
+#X connect 10 0 15 0;
+#X connect 12 0 5 0;
+#X connect 13 0 0 0;
+#X connect 16 0 2 0;
+#X connect 17 0 18 0;
+#X connect 18 0 16 0;
+#X connect 36 0 3 0;
+#X connect 37 0 1 0;
+#X connect 38 0 17 0;
+#X connect 39 0 6 0;
+#X connect 40 0 8 0;
+#X connect 42 0 41 0;
+#X connect 48 0 43 0;
+#X connect 49 0 43 0;
+#X connect 50 0 43 0;
+#X connect 51 0 43 0;
diff --git a/examples/poof.jpg b/examples/poof.jpg
new file mode 100644
index 0000000..d15a262
--- /dev/null
+++ b/examples/poof.jpg
Binary files differ
diff --git a/examples/scale.gif b/examples/scale.gif
new file mode 100644
index 0000000..61c6def
--- /dev/null
+++ b/examples/scale.gif
Binary files differ
diff --git a/examples/scale2.gif b/examples/scale2.gif
new file mode 100644
index 0000000..95d1e95
--- /dev/null
+++ b/examples/scale2.gif
Binary files differ
diff --git a/examples/screw.gif b/examples/screw.gif
new file mode 100644
index 0000000..1ebd9ae
--- /dev/null
+++ b/examples/screw.gif
Binary files differ
diff --git a/gripd b/gripd
new file mode 100755
index 0000000..3e9fb38
--- /dev/null
+++ b/gripd
@@ -0,0 +1,42 @@
+#!/usr/bin/python -OO
+
+## GrIPD v0.1.1 - Graphical Interface for Pure Data
+## Copyright (C) 2003 Joseph A. Sarlo
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License
+## as published by the Free Software Foundation; either version 2
+## of the License, or (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## jsarlo@ucsd.edu
+
+from wxPython.wx import *
+from gripdMain import *
+import sys
+import signal
+import os
+
+def signalHandler(sigNum, frame):
+ print 'Caught signal', sigNum
+ try:
+ app.frame.eClose(wxEvent())
+ except:
+ app.ExitMainLoop()
+if (os.name == "posix"):
+ signal.signal(signal.SIGQUIT, signalHandler)
+ signal.signal(signal.SIGINT, signalHandler)
+ signal.signal(signal.SIGTERM, signalHandler)
+app = mainApp(sys.argv)
+app.MainLoop()
+
+
+
diff --git a/gripd.opt b/gripd.opt
new file mode 100644
index 0000000..411fd79
--- /dev/null
+++ b/gripd.opt
@@ -0,0 +1,2 @@
+joystick = TRUE
+midi = TRUE
diff --git a/gripd.py b/gripd.py
new file mode 100644
index 0000000..beb6047
--- /dev/null
+++ b/gripd.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python -OO
+
+## GrIPD v0.1.1 - Graphical Interface for Pure Data
+## Copyright (C) 2003 Joseph A. Sarlo
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License
+## as published by the Free Software Foundation; either version 2
+## of the License, or (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## jsarlo@ucsd.edu
+
+from wxPython.wx import *
+from gripdMain import *
+import sys
+import signal
+import os
+
+def signalHandler(sigNum, frame):
+ print 'Caught signal', sigNum
+ try:
+ app.frame.eClose(wxEvent())
+ except:
+ app.ExitMainLoop()
+if (os.name == "posix"):
+ signal.signal(signal.SIGQUIT, signalHandler)
+ signal.signal(signal.SIGINT, signalHandler)
+ signal.signal(signal.SIGTERM, signalHandler)
+app = mainApp(sys.argv)
+app.MainLoop()
+
+
+
+
diff --git a/gripd.spec b/gripd.spec
new file mode 100644
index 0000000..453270c
--- /dev/null
+++ b/gripd.spec
@@ -0,0 +1,16 @@
+a = Analysis(['../../support/_mountzlib.py',
+ '../../support/useUnicode.py',
+ 'src/gripd.py'],
+ pathex=[])
+pyz = PYZ(a.pure)
+exe = EXE(pyz,
+ a.scripts + [('OO','','OPTION')] + [('f','','OPTION')],
+ exclude_binaries=1,
+ name='buildgripd/gripd',
+ debug=0,
+ strip=1,
+ console=1 )
+coll = COLLECT( exe,
+ a.binaries,
+ strip=1,
+ name='distgripd')
diff --git a/gripdControls.py b/gripdControls.py
new file mode 100644
index 0000000..10ebc1e
--- /dev/null
+++ b/gripdControls.py
@@ -0,0 +1,1675 @@
+## GrIPD v0.1.1 - Graphical Interface for Pure Data
+## Copyright (C) 2003 Joseph A. Sarlo
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License
+## as published by the Free Software Foundation; either version 2
+## of the License, or (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## jsarlo@ucsd.edu
+
+from wxPython.wx import *
+from string import *
+from gripdFunctions import *
+import os
+import math
+
+MBUTTONTYPE = 0
+MTOGGLETYPE = 1
+MVSLIDERTYPE = 2
+MHSLIDERTYPE = 3
+MRECTTYPE = 4
+MTEXTTYPE = 5
+MVGAUGETYPE = 6
+MHGAUGETYPE = 7
+MCHECKBOXTYPE = 8
+MTEXTBOXTYPE = 9
+MSPINBUTTONTYPE = 10
+MMOUSEAREATYPE = 11
+MRADIOBUTTONTYPE = 12
+MRADIONEWTYPE = 13
+MIMAGETYPE = 14
+MGRAPHTYPE = 15
+PAIRSEPCHAR = chr(29)
+SYMMSGSEP = chr(31)
+DEFCONTROLID = -1
+DEFEDITPOS = (5,7)
+DEFSLIDERVALUE = 0
+DEFSLIDERMIN = 0
+DEFSLIDERMAX = 100
+DEFVSLIDERSIZE = (30, 80)
+DEFHSLIDERSIZE = (80, 30)
+DEFRECTSIZE = (200, 200)
+DEFVGAUGESIZE = (30, 80)
+DEFHGAUGESIZE = (80, 30)
+DEFGAUGEMIN = 0
+DEFGAUGEMAX = 100
+DEFTAGSIZE = 9
+RESIZETAGCOLOR = "#555555"
+DEFMOUSEAREASIZE = 100
+SETRCVRCOMMAND = "!setRcvr"
+SETARRAYCOMMAND = "!setArray"
+TEXTEDITINPUT = 0
+FONTEDITINPUT = 1
+COLOREDITINPUT = 2
+FILEEDITINPUT = 3
+DROPDOWNEDITINPUT = 4
+MAXARRAYSENDSIZE = 2000
+
+lastEditWindowPosition = (-1, -1)
+
+# Abstract class for controls (buttons, sliders, etc)
+class mControl(wxControl):
+ def __init__(self, parentApp, type, sSym, rSym, cnxtn):
+ self.editMode = False
+ self.selected = False
+ self.parentApp = parentApp
+ self.type = type
+ self.sendSymbol = sSym
+ self.receiveSymbol = rSym
+ self.connection = cnxtn
+ self.resetBackground = False
+ self.updateRSym()
+ self.clickedOn = False
+ self.grabbed = False
+ self.setEditMode(True)
+ EVT_CHAR(self, self.eChar)
+ EVT_KEY_UP(self, self.parentApp.eKeyUp)
+ EVT_KEY_DOWN(self, self.parentApp.eKeyDown)
+ def mDestroy(self):
+ if (self.editMode):
+ self.moveTag.Destroy()
+ self.BLResizeTag.Destroy()
+ self.BRResizeTag.Destroy()
+ self.TRResizeTag.Destroy()
+ self.Destroy()
+ def select(self):
+ if (not self.selected):
+ self.relocateTags()
+ self.moveTag.Show(True)
+ self.BLResizeTag.Show(True)
+ self.BRResizeTag.Show(True)
+ self.TRResizeTag.Show(True)
+ self.parentApp.selectedControlList.append(self)
+ # To keep tags above controls in Windows, repaints tags in idle time
+ # (i.e. after everything else has bee repainted)
+ self.selected = True
+ self.Connect(-1, -1, EVT_RAISE_TAGS_ID, self.eRepaintControlTags)
+ wxPostEvent(self, RaiseTagsEvent())
+ def deselect(self):
+ if (self.selected):
+ self.moveTag.Show(False)
+ self.BLResizeTag.Show(False)
+ self.BRResizeTag.Show(False)
+ self.TRResizeTag.Show(False)
+ self.parentApp.selectedControlList.remove(self)
+ self.Disconnect(-1, EVT_RAISE_TAGS_ID)
+ self.selected = False
+ def isSelected(self):
+ return self.selected
+ def grab(self):
+ if (not self.grabbed):
+ self.grabbed = True
+ self.parentApp.dragging = True
+ EVT_MOTION(self.moveTag, self.moveTag.eMove)
+ self.moveTag.lastPos = wxGetMousePosition()
+ self.moveTag.SetCursor(wxStockCursor(self.moveTag.pointerStyle))
+ self.parentApp.startMoveControls()
+ self.moveTag.CaptureMouse()
+ def ungrab(self):
+ if (self.grabbed):
+ self.grabbed = False
+ self.parentApp.dragging = False
+ self.moveTag.ReleaseMouse()
+ # this doesn't seem to actually disconnect
+ self.moveTag.Disconnect(-1, wxEVT_MOTION)
+ self.moveTag.SetCursor(wxSTANDARD_CURSOR)
+ self.parentApp.endDragMoveControls()
+ self.parentApp.mainFrame.mainPanel.Refresh()
+ self.Refresh()
+ def updateRSym(self):
+ self.connection.send(SETRCVRCOMMAND + SYMMSGSEP + \
+ self.receiveSymbol + PAIRSEPCHAR)
+ def sendMessage(self, message):
+ try:
+ self.connection.send(self.sendSymbol + SYMMSGSEP + \
+ message + PAIRSEPCHAR)
+ except:
+ pass
+ def PDAction(self, value):
+ self.SetLabel(value)
+ def relocateTags(self):
+ self.moveTag.relocate()
+ self.BLResizeTag.relocate()
+ self.BRResizeTag.relocate()
+ self.TRResizeTag.relocate()
+ def refreshTags(self):
+ self.moveTag.Show(True)
+ self.BLResizeTag.Show(True)
+ self.BRResizeTag.Show(True)
+ self.TRResizeTag.Show(True)
+ self.moveTag.Refresh()
+ self.BLResizeTag.Refresh()
+ self.BRResizeTag.Refresh()
+ self.TRResizeTag.Refresh()
+ def startMove(self):
+ self.TRResizeTag.Show(False)
+ self.BRResizeTag.Show(False)
+ self.BLResizeTag.Show(False)
+ def move(self, deltaPos):
+ if (self.editMode and self.isSelected()):
+ xPos = self.GetPosition()[0] + deltaPos[0]
+ yPos = self.GetPosition()[1] + deltaPos[1]
+ deltaPosMTX = xPos - self.GetPosition()[0]
+ deltaPosMTY = yPos - self.GetPosition()[1]
+ xMTPos = self.moveTag.GetPosition()[0] + deltaPosMTX
+ yMTPos = self.moveTag.GetPosition()[1] + deltaPosMTY
+ self.MoveXY(xPos, yPos)
+ self.moveTag.MoveXY(xMTPos, yMTPos)
+ def endMove(self):
+ self.relocateTags()
+ self.TRResizeTag.Show(True)
+ self.BRResizeTag.Show(True)
+ self.BLResizeTag.Show(True)
+ def endDragMove(self):
+ if (self.parentApp.snapToGrid):
+ self.setPosition( \
+ self.parentApp.getNearestGridPoint(self.GetPosition()))
+ self.endMove()
+ def resize(self, deltaPos):
+ if (self.editMode):
+ xSize = self.GetSize()[0] + deltaPos[0]
+ ySize = self.GetSize()[1] + deltaPos[1]
+ if (xSize > 0 and ySize > 0):
+ self.setSize((xSize, ySize))
+ def setEditMode(self, mode):
+ if (mode):
+ if (not self.editMode):
+ EVT_LEFT_DOWN(self, self.eLeftDown)
+ EVT_RIGHT_DOWN(self, self.eRightDown)
+ self.moveTag = controlEditTag(self,
+ (0,0),
+ wxBLACK,
+ wxCURSOR_CROSS)
+ self.BLResizeTag = controlResizeTag(self,
+ (1,0),
+ RESIZETAGCOLOR,
+ wxCURSOR_SIZEWE)
+ self.TRResizeTag = controlResizeTag(self,
+ (0,1),
+ RESIZETAGCOLOR,
+ wxCURSOR_SIZENS)
+ self.BRResizeTag = controlResizeTag(self,
+ (1,1),
+ RESIZETAGCOLOR,
+ wxCURSOR_SIZENWSE)
+ self.editMode = True
+ elif (self.editMode):
+ self.deselect()
+ self.moveTag.Destroy()
+ self.BLResizeTag.Destroy()
+ self.TRResizeTag.Destroy()
+ self.BRResizeTag.Destroy()
+ self.Disconnect(-1, wxEVT_LEFT_DOWN)
+ self.Disconnect(-1, wxEVT_RIGHT_DOWN)
+ self.editMode = False
+ def getEditMode(self):
+ return self.editMode
+ def setSendSymbol(self, sym):
+ self.sendSymbol = sym
+ def getSendSymbol(self):
+ return self.sendSymbol
+ def setReceiveSymbol(self, sym):
+ self.receiveSymbol = sym
+ self.updateRSym()
+ def getReceiveSymbol(self):
+ return self.receiveSymbol
+ def setConnection(self, cnxtn):
+ self.connection = cnxtn
+ def getConnection(self):
+ return self.connection
+ def getType(self):
+ return self.type
+ def setPosition(self, pos):
+ self.MoveXY(pos[0], pos[1])
+ self.relocateTags()
+ def setSize(self, size):
+ self.SetSize(size)
+ if (self.selected):
+ self.relocateTags()
+ # catch GTK bug
+ def GetBackgroundColour(self):
+ color = wxControl.GetBackgroundColour(self)
+ if (not color.Ok()):
+ color = wxBLACK
+ return color
+ def editCallback(self, editValues):
+ try:
+ self.setPosition((atoi(editValues[0]), atoi(editValues[1])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Position",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ try:
+ self.setSize(wxSize(atoi(editValues[2]), atoi(editValues[3])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Size",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ self.setSendSymbol(editValues[4])
+ self.setReceiveSymbol(editValues[5])
+ self.SetLabel(editValues[6])
+ self.SetForegroundColour(editValues[7])
+ self.SetBackgroundColour(editValues[8])
+ self.SetFont(editValues[9])
+ def eEdit(self, event):
+ editor = controlEditor(self)
+ editor.addEditItem("X Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[0])
+ editor.addEditItem("Y Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[1])
+ editor.addEditItem("Width:",
+ TEXTEDITINPUT,
+ self.GetSize()[0])
+ editor.addEditItem("Height:",
+ TEXTEDITINPUT,
+ self.GetSize()[1])
+ editor.addEditItem("S Symbol:",
+ TEXTEDITINPUT,
+ self.getSendSymbol())
+ editor.addEditItem("R Symbol:",
+ TEXTEDITINPUT,
+ self.getReceiveSymbol())
+ editor.addEditItem("Label:",
+ TEXTEDITINPUT,
+ self.GetLabel())
+ editor.addEditItem("F Color:",
+ COLOREDITINPUT,
+ self.GetForegroundColour())
+ editor.addEditItem("B Color:",
+ COLOREDITINPUT,
+ self.GetBackgroundColour())
+ editor.addEditItem("Font:",
+ FONTEDITINPUT,
+ self.GetFont())
+ editor.edit()
+ def eChar(self, event):
+ self.parentApp.eChar(event)
+ def eLeftDown(self, event):
+ if (self.editMode):
+ if (event.ControlDown()):
+ if (self.isSelected()):
+ self.deselect()
+ else:
+ self.select()
+ else:
+ self.parentApp.deselectOthers(self.GetId())
+ self.select()
+ else:
+ event.Skip()
+ def eRightDown(self, event):
+ if (self.editMode):
+ self.parentApp.deselectOthers(self.GetId())
+ self.select()
+ self.eEdit(event)
+ else:
+ event.Skip()
+ def eRepaintControlTags(self, event):
+ self.refreshTags()
+
+# Class for little box user grabs to move/edit control
+class controlEditTag(wxPanel):
+ def __init__(self, parentControl, position, color, pointerStyle):
+ wxPanel.__init__(self,
+ parentControl.parentApp.mainFrame.mainPanel,
+ -1, (0,0),
+ (DEFTAGSIZE, DEFTAGSIZE), 0)
+ self.SetBackgroundColour(color)
+ self.parentControl = parentControl
+ self.pointerStyle = pointerStyle
+ self.leftDownOnTag = False
+ self.position = position
+ EVT_CHAR(self, self.parentControl.parentApp.eChar)
+ EVT_KEY_UP(self, self.parentControl.parentApp.eKeyUp)
+ EVT_KEY_DOWN(self, self.parentControl.parentApp.eKeyDown)
+ EVT_LEFT_DOWN(self, self.eLeftDown)
+ EVT_LEFT_UP(self, self.eRelease)
+ EVT_RIGHT_DOWN(self, self.eRightDown)
+ EVT_ENTER_WINDOW(self, self.eEnter)
+ EVT_LEAVE_WINDOW(self, self.eLeave)
+ self.Show(False)
+ def relocate(self):
+ nuPos = [0,0]
+ parentPos = self.parentControl.GetPosition()
+ parentSize = self.parentControl.GetSize()
+ if (self.position[0]):
+ nuPos[0] = parentPos[0] + parentSize[0]
+ else:
+ nuPos[0] = parentPos[0] - DEFTAGSIZE
+ if (self.position[1]):
+ nuPos[1] = parentPos[1] + parentSize[1]
+ else:
+ nuPos[1] = parentPos[1] - DEFTAGSIZE
+ self.MoveXY(nuPos[0], nuPos[1])
+ def eLeftDown(self, event):
+ self.leftDownOnTag = True
+ if (self.parentControl.grabbed):
+ self.parentControl.ungrab()
+ self.parentControl.deselect()
+ self.parentControl.parentApp.deselectOthers(-1)
+ else:
+ self.parentControl.grab()
+ def eRightDown(self, event):
+ if (not self.parentControl.grabbed):
+ self.parentControl.eEdit(event)
+ def eMove(self, event):
+ if (self.parentControl.grabbed):
+ self.newPos = wxGetMousePosition()
+ deltaPos = (self.newPos[0] - self.lastPos[0],
+ self.newPos[1] - self.lastPos[1])
+ self.lastPos = self.newPos
+ self.parentControl.parentApp.moveSelectedControls(deltaPos)
+ def eRelease(self, event):
+ self.leftDownOnTag = False
+ self.parentControl.ungrab()
+ def eEnter(self, event):
+ self.SetCursor(wxStockCursor(self.pointerStyle))
+ def eLeave(self, event):
+ self.SetCursor(wxSTANDARD_CURSOR)
+# Class for little box user grabs to resize control
+class controlResizeTag(controlEditTag):
+ def eLeftDown(self, event):
+ EVT_MOTION(self, self.eMove)
+ self.leftDownOnTag = True
+ self.lastPos = wxGetMousePosition()
+ self.SetCursor(wxStockCursor(self.pointerStyle))
+ self.CaptureMouse()
+ def eMove(self, event):
+ if (event.LeftIsDown() and self.leftDownOnTag):
+ self.newPos = wxGetMousePosition()
+ deltaPos = ((self.newPos[0] - self.lastPos[0]) * self.position[0],
+ (self.newPos[1] - self.lastPos[1]) * self.position[1])
+ self.lastPos = self.newPos
+ self.parentControl.parentApp.resizeSelectedControls(deltaPos)
+ def eRelease(self, event):
+ self.ReleaseMouse()
+ self.Disconnect(-1, wxEVT_MOTION)
+ self.SetCursor(wxSTANDARD_CURSOR)
+ self.leftDownOnTag = False
+ self.parentControl.parentApp.mainFrame.mainPanel.Refresh()
+
+# Class for regular buttons
+class mButton(mControl, wxButton):
+ def __init__(self, parentApp, type, id, text, pos, sSym, rSym, conn):
+ wxButton.__init__(self, parentApp.mainFrame.mainPanel,
+ id, text, pos)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ EVT_BUTTON(parentApp.mainFrame.mainPanel,
+ self.GetId(), self.eClicked)
+ def eClicked(self, event):
+ if (not self.editMode):
+ self.sendMessage("bang")
+
+# Class for toggle buttons
+# Problem with grabbing clicks with EVT_*_DOWN mouse events
+# in GTK on toggle button, seems to be a wxWindows thing
+class mToggle(mButton, wxToggleButton, wxButton):
+ def __init__(self, parentApp, type, id, text, pos, sSym, rSym, conn):
+ wxToggleButton.__init__(self, parentApp.mainFrame.mainPanel,
+ id, text, pos)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ EVT_TOGGLEBUTTON(parentApp.mainFrame.mainPanel,
+ self.GetId(), self.eClicked)
+ def toggle(self):
+ self.SetValue(1 - self.GetValue())
+ def PDAction(self, value):
+ try:
+ num = atof(value)
+ if (num == 0):
+ self.SetValue(0)
+ else:
+ self.SetValue(1)
+ except:
+ if (value == "bang"):
+ self.toggle()
+ else:
+ self.SetLabel(value)
+ def eClicked(self, event):
+ # checking edit mode due to above-mentioned problem
+ # checking for ctrl key (308)
+ if (self.editMode):
+ try:
+ self.parentApp.keysDown.index(308)
+ if (self.selected):
+ self.deselect()
+ else:
+ self.select()
+ except:
+ self.parentApp.deselectOthers(-1)
+ self.select()
+ else:
+ self.sendMessage(repr(event.IsChecked()))
+
+# Class for sliders
+# Screwyness since wxSliders have a maximum at down position.
+# No way to change as far as I can tell.
+class mSlider(mControl, wxSlider):
+ def __init__(self, parentApp, type, id, label,
+ pos, style, sSym, rSym, conn):
+ if (style & wxSL_HORIZONTAL):
+ sSize = DEFHSLIDERSIZE
+ if (style & wxSL_VERTICAL):
+ sSize = DEFVSLIDERSIZE
+ if (isinstance(label, list)):
+ try:
+ value = atoi(label[0])
+ except:
+ value = 0
+ min = label[1]
+ max = label[2]
+ dir = label[3]
+ else:
+ try:
+ value = atoi(label)
+ except:
+ value = 0
+ min = DEFSLIDERMIN
+ max = DEFSLIDERMAX
+ dir = 1
+ wxSlider.__init__(self, parentApp.mainFrame.mainPanel,
+ id, value, min, max, pos, sSize, style)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ EVT_COMMAND_SCROLL(parentApp, self.GetId(), self.eScrolled)
+ self.lastValue = value
+ self.setDirection(dir)
+ self.resetBackground = True
+ self.setSliderValue(value)
+ def PDAction(self, value):
+ try:
+ num = atof(value)
+ self.setSliderValue(num)
+ except:
+ pass
+ def setDirection(self, val):
+ if (val == 0):
+ self.direction = 0
+ else:
+ self.direction = 1
+ def getDirection(self):
+ return self.direction
+ def getSliderValue(self):
+ direction = self.direction
+ styleFlag = self.GetWindowStyleFlag()
+ if (((direction) and (styleFlag & wxSL_VERTICAL)) \
+ or ((not direction) and (styleFlag & wxSL_HORIZONTAL))):
+ value = self.GetMax() - self.GetValue() + self.GetMin()
+ else:
+ value = self.GetValue()
+ return value
+ def setSliderValue(self, num):
+ if (((self.direction == 1) and (self.GetWindowStyleFlag() \
+ & wxSL_VERTICAL)) \
+ or ((self.direction == 0) \
+ and (self.GetWindowStyleFlag() \
+ & wxSL_HORIZONTAL))):
+ value = self.GetMax() - num + self.GetMin()
+ else:
+ value = num
+ self.SetValue(value)
+ def GetLabel(self):
+ return repr(self.getSliderValue())
+ def SetLabel(self, value):
+ try:
+ self.setSliderValue(atoi(value))
+ except:
+ pass
+ def editCallback(self, editValues):
+ try:
+ self.setPosition((atoi(editValues[0]), atoi(editValues[1])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Position",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ try:
+ self.setSize(wxSize(atoi(editValues[2]), atoi(editValues[3])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Size",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ self.setSendSymbol(editValues[4])
+ self.setReceiveSymbol(editValues[5])
+ self.SetForegroundColour(editValues[6])
+ self.SetBackgroundColour(editValues[7])
+ try:
+ self.SetRange(atoi(editValues[8]),
+ atoi(editValues[9]))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Range",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ if (editValues[10] == "Up"):
+ self.setDirection(1)
+ elif (editValues[10] == "Down"):
+ self.setDirection(0)
+ def eEdit(self, event):
+ editor = controlEditor(self)
+ editor.addEditItem("X Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[0])
+ editor.addEditItem("Y Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[1])
+ editor.addEditItem("Width:",
+ TEXTEDITINPUT,
+ self.GetSize()[0])
+ editor.addEditItem("Height:",
+ TEXTEDITINPUT,
+ self.GetSize()[1])
+ editor.addEditItem("S Symbol:",
+ TEXTEDITINPUT,
+ self.getSendSymbol())
+ editor.addEditItem("R Symbol:",
+ TEXTEDITINPUT,
+ self.getReceiveSymbol())
+ editor.addEditItem("F Color:",
+ COLOREDITINPUT,
+ self.GetForegroundColour())
+ editor.addEditItem("B Color:",
+ COLOREDITINPUT,
+ self.GetBackgroundColour())
+ editor.addEditItem("Minimum:",
+ TEXTEDITINPUT,
+ self.GetMin())
+ editor.addEditItem("Maximum:",
+ TEXTEDITINPUT,
+ self.GetMax())
+ if (self.getDirection() == 1):
+ ddValues = ["Up", "Down"]
+ else:
+ ddValues = ["Down", "Up"]
+ editor.addEditItem("Direction:",
+ DROPDOWNEDITINPUT,
+ ddValues)
+ editor.edit()
+ def eScrolled(self, event):
+ if (not self.editMode):
+ value = self.getSliderValue()
+ if (self.lastValue != value):
+ self.lastValue = value
+ self.sendMessage(repr(value))
+
+#class for `decorative' rectangle
+class mRectangle(mControl, wxStaticBox):
+ def __init__(self, parentApp, type, id, text, pos, sSym, rSym, conn):
+ wxStaticBox.__init__(self, parentApp.mainFrame.mainPanel,
+ id, text, pos, DEFRECTSIZE)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ self.resetBackground = True
+ def SetValue(self, value):
+ self.SetLabel(value)
+ def eLeftDown(self, event):
+ if (self.editMode):
+ if (event.GetPosition()[0] < 20 or \
+ event.GetPosition()[1] < 20 or \
+ event.GetPosition()[0] > self.GetSize()[0] - 20 or\
+ event.GetPosition()[1] > self.GetSize()[1] - 20):
+ if (event.ControlDown()):
+ if (self.isSelected()):
+ self.deselect()
+ else:
+ self.select()
+ else:
+ self.parentApp.deselectOthers(self.GetId())
+ self.select()
+ else:
+ self.parentApp.eLeftDown(event)
+ else:
+ event.Skip()
+
+
+# Class for `decorative' text
+class mText(mControl, wxStaticText):
+ def __init__(self, parentApp, type, id, text, pos, sSym, rSym, conn):
+ wxStaticText.__init__(self, parentApp.mainFrame.mainPanel,
+ id, text, pos, wxDefaultSize,
+ wxALIGN_CENTRE | wxST_NO_AUTORESIZE)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ self.resetBackground = True
+ def SetValue(self, value):
+ self.SetLabel(value)
+ self.Refresh()
+
+#Class for gauges
+class mGauge(wxGauge, mSlider):
+ def __init__(self, parentApp, type, id, label, pos,
+ style, sSym, rSym, conn):
+ if (style & wxGA_HORIZONTAL):
+ size = DEFHGAUGESIZE
+ else:
+ size = DEFVGAUGESIZE
+ if (isinstance(label, list)):
+ try:
+ value = atoi(label[0])
+ except:
+ value = 0
+ max = label[2]
+ else:
+ try:
+ value = atoi(label)
+ except:
+ value = 0
+ max = DEFSLIDERMAX
+ wxGauge.__init__(self, parentApp.mainFrame.mainPanel,
+ id, max, pos, size, style | wxGA_SMOOTH)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ try:
+ self.SetValue(value)
+ except:
+ pass
+ def GetMin(self):
+ return 0
+ def GetMax(self):
+ return self.GetRange()
+ def SetRange(self, min, max):
+ wxGauge.SetRange(self, max)
+ def getDirection(self):
+ return 0
+ def setDirection(self, x):
+ pass
+ def GetLabel(self):
+ return repr(self.GetValue())
+ def SetLabel(self, value):
+ try:
+ self.SetValue(atoi(value))
+ except:
+ pass
+ def PDAction(self, value):
+ try:
+ num = atof(value)
+ if (num > self.GetMax()):
+ num = self.GetMax()
+ if (num < 0):
+ num = 0
+ self.SetValue(num)
+ except:
+ self.SetLabel(value)
+ def editCallback(self, editValues):
+ try:
+ self.setPosition((atoi(editValues[0]), atoi(editValues[1])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Position",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ try:
+ self.setSize(wxSize(atoi(editValues[2]), atoi(editValues[3])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Size",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ self.setSendSymbol(editValues[4])
+ self.setReceiveSymbol(editValues[5])
+ try:
+ self.SetRange(0,
+ atoi(editValues[6]))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Maximum",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ self.SetForegroundColour(editValues[7])
+ self.SetBackgroundColour(editValues[8])
+ def eEdit(self, event):
+ editor = controlEditor(self)
+ editor.addEditItem("X Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[0])
+ editor.addEditItem("Y Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[1])
+ editor.addEditItem("Width:",
+ TEXTEDITINPUT,
+ self.GetSize()[0])
+ editor.addEditItem("Height:",
+ TEXTEDITINPUT,
+ self.GetSize()[1])
+ editor.addEditItem("S Symbol:",
+ TEXTEDITINPUT,
+ self.getSendSymbol())
+ editor.addEditItem("R Symbol:",
+ TEXTEDITINPUT,
+ self.getReceiveSymbol())
+ editor.addEditItem("Maximum:",
+ TEXTEDITINPUT,
+ self.GetMax())
+ editor.addEditItem("F Color:",
+ COLOREDITINPUT,
+ self.GetForegroundColour())
+ editor.addEditItem("B Color:",
+ COLOREDITINPUT,
+ self.GetBackgroundColour())
+ editor.edit()
+
+# Class for checkboxes
+class mCheckBox(wxCheckBox, mToggle):
+ def __init__(self, parentApp, type, id, text, pos, sSym, rSym, conn):
+ wxCheckBox.__init__(self, parentApp.mainFrame.mainPanel,
+ id, text, pos)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ self.resetBackground = True
+ EVT_CHECKBOX(parentApp.mainFrame.mainPanel,
+ self.GetId(), self.eClicked)
+
+# Class for radio buttons
+class mRadioButton(wxRadioButton, mToggle):
+ def __init__(self, parentApp, type, id, text,
+ pos, sSym, rSym, style, conn):
+ wxRadioButton.__init__(self, parentApp.mainFrame.mainPanel,
+ id, text, pos, wxDefaultSize, style)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ self.resetBackground = True
+ EVT_RADIOBUTTON(parentApp.mainFrame.mainPanel,
+ self.GetId(), self.eClicked)
+ self.SetValue(False)
+ def eClicked(self, event):
+ if (not self.editMode and (self.GetValue() > 0)):
+ self.sendMessage("bang")
+
+# Class for textboxes
+class mTextBox(mControl, wxTextCtrl):
+ def __init__(self, parentApp, type, id, label, pos, sSym, rSym, conn):
+ wxTextCtrl.__init__(self, parentApp.mainFrame.mainPanel,
+ id, "", pos, wxDefaultSize,
+ wxTE_PROCESS_ENTER)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ self.SetValue(label)
+ EVT_TEXT_ENTER(parentApp.mainFrame.mainPanel, self.GetId(), self.eEnter)
+ def PDAction(self, value):
+ if (value == "bang"):
+ self.SetValue("")
+ else:
+ self.SetValue(value)
+ def GetLabel(self):
+ return self.GetValue()
+ def SetLabel(self, value):
+ self.SetValue(value)
+ def eEnter(self, event):
+ value = self.GetValue()
+ if (not self.editMode):
+ self.sendMessage(value)
+
+# Class for spin buttons
+class mSpinButton(wxSpinButton, mSlider):
+ def __init__(self, parentApp, type, id, label, pos, sSym, rSym, conn):
+ wxSpinButton.__init__(self, parentApp.mainFrame.mainPanel,
+ id, pos, wxDefaultSize,
+ wxSP_VERTICAL)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ try:
+ self.SetValue(atoi(label))
+ except:
+ pass
+ EVT_SPIN(parentApp.mainFrame.mainPanel, self.GetId(), self.eSpin)
+ def getDirection(self):
+ return 0
+ def setDirection(self, x):
+ pass
+ def PDAction(self, value):
+ try:
+ num = atof(value)
+ if (num > self.GetMax()):
+ num = self.GetMax()
+ if (num < 0):
+ num = 0
+ self.SetValue(num)
+ except:
+ self.SetLabel(value)
+ def GetLabel(self):
+ return repr(self.GetValue())
+ def SetLabel(self, value):
+ try:
+ self.SetValue(atoi(value))
+ except:
+ pass
+ def eSpin(self, event):
+ value = repr(self.GetValue())
+ if (not self.editMode):
+ self.sendMessage(value)
+ def editCallback(self, editValues):
+ try:
+ self.setPosition((atoi(editValues[0]), atoi(editValues[1])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Position",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ try:
+ self.setSize(wxSize(atoi(editValues[2]), atoi(editValues[3])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Size",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ self.setSendSymbol(editValues[4])
+ self.setReceiveSymbol(editValues[5])
+ try:
+ self.SetRange(atoi(editValues[6]),
+ atoi(editValues[7]))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Range",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ self.SetForegroundColour(editValues[8])
+ self.SetBackgroundColour(editValues[9])
+ def eEdit(self, event):
+ editor = controlEditor(self)
+ editor.addEditItem("X Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[0])
+ editor.addEditItem("Y Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[1])
+ editor.addEditItem("Width:",
+ TEXTEDITINPUT,
+ self.GetSize()[0])
+ editor.addEditItem("Height:",
+ TEXTEDITINPUT,
+ self.GetSize()[1])
+ editor.addEditItem("S Symbol:",
+ TEXTEDITINPUT,
+ self.getSendSymbol())
+ editor.addEditItem("R Symbol:",
+ TEXTEDITINPUT,
+ self.getReceiveSymbol())
+ editor.addEditItem("Minimum:",
+ TEXTEDITINPUT,
+ self.GetMin())
+ editor.addEditItem("Maximum:",
+ TEXTEDITINPUT,
+ self.GetMax())
+ editor.addEditItem("F Color:",
+ COLOREDITINPUT,
+ self.GetForegroundColour())
+ editor.addEditItem("B Color:",
+ COLOREDITINPUT,
+ self.GetBackgroundColour())
+ editor.edit()
+
+# Class for mouse capture area
+class mMouseArea(wxPanel, mControl):
+ def __init__(self, parentApp, type, id, pos, sSym, rSym, conn):
+ wxPanel.__init__(self, parentApp.mainFrame.mainPanel, -1, pos,
+ (DEFMOUSEAREASIZE, DEFMOUSEAREASIZE), wxBORDER)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ self.mouseCaptured = False
+ EVT_MIDDLE_DOWN(self, self.eMiddleDown)
+ EVT_MIDDLE_UP(self, self.eMiddleUp)
+ EVT_RIGHT_UP(self, self.eRightUp)
+ def sendMouseInfo(self, xPos, yPos, buttonNum, buttonStatus):
+ xPosStr = repr(xPos)
+ yPosStr = repr(yPos)
+ if (buttonNum > -1):
+ buttonNumStr = repr(buttonNum)
+ buttonStatusStr = repr(buttonStatus)
+ self.sendMessage(xPosStr + " " + \
+ yPosStr + " " + \
+ buttonNumStr + " " + \
+ buttonStatusStr)
+ else:
+ self.sendMessage(xPosStr + " " + yPosStr)
+ def editCallback(self, editValues):
+ try:
+ self.setPosition((atoi(editValues[0]), atoi(editValues[1])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Position",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ try:
+ self.setSize(wxSize(atoi(editValues[2]), atoi(editValues[3])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Size",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ self.setSendSymbol(editValues[4])
+ self.setReceiveSymbol(editValues[5])
+ self.SetBackgroundColour(editValues[6])
+ def eEdit(self, event):
+ editor = controlEditor(self)
+ editor.addEditItem("X Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[0])
+ editor.addEditItem("Y Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[1])
+ editor.addEditItem("Width:",
+ TEXTEDITINPUT,
+ self.GetSize()[0])
+ editor.addEditItem("Height:",
+ TEXTEDITINPUT,
+ self.GetSize()[1])
+ editor.addEditItem("S Symbol:",
+ TEXTEDITINPUT,
+ self.getSendSymbol())
+ editor.addEditItem("R Symbol:",
+ TEXTEDITINPUT,
+ self.getReceiveSymbol())
+ editor.addEditItem("Color:",
+ COLOREDITINPUT,
+ self.GetBackgroundColour())
+ editor.edit()
+ def eLeftDown(self, event):
+ if (self.editMode):
+ if (event.ControlDown()):
+ if (self.isSelected()):
+ self.deselect()
+ else:
+ self.select()
+ else:
+ self.parentApp.deselectOthers(self.GetId())
+ self.select()
+ else:
+ self.sendMouseInfo(event.GetPosition()[0],
+ event.GetPosition()[1],
+ 0,
+ 1)
+ event.Skip()
+ self.eStartCapture(event)
+ def eRightDown(self, event):
+ if (self.editMode):
+ self.parentApp.deselectOthers(self.GetId())
+ self.select()
+ self.eEdit(event)
+ else:
+ self.sendMouseInfo(event.GetPosition()[0],
+ event.GetPosition()[1],
+ 2,
+ 1)
+ def eRightUp(self, event):
+ if (not self.editMode):
+ self.sendMouseInfo(event.GetPosition()[0],
+ event.GetPosition()[1],
+ 2,
+ 0)
+ def eMiddleDown(self, event):
+ if (not self.editMode):
+ self.sendMouseInfo(event.GetPosition()[0],
+ event.GetPosition()[1],
+ 1,
+ 1)
+ def eMiddleUp(self, event):
+ if (not self.editMode):
+ self.sendMouseInfo(event.GetPosition()[0],
+ event.GetPosition()[1],
+ 1,
+ 0)
+ def eStartCapture(self, event):
+ if (not self.mouseCaptured):
+ self.CaptureMouse()
+ self.mouseCaptured = True
+ EVT_LEFT_UP(self, self.eEndCapture)
+ EVT_MOTION(self, self.eCaptureMouse)
+ def eEndCapture(self, event):
+ if (self.mouseCaptured):
+ self.ReleaseMouse()
+ self.mouseCaptured = False
+ self.sendMouseInfo(event.GetPosition()[0],
+ event.GetPosition()[1],
+ 0,
+ 0)
+ self.Disconnect(-1, wxEVT_MOTION)
+ self.Disconnect(-1, wxEVT_LEFT_UP)
+ def eCaptureMouse(self, event):
+ if (event.LeftIsDown() and self.mouseCaptured):
+ self.sendMouseInfo(event.GetPosition()[0],
+ event.GetPosition()[1],
+ -1,
+ -1)
+
+class mGraph(wxPanel, mSlider):
+ def __init__(self, parentApp, type, id, label, pos, sSym, rSym, conn):
+ wxPanel.__init__(self, parentApp.mainFrame.mainPanel, -1, pos,
+ (DEFMOUSEAREASIZE, DEFMOUSEAREASIZE), wxSIMPLE_BORDER)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ self.arrayLength = 0
+ self.arrayRawData = []
+ self.arrayDrawData = []
+ self.min = -1
+ self.max = 1
+ self.mouseCaptured = False
+ if (isinstance(label, list)):
+ try:
+ value = atoi(label[0])
+ except:
+ value = 0
+ self.min = label[1]
+ self.max = label[2]
+ aData = label[3]
+ self.arrayLength = aData[0]
+ self.arrayRawData = aData[1:]
+ if (self.arrayLength == 0):
+ self.arrayLength = 100
+ for i in range(0, 100):
+ self.arrayRawData.append(0)
+ for i in range(0, self.arrayLength):
+ drawData = self.getDrawData(i, 0)
+ self.arrayDrawData.append(drawData)
+ EVT_PAINT(self, self.ePaint)
+ def GetMin(self):
+ return self.min
+ def GetMax(self):
+ return self.max
+ def getDirection(self):
+ return [self.arrayLength] + self.arrayRawData
+ def PDAction(self, value):
+ value = strip(value)
+ if (lower(value) == "bang"):
+ self.Refresh()
+ else:
+ isAnInt = False
+ try:
+ aLen = atoi(value)
+ isAnInt = True
+ except:
+ pass
+ if (isAnInt):
+ if (aLen > self.arrayLength):
+ for i in range(self.arrayLength, aLen):
+ self.arrayRawData.append(0)
+ self.arrayDrawData.append(self.getDrawData(i, 0))
+ elif (aLen < self.arrayLength):
+ del self.arrayRawData[aLen:]
+ del self.arrayDrawData[aLen:]
+ self.arrayLength = aLen
+ for i in range(0, self.arrayLength):
+ self.arrayDrawData[i] = self.getDrawData(i,
+ self.arrayRawData[i])
+ else:
+ try:
+ [aIndex, aValue] = split(value, ' ')
+ aIndex = atoi(aIndex)
+ aValue = atof(aValue)
+ if (self.arrayRawData[aIndex] != aValue and \
+ aIndex >= 0 and \
+ aIndex < self.arrayLength):
+ self.arrayRawData[aIndex] = aValue
+ self.arrayDrawData[aIndex] = self.getDrawData(aIndex,
+ aValue)
+ except:
+ pass
+ self.Refresh()
+ def getDrawData(self, index, value):
+ (xSize, ySize) = self.GetSize()
+ div = float(self.arrayLength - 1)
+ if (div != 0):
+ xScale = xSize / div
+ else:
+ xScale = 1
+ div = float(self.max - self.min)
+ if (div != 0):
+ yScale = ySize / div
+ else:
+ yScale = 1
+ yOffset = int(self.max * yScale)
+ x = int(xScale * index)
+ y = yOffset - int(yScale * value)
+ pnt = (x,y)
+ return pnt
+ def setSize(self, size):
+ self.SetSize(size)
+ if (self.selected):
+ self.relocateTags()
+ for i in range(0, len(self.arrayRawData)):
+ self.arrayDrawData[i] = self.getDrawData(i,
+ self.arrayRawData[i])
+ self.Refresh()
+ def editCallback(self, editValues):
+ try:
+ self.setPosition((atoi(editValues[0]), atoi(editValues[1])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Position",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ try:
+ self.setSize(wxSize(atoi(editValues[2]), atoi(editValues[3])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Size",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ try:
+ self.min = atof(editValues[6])
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Minimum",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ try:
+ self.max = atof(editValues[7])
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Maximum",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ self.setSendSymbol(editValues[4])
+ self.setReceiveSymbol(editValues[5])
+ self.SetBackgroundColour(editValues[8])
+ self.SetForegroundColour(editValues[9])
+ def eEdit(self, event):
+ editor = controlEditor(self)
+ editor.addEditItem("X Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[0])
+ editor.addEditItem("Y Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[1])
+ editor.addEditItem("Width:",
+ TEXTEDITINPUT,
+ self.GetSize()[0])
+ editor.addEditItem("Height:",
+ TEXTEDITINPUT,
+ self.GetSize()[1])
+ editor.addEditItem("S Symbol:",
+ TEXTEDITINPUT,
+ self.getSendSymbol())
+ editor.addEditItem("R Symbol:",
+ TEXTEDITINPUT,
+ self.getReceiveSymbol())
+ editor.addEditItem("Minumum:",
+ TEXTEDITINPUT,
+ repr(self.min))
+ editor.addEditItem("Maximum:",
+ TEXTEDITINPUT,
+ repr(self.max))
+ editor.addEditItem("B Color:",
+ COLOREDITINPUT,
+ self.GetBackgroundColour())
+ editor.addEditItem("F Color:",
+ COLOREDITINPUT,
+ self.GetForegroundColour())
+ editor.edit()
+ def ePaint(self, event):
+ event.Skip()
+ myDC = wxPaintDC(self)
+ myDC.BeginDrawing()
+ myDC.SetPen(wxPen(self.GetForegroundColour(), 1, wxSOLID))
+ myDC.SetBrush(wxBrush("#000000", wxTRANSPARENT))
+ myDC.DrawLines(self.arrayDrawData)
+ myDC.EndDrawing()
+ def eDrawMotion(self, event):
+ if (self.mouseCaptured):
+ (mouseX, mouseY) = event.GetPosition()
+ div = float(self.arrayLength - 1)
+ if (div != 0):
+ xScale = self.GetSize()[0] / div
+ else:
+ xScale = 1
+ div = float(self.max - self.min)
+ if (div != 0):
+ yScale = self.GetSize()[1] / div
+ else:
+ yScale = 1
+ yOffset = int(self.max * yScale)
+ if (xScale != 0):
+ x = int(mouseX / xScale)
+ else:
+ x = 0
+ if (yScale != 0):
+ y = self.max - (mouseY / yScale)
+ else:
+ y = 0
+ if (x >= 0 and x < self.arrayLength and \
+ y >= self.min and y <= self.max):
+ self.arrayRawData[x] = y
+ self.arrayDrawData[x] = self.getDrawData(x, y)
+ self.Refresh()
+ self.sendMessage(repr(x) + " " + repr(y))
+ def eLeftDown(self, event):
+ if (self.editMode):
+ if (event.ControlDown()):
+ if (self.isSelected()):
+ self.deselect()
+ else:
+ self.select()
+ else:
+ self.parentApp.deselectOthers(self.GetId())
+ self.select()
+ else:
+ event.Skip()
+ self.eStartCapture(event)
+ def eStartCapture(self, event):
+ if (not self.mouseCaptured):
+ self.CaptureMouse()
+ self.mouseCaptured = True
+ EVT_LEFT_UP(self, self.eEndCapture)
+ EVT_MOTION(self, self.eDrawMotion)
+ def eEndCapture(self, event):
+ if (self.mouseCaptured):
+ self.ReleaseMouse()
+ self.mouseCaptured = False
+ self.Disconnect(-1, wxEVT_MOTION)
+ self.Disconnect(-1, wxEVT_LEFT_UP)
+ def eCaptureMouse(self, event):
+ pass
+
+# Class for clickable image
+# seems to have problems capturing the mouse?
+class mImage(mMouseArea, wxStaticBitmap):
+ def __init__(self, parentApp, type, id, filepath,
+ pos, sSym, rSym, conn):
+ self.filename = filepath
+ self.image = wxImage(self.filename,
+ wxBITMAP_TYPE_ANY)
+ tempBitmap = self.image.ConvertToBitmap()
+ if (not tempBitmap.Ok()):
+ raise Exception
+ wxStaticBitmap.__init__(self, parentApp.mainFrame.mainPanel, id,
+ tempBitmap, pos, wxDefaultSize)
+ mControl.__init__(self, parentApp, type, sSym, rSym, conn)
+ self.resetBackground = True
+ self.mouseCaptured = False
+ EVT_LEFT_DOWN(self, self.eLeftDown)
+ EVT_MIDDLE_DOWN(self, self.eMiddleDown)
+ EVT_MIDDLE_UP(self, self.eMiddleUp)
+ EVT_RIGHT_UP(self, self.eRightUp)
+ def sendMouseInfo(self, xPos, yPos, buttonNum, buttonStatus):
+ xPosStr = repr(xPos)
+ yPosStr = repr(yPos)
+ if (buttonNum > -1):
+ buttonNumStr = repr(buttonNum)
+ buttonStatusStr = repr(buttonStatus)
+ self.sendMessage(xPosStr + " " + \
+ yPosStr + " " + \
+ buttonNumStr + " " + \
+ buttonStatusStr)
+ else:
+ self.sendMessage(xPosStr + " " + yPosStr)
+ def resize(self, deltaPos):
+ if (self.editMode):
+ xSize = self.GetSize()[0] + deltaPos[0]
+ ySize = self.GetSize()[1] + deltaPos[1]
+ if (xSize > 0 and ySize > 0):
+ if (xSize <= self.image.GetWidth() and
+ ySize <= self.image.GetHeight()):
+ self.setSize((xSize, ySize))
+ elif (xSize <= self.image.GetWidth()):
+ self.setSize((xSize, self.GetSize()[1]))
+ elif (ySize <= self.image.GetHeight()):
+ self.setSize((self.GetSize()[0], ySize))
+ def setSize(self, size):
+ self.SetSize(size)
+ if (self.selected):
+ self.relocateTags()
+ newImage = self.image.GetSubImage((0,0,size[0],size[1]))
+ newBitmap = newImage.ConvertToBitmap()
+ self.SetBitmap(newBitmap)
+ def setEditMode(self, mode):
+ if (mode):
+ if (not self.editMode):
+ EVT_RIGHT_DOWN(self, self.eRightDown)
+ self.moveTag = controlEditTag(self,
+ (0,0),
+ wxBLACK,
+ wxCURSOR_CROSS)
+ self.BLResizeTag = controlResizeTag(self,
+ (1,0),
+ RESIZETAGCOLOR,
+ wxCURSOR_SIZEWE)
+ self.TRResizeTag = controlResizeTag(self,
+ (0,1),
+ RESIZETAGCOLOR,
+ wxCURSOR_SIZENS)
+ self.BRResizeTag = controlResizeTag(self,
+ (1,1),
+ RESIZETAGCOLOR,
+ wxCURSOR_SIZENWSE)
+ self.editMode = True
+ else:
+ if (self.editMode):
+ self.Disconnect(-1, wxEVT_RIGHT_DOWN)
+ self.deselect()
+ self.moveTag.Destroy()
+ self.BLResizeTag.Destroy()
+ self.TRResizeTag.Destroy()
+ self.BRResizeTag.Destroy()
+ self.editMode = False
+ def Refresh(self):
+ if (self.filename != self.GetLabel()):
+ self.SetLabel(self.filename)
+ wxStaticBitmap.Refresh(self)
+ wxYield()
+ self.parentApp.mainFrame.mainPanel.Refresh()
+ def SetLabel(self, label):
+ self.filename = label
+ self.image = wxImage(self.filename,
+ wxBITMAP_TYPE_ANY)
+ tempBitmap = self.image.ConvertToBitmap()
+ self.SetBitmap(tempBitmap)
+ self.setSize((self.image.GetWidth(), self.image.GetHeight()))
+ wxStaticBitmap.Refresh(self)
+ self.parentApp.mainFrame.mainPanel.Refresh()
+ def GetLabel(self):
+ return self.filename
+ def PDAction(self, value):
+ if (value[0:4] == "hide"):
+ self.Show(False)
+ # self.parentApp.mainFrame.mainPanel.Refresh()
+ elif (value[0:4] == "show"):
+ self.Show(True)
+ # self.parentApp.mainFrame.mainPanel.Refresh()
+ elif (value[0:6] == "rotate"):
+ theta = atof(value[6:len(value)]) * math.pi / 180
+ tempImage = wxImage(self.filename,wxBITMAP_TYPE_ANY)
+ bgColor = self.parentApp.mainFrame.mainPanel.GetBackgroundColour()
+ tempImage.SetMaskColour(bgColor.Red(),
+ bgColor.Green(),
+ bgColor.Blue())
+ rotateImage = tempImage.Rotate(theta, (0,0), True)
+ bgColor = self.parentApp.mainFrame.mainPanel.GetBackgroundColour()
+ self.SetBitmap(rotateImage.ConvertToBitmap())
+ wxStaticBitmap.Refresh(self)
+ self.parentApp.mainFrame.mainPanel.Refresh()
+ else:
+ if (value[0:2] == "./" or
+ value[0:3] == "../"):
+ value = scrubPath(self.parentApp.filepath + value)
+ self.SetLabel(value)
+ def editCallback(self, editValues):
+ try:
+ self.setPosition((atoi(editValues[0]), atoi(editValues[1])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Size",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ try:
+ self.setSize(wxSize(atoi(editValues[2]), atoi(editValues[3])))
+ except:
+ dlg = wxMessageDialog(self.parentApp.mainFrame,
+ "Invalid Size",
+ "Edit Error",
+ wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ self.setSendSymbol(editValues[4])
+ self.setReceiveSymbol(editValues[5])
+ self.SetLabel(editValues[6])
+ def eEdit(self, event):
+ editor = controlEditor(self)
+ editor.addEditItem("X Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[0])
+ editor.addEditItem("Y Position:",
+ TEXTEDITINPUT,
+ self.GetPosition()[1])
+ editor.addEditItem("width:",
+ TEXTEDITINPUT,
+ self.GetSize()[0])
+ editor.addEditItem("Height:",
+ TEXTEDITINPUT,
+ self.GetSize()[1])
+ editor.addEditItem("S Symbol:",
+ TEXTEDITINPUT,
+ self.getSendSymbol())
+ editor.addEditItem("R Symbol:",
+ TEXTEDITINPUT,
+ self.getReceiveSymbol())
+ editor.addEditItem("File:",
+ FILEEDITINPUT,
+ self.GetLabel())
+ editor.edit()
+ def eStartCapture(self, event):
+ if (not self.mouseCaptured):
+ self.mouseCaptured = True
+ EVT_LEFT_UP(self, self.eEndCapture)
+ EVT_MOTION(self, self.eCaptureMouse)
+ def eEndCapture(self, event):
+ if (self.mouseCaptured):
+ self.mouseCaptured = False
+ self.sendMouseInfo(event.GetPosition()[0],
+ event.GetPosition()[1],
+ 0,
+ 0)
+ self.Disconnect(-1, wxEVT_MOTION)
+ self.Disconnect(-1, wxEVT_LEFT_UP)
+
+class editItem:
+ def __init__(self, title, dataType, value):
+ self.title = title
+ self.dataType = dataType
+ self.value = value
+ def setValue(self, value):
+ self.value = value
+
+class editSetButton(wxButton):
+ def __init__(self, parent, position, size, value):
+ wxButton.__init__(self, parent, -1, "Set", position, size)
+ self.parent = parent
+ self.value = value
+ EVT_BUTTON(parent, self.GetId(), self.eClick)
+ def GetValue(self):
+ return self.value
+
+class editSetFontButton(editSetButton):
+ def eClick(self, event):
+ self.value = getFontFromDialog(self.parent, self.value)
+
+class editSetColorButton(editSetButton):
+ def eClick(self, event):
+ self.value = getColorFromDialog(self.parent, self.value)
+
+class editSetFileButton(editSetButton):
+ def eClick(self, event):
+ tempFile = getFileFromDialog(self.parent, self.value)
+ if (tempFile):
+ self.value = tempFile
+
+class editDropdown(wxComboBox):
+ def __init__(self, parent, position, size, values):
+ wxComboBox.__init__(self,
+ parent,
+ -1,
+ values[0],
+ position,
+ size,
+ values,
+ wxCB_READONLY)
+ self.parent = parent
+
+class controlEditor:
+ def __init__(self, control):
+ self.control = control
+ self.editItems = []
+ self.valueControls = []
+ def addEditItem(self, title, dataType, value):
+ self.editItems.append(editItem(title, dataType, value))
+ def edit(self):
+ global lastEditWindowPosition
+ if (lastEditWindowPosition == (-1, -1)):
+ lastEditWindowPosition = ( \
+ self.control.parentApp.mainFrame.GetPosition()[0] + 20,
+ self.control.parentApp.mainFrame.GetPosition()[1] + 20)
+ self.editFrame = wxMiniFrame(self.control,
+ -1,
+ "Edit Control",
+ lastEditWindowPosition,
+ (100, 200),
+ wxCAPTION | wxSTAY_ON_TOP)
+ self.editFrame.editPanel = wxPanel(self.editFrame, -1, (0,0), (-1, -1))
+ labels = []
+ self.valueControls = []
+ count = 0
+ newLabel = wxStaticText(self.editFrame.editPanel,
+ -1,
+ self.editItems[0].title,
+ DEFEDITPOS)
+ labels.append(newLabel)
+ if (type(self.editItems[0].value) == type(0)):
+ value = repr(self.editItems[0].value)
+ else:
+ value = self.editItems[0].value
+ if (self.editItems[0].dataType == TEXTEDITINPUT):
+ newControl = wxTextCtrl(self.editFrame.editPanel,
+ -1,
+ value,
+ (labels[0].GetPosition()[0] \
+ + 65,
+ labels[0].GetPosition()[1] - 2),
+ (60,-1))
+ if (self.editItems[0].dataType == FONTEDITINPUT):
+ newControl = editSetFontButton(self.editFrame.editPanel,
+ (labels[0].GetPosition()[0] + 65,
+ labels[0].GetPosition()[1] - 2),
+ (60, -1),
+ self.editItems[0].value)
+ if (self.editItems[0].dataType == COLOREDITINPUT):
+ newControl = editSetColorButton(self.editFrame.editPanel,
+ (labels[0].GetPosition()[0] + 65,
+ labels[0].GetPosition()[1] - 2),
+ (60, -1),
+ self.editItems[0].value)
+ if (self.editItems[0].dataType == FILEEDITINPUT):
+ newControl = editSetFileButton(self.editFrame.editPanel,
+ (labels[0].GetPosition()[0] + 65,
+ labels[0].GetPosition()[1] - 2),
+ (60, -1),
+ self.editItems[0].value)
+ if (self.editItems[0].dataType == DROPDOWNEDITINPUT):
+ newControl = editDropdown(self.editFrame.editPanel,
+ labels[0].GetPosition()[0] + 65,
+ labels[0].GetPosition()[1] - 2,
+ (60, -1),
+ self.editItems[0].value)
+ self.valueControls.append(newControl)
+ for i in self.editItems[1:]:
+ count = count + 1
+ if (type(i.value) == type(0)):
+ value = repr(i.value)
+ else:
+ value = i.value
+ newLabel = wxStaticText(self.editFrame.editPanel,
+ -1,
+ i.title,
+ (labels[count - 1].GetPosition()[0],
+ self.valueControls[count - 1].GetPosition()[1] \
+ + self.valueControls[count - 1].GetSize()[1] + 10))
+ labels.append(newLabel)
+ if (i.dataType == TEXTEDITINPUT):
+ newControl = wxTextCtrl(self.editFrame.editPanel,
+ -1,
+ value,
+ (self.valueControls[count - 1].GetPosition()[0],
+ labels[count].GetPosition()[1] - 2),
+ self.valueControls[count - 1].GetSize())
+ if (self.editItems[count].dataType == FONTEDITINPUT):
+ newControl = editSetFontButton(self.editFrame.editPanel,
+ (self.valueControls[count - 1].GetPosition()[0],
+ labels[count].GetPosition()[1] - 2),
+ self.valueControls[count - 1].GetSize(),
+ self.editItems[count].value)
+ if (self.editItems[count].dataType == COLOREDITINPUT):
+ newControl = editSetColorButton(self.editFrame.editPanel,
+ (self.valueControls[count - 1].GetPosition()[0],
+ labels[count].GetPosition()[1] - 2),
+ self.valueControls[count - 1].GetSize(),
+ self.editItems[count].value)
+ if (self.editItems[count].dataType == FILEEDITINPUT):
+ newControl = editSetFileButton(self.editFrame.editPanel,
+ (self.valueControls[count - 1].GetPosition()[0],
+ labels[count].GetPosition()[1] - 2),
+ self.valueControls[count - 1].GetSize(),
+ self.editItems[count].value)
+ if (self.editItems[count].dataType == DROPDOWNEDITINPUT):
+ newControl = editDropdown(self.editFrame.editPanel,
+ (self.valueControls[count - 1].GetPosition()[0],
+ labels[count].GetPosition()[1] - 2),
+ self.valueControls[count - 1].GetSize(),
+ self.editItems[count].value)
+ self.valueControls.append(newControl)
+ line = wxStaticLine(self.editFrame.editPanel, -1,
+ (0, self.valueControls[-1].GetPosition()[1] \
+ + self.valueControls[-1].GetSize()[1] + 20),
+ (self.valueControls[0].GetPosition()[0] \
+ + self.valueControls[0].GetSize()[0] + 10, 1))
+ okButton = wxButton(self.editFrame.editPanel, -1, "OK",
+ (labels[0].GetPosition()[0],
+ line.GetPosition()[1] + 15),
+ (self.valueControls[0].GetPosition()[0] \
+ + self.valueControls[0].GetSize()[0], -1))
+ self.editFrame.SetSize((okButton.GetPosition()[0] + \
+ okButton.GetSize()[0] + 10,
+ okButton.GetPosition()[1] + okButton.GetSize()[1] \
+ + (okButton.GetPosition()[1] - line.GetPosition()[1]) \
+ + 20))
+ self.editFrame.editPanel.SetSize(self.editFrame.GetSize())
+ EVT_BUTTON(self.editFrame.editPanel,
+ okButton.GetId(),
+ self.eOk)
+ self.editFrame.Show(True)
+ self.editFrame.MakeModal(True)
+ def eOk(self, event):
+ global lastEditWindowPosition
+ returnValues = []
+ for i in range(0, len(self.valueControls)):
+ returnValues.append(self.valueControls[i].GetValue())
+ lastEditWindowPosition = self.editFrame.GetPosition()
+ self.editFrame.MakeModal(False)
+ self.editFrame.Destroy()
+ self.control.editCallback(returnValues)
+
diff --git a/gripdFunctions.py b/gripdFunctions.py
new file mode 100644
index 0000000..2bf0a55
--- /dev/null
+++ b/gripdFunctions.py
@@ -0,0 +1,191 @@
+## GrIPD v0.1.1 - Graphical Interface for Pure Data
+## Copyright (C) 2003 Joseph A. Sarlo
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License
+## as published by the Free Software Foundation; either version 2
+## of the License, or (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## jsarlo@ucsd.edu
+
+from wxPython.wx import *
+from string import *
+import os
+import sys
+
+VERSION = "0.1.1"
+MAXDEC = 9
+DECTOHEXOFFSET = 87
+EVT_RAISE_TAGS_ID = wxNewId()
+
+debugFile = sys.stderr
+
+def setDebugFile(filename):
+ global debugFile
+ if (filename != ""):
+ debugFile = open(filename, "w", -1)
+
+def debugLog(logString):
+ debugFile.write(logString + "\n")
+ debugFile.flush()
+
+def getColorFromDialog(parent, initColor):
+ colorData = wxColourData()
+ colorData.SetColour(initColor)
+ colorData.SetCustomColour(0, initColor)
+ colorDialog = wxColourDialog(parent, colorData)
+ colorDialog.ShowModal()
+ colorData = colorDialog.GetColourData()
+ return colorData.GetColour()
+
+def getFontFromDialog(parent, initFont):
+ fontData = wxFontData()
+ fontData.SetInitialFont(initFont)
+ fontDialog = wxFontDialog(parent, fontData)
+ fontDialog.ShowModal()
+ fontData = fontDialog.GetFontData()
+ return fontData.GetChosenFont()
+
+def getFileFromDialog(parent, initFile):
+ if (initFile == ""):
+ initFile = parent.parentApp.filepath
+ fileDialog = wxFileDialog(parent,
+ "Open file",
+ getDirectory(initFile),
+ initFile,
+ "*.*",
+ wxOPEN)
+ if (fileDialog.ShowModal() == wxID_OK):
+ return fileDialog.GetPath()
+ else:
+ return ""
+
+def colorTuple2HexString(tuple):
+ def dec2HexString(value):
+ if (value > MAXDEC):
+ return chr(value + DECTOHEXOFFSET)
+ else:
+ return repr(value)
+ hexString = ""
+ for i in range(0, 3):
+ hexString = hexString + dec2HexString(int(round(tuple[i] / 16)))
+ hexString = hexString + dec2HexString(int(round(tuple[i] \
+ - (int(tuple[i] / 16) * 16))))
+ return hexString
+
+def selectIntersect(rect1, rect2):
+ left1 = rect1[0]
+ top1 = rect1[1]
+ right1 = rect1[0] + rect1[2]
+ bottom1 = rect1[1] + rect1[3]
+ left2 = rect2[0]
+ top2 = rect2[1]
+ right2 = rect2[0] + rect2[2]
+ bottom2 = rect2[1] + rect2[3]
+ if ((left1 < left2) and (right1 > right2)
+ and (top1 < top2) and (bottom1 > bottom2)):
+ return False
+ if (((left2 > left1) and (left2 < right1))
+ or ((right2 > left1) and (right2 < right1))
+ or ((left2 < left1) and (right2 > right1))):
+ if ((top2 > top1) and (top2 < bottom1)):
+ return True
+ elif ((bottom2 >top1) and (bottom2 < bottom1)):
+ return True
+ elif ((top2 < top1) and (bottom2 > bottom1)):
+ return True
+ return False
+
+def getDirectory(path):
+ if (os.name == "posix"):
+ index = rfind(path, "/")
+ if (index > -1):
+ tempPath = path[0:index]
+ while (tempPath[len(tempPath) - 1] == "/"):
+ tempPath = tempPath[0:len(tempPath) - 1]
+ tempPath = tempPath + "/"
+ else:
+ tempPath = ""
+ else:
+ index = max(rfind(path, "\\"), rfind(path, "/"))
+ if (index > -1):
+ tempPath = path[0:index]
+ while (tempPath[len(tempPath) - 1] == "/" or
+ tempPath[len(tempPath) - 1] == "\\"):
+ tempPath = tempPath[0:len(tempPath) - 1]
+ tempPath = tempPath + "\\"
+ else:
+ tempPath = ""
+ return tempPath
+
+def replaceSlashes(path):
+ path = replace(path, "/", "\\")
+ return path
+
+def scrubPath(path):
+ if (os.name == "posix"):
+ while (find(path, "/../") > 0):
+ index = rfind(path[0:find(path, "/../")], "/")
+ path = path[0:index] + path[find(path, "/../") + 3:len(path)]
+ while (find(path, "/./") > 0):
+ index = find(path, "/./")
+ path = path[0:index] + path[index + 2:len(path)]
+ path = replace(path, "//", "/")
+ else:
+ path = replaceSlashes(path)
+ while (find(path, "\\..\\") > 0):
+ index = rfind(path[0:find(path, "\\..\\")], "\\")
+ path = path[0:index] + path[find(path, "\\..\\") + 3:len(path)]
+ while (find(path, "\\.\\") > 0):
+ index = find(path, "\\.\\")
+ path = path[0:index] + path[index + 2:len(path)]
+ path = replace(path, "\\\\", "\\")
+ return path
+
+def makeAbsolutePath(superPath, subPath):
+ if (os.name == "posix"):
+ if (find(subPath, "./") == 0 or
+ find(subPath, "../") == 0):
+ tempPath = superPath + subPath
+ elif (subPath[0] != "/"):
+ tempPath = superPath + "/" + subPath
+ else:
+ tempPath = subPath
+ else:
+ if (find(subPath, "/") >= 0):
+ subPath = replaceSlashes(subPath)
+ if (find(subPath, ".\\") == 0 or
+ find(subPath, "..\\") == 0):
+ tempPath = superPath + subPath
+ elif (subPath[1] != ":"):
+ tempPath = superPath + "\\" + subPath
+ else:
+ tempPath = subPath
+ return scrubPath(tempPath)
+
+def makeRelativePath(superPath, subPath):
+ if (os.name != "posix"):
+ superPath = lower(superPath)
+ subPath = lower(subPath)
+ if (find(subPath, superPath) == 0 and superPath != ""):
+ tempPath = "./" + subPath[len(superPath):len(subPath)]
+ else:
+ tempPath = subPath
+ return scrubPath(tempPath)
+
+
+class RaiseTagsEvent(wxPyEvent):
+ def __init__(self):
+ wxPyEvent.__init__(self)
+ self.SetEventType(EVT_RAISE_TAGS_ID)
+
+
diff --git a/gripdMain.py b/gripdMain.py
new file mode 100644
index 0000000..1e20cb5
--- /dev/null
+++ b/gripdMain.py
@@ -0,0 +1,2337 @@
+## GrIPD v0.1.1 - Graphical Interface for Pure Data
+## Copyright (C) 2003 Joseph A. Sarlo
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License
+## as published by the Free Software Foundation; either version 2
+## of the License, or (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## jsarlo@ucsd.edu
+
+from wxPython.wx import *
+from gripdControls import *
+from gripdFunctions import *
+from socket import *
+from string import *
+
+midi = 0
+joystick = 0
+DEFMAINFRAMESIZE = (600, 400)
+DEFCONTROLPOS = (20,20)
+ID_ABOUT = 100
+ID_EXIT = 101
+ID_ADD = 102
+ID_EDITMODE = 103
+ID_EDIT = 104
+ID_DELETE = 105
+ID_CONNECT = 106
+ID_OPEN = 107
+ID_SAVE = 108
+ID_OPTIONS = 109
+ID_BUTTONMENU = 110
+ID_SLIDERMENU = 111
+ID_GAUGEMENU = 112
+ID_SELECTALL = 113
+ID_NEW = 114
+ID_DUPLICATE = 115
+ID_ALIGNVERT = 116
+ID_ALIGNHORZ = 117
+ID_REFRESH = 118
+ID_BUTTON = 200
+ID_TOGGLE = 201
+ID_VSLIDER = 202
+ID_HSLIDER = 203
+ID_RECT = 204
+ID_TEXT = 205
+ID_SETOPTS = 206
+ID_DISCONNECT = 207
+ID_VGAUGE = 208
+ID_HGAUGE = 209
+ID_CHECKBOX = 210
+ID_TEXTBOX = 211
+ID_SPINBUTTON = 212
+ID_MOUSEAREA = 213
+ID_ENABLEJOY = 214
+ID_ENABLEKEY = 215
+ID_LOCKONPERF = 216
+ID_RADIOBUTTON = 217
+ID_IMAGE = 218
+ID_ALWAYSONTOP = 219
+ID_SHOWGRID = 220
+ID_SNAPTOGRID = 221
+ID_ENABLEMIDI = 222
+ID_GRAPH = 223
+COMMANDCHAR = '!'
+DEFHOST = 'localhost'
+DEFPORT = 3490
+CONNECTINTERVAL = 1000
+TIMEOUT = 20
+HIDECOMMAND = "!hide"
+SHOWCOMMAND = "!show"
+EXITCOMMAND = "!exit"
+LOCKCOMMAND = "!lock"
+UNLOCKCOMMAND = "!unlock"
+SETTITLECOMMAND = "!settitle"
+CLOSECOMMAND = "!disconnect"
+PINGCOMMAND = "!ping"
+OPENPANELCOMMAND = "!openpanel"
+SAVEPANELCOMMAND = "!savepanel"
+BEGINCONTROLMARKER = "!BEGIN-CONTROL"
+ENDCONTROLMARKER = "!END-CONTROL"
+DEFOPTIONSPOS = (5, 5)
+DUPPOSOFFSET = (10, 10)
+SMALLCHARMOVE = 1
+LARGECHARMOVE = 20
+BGCOLORDIF = 30
+DEFSOCKETTIMERTIME = 5
+DEFJOYPOLLTIME = 10
+DEFMIDIPOLLTIME = 5
+DEFMIDIDEVICE1 = 0
+DEFMIDIDEVICE2 = 1
+PAIRSEPCHAR = chr(29)
+SYMMSGSEP = chr(31)
+FILETOKENSEP = "|"
+MAXPINGCOUNT = 10
+PINGPOLLTIME = 1000
+MIDINOTEMESSAGE = "9"
+MIDICTLMESSAGE = "b"
+MIDIPGMMESSAGE = "c"
+SETARRAYSTRING = "!setArray"
+
+if (os.name == "posix"):
+ FUGEFACTOR = 1
+ DEFJOYDEVICE1 = "/dev/js0"
+ DEFJOYDEVICE2 = "/dev/js1"
+else:
+ FUGEFACTOR = 2
+ DEFJOYDEVICE1 = "1"
+ DEFJOYDEVICE2 = "2"
+
+# Main application class
+class mainApp(wxPySimpleApp):
+ def __init__(self, args):
+ self.args = args
+ wxApp.__init__(self, False)
+ try:
+ wxLog_SetLogLevel(0)
+ except:
+ pass
+ def OnInit(self):
+ global midi
+ global joystick
+ openAuto = False
+ newPort = 0
+ filename = ""
+ locked = False
+ self.path = scrubPath(getDirectory(self.args[0]))
+ setDebugFile(self.path + "/log.txt")
+ self.filepath = ""
+ if (len(self.args) > 1):
+ filename = self.args[1]
+ self.filepath = getDirectory(filename)
+ if (self.filepath == ""):
+ self.filepath = self.path
+ self.filepath = makeAbsolutePath(self.path, self.filepath)
+ if (len(self.args) > 2):
+ newPort = atoi(self.args[2])
+ if (len(self.args) > 3):
+ openAuto = atoi(self.args[3])
+ if (len(self.args) > 4):
+ locked = atoi(self.args[4])
+ self.midiAvailable = True
+ self.joystickAvailable = True
+ try:
+ optionsFile = open(self.path + "/gripd.opt", 'r', -1)
+ options = optionsFile.readlines()
+ for option in options:
+ [key, value] = split(option, '=')
+ key = strip(key)
+ value = strip(value)
+ if (lower(key) == 'midi'):
+ if (lower(value) == 'false'):
+ self.midiAvailable = False
+ if (lower(key) == 'joystick'):
+ if (lower(value) == 'false'):
+ self.joystickAvailable = False
+ except:
+ pass
+ if (self.midiAvailable):
+ import midi
+ if (self.joystickAvailable):
+ import joystick
+ wxInitAllImageHandlers()
+ if (not os.name == "posix"):
+ self.icon = wxIcon(self.path + "icon.pic", wxBITMAP_TYPE_ICO)
+ self.jsImage = wxImage(self.path + "joystick.xpm",
+ wxBITMAP_TYPE_XPM).ConvertToBitmap()
+ self.jsImageX = wxImage(self.path + "joystickX.xpm",
+ wxBITMAP_TYPE_XPM).ConvertToBitmap()
+ self.jsImageA = wxImage(self.path + "joystickA.xpm",
+ wxBITMAP_TYPE_XPM).ConvertToBitmap()
+ self.midiImage = wxImage(self.path + "midi.xpm",
+ wxBITMAP_TYPE_XPM).ConvertToBitmap()
+ self.midiImageX = wxImage(self.path + "midiX.xpm",
+ wxBITMAP_TYPE_XPM).ConvertToBitmap()
+ self.midiImageA = wxImage(self.path + "midiA.xpm",
+ wxBITMAP_TYPE_XPM).ConvertToBitmap()
+ self.connectImage = wxImage(self.path + "connect.xpm",
+ wxBITMAP_TYPE_XPM).ConvertToBitmap()
+ self.connectImageX = wxImage(self.path + "connectX.xpm",
+ wxBITMAP_TYPE_XPM).ConvertToBitmap()
+ self.editMode = False
+ # socket stuff
+ self.host = DEFHOST
+ self.port = DEFPORT
+ self.connection = nullConnection()
+ self.connected = False
+ # All controls (on mainPanel)
+ self.controlList = []
+ # Selected controls, Should speed up editing
+ # DO NOT use to loop through selected controls to deselect
+ # <control>.deselect() modifies selectedControlList
+ self.selectedControlList = []
+ # If currently using selecting with selectRect
+ self.selecting = False
+ # If currently dragging a control
+ self.dragging = False
+ # Keys currently depressed
+ self.keysDown = []
+ # If left mouse was clicked on panel
+ # not on control or tag, for selectRect
+ self.leftDownOnPanel = False
+ # If current GUI has been changed since last save
+ self.edited = False
+ # control counters (for send/receive syms)
+ self.resetControlIndecies()
+ # timer to check connection status
+ self.pTimer = pingTimer(self)
+ # set ping count
+ self.pingCount = 0
+ # timer to poll for connections
+ self.cTimer = connectionTimer(self)
+ # socket polling time
+ self.pollTime = DEFSOCKETTIMERTIME
+ # timer to poll socket for receive messages
+ self.sTimer = socketTimer(self)
+ # timer to poll joystick
+ self.joyTimer = joystickTimer(self)
+ # joystick poll time
+ self.joyPollTime = DEFJOYPOLLTIME
+ # joystick device string
+ self.joyDevice1 = DEFJOYDEVICE1
+ self.joyDevice2 = DEFJOYDEVICE2
+ # joystick device id
+ self.joyID1 = -1
+ self.joyID2 = -1
+ # joystick on
+ self.joystickEnabled = False
+ self.jsOn1 = False
+ self.jsOn2 = False
+ # timer to poll midi
+ self.midiTimer = midiTimer(self)
+ # midi poll time
+ self.midiPollTime = DEFMIDIPOLLTIME
+ # midi device numbers
+ self.midiDevice1 = DEFMIDIDEVICE1
+ self.midiDevice2 = DEFMIDIDEVICE2
+ # midi device id
+ self.midiID1 = -1
+ self.midiID2 = -1
+ # midi on
+ self.midiEnabled = False
+ self.midiOn1 = False
+ self.midiOn2 = False
+ # send keystrokes
+ self.sendKeys = True
+ # grid sized
+ self.gridSpace = 10
+ # display grid
+ self.showGrid = False
+ # snap moved controls to grid
+ self.snapToGrid = False
+ # locked or unlocked GUI
+ self.locked = locked
+ self.openAuto = openAuto
+ self.frameTitle = "GrIPD"
+ self.alwaysOnTop = False
+ self.resizable = False
+ self.mainFrame = gripdFrame(self, -1, self.frameTitle,
+ (-1, -1),
+ self.resizable, self.locked,
+ self.alwaysOnTop)
+ self.SetTopWindow(self.mainFrame)
+ # for catching keystokes
+ EVT_CHAR(self.mainFrame.mainPanel, self.eChar)
+ EVT_KEY_UP(self.mainFrame.mainPanel, self.eKeyUp)
+ EVT_KEY_DOWN(self.mainFrame.mainPanel, self.eKeyDown)
+ if (not os.name == "posix"):
+ EVT_CHAR_HOOK(self.mainFrame, self.eChar)
+ EVT_CLOSE(self.mainFrame, self.eClose)
+ EVT_SIZE(self.mainFrame, self.eSize)
+ self.mainFrame.positionIcons()
+ if ((filename != "0") and (filename != "")):
+ self.openFromDisk(filename)
+ if (newPort):
+ self.port = newPort
+ if (self.openAuto):
+ self.connect()
+ else:
+ self.mainFrame.Show(True)
+ return True
+
+## Functions ##
+
+ def createControl(self, type, tIndex, tString, filepath = ""):
+ if (self.editMode and not self.dragging):
+ indexStr = tString + repr(tIndex)
+ clientMousePos = self.mainFrame.mainPanel.ScreenToClient( \
+ wxGetMousePosition())
+ coords = (clientMousePos[0] + 4, clientMousePos[1] + 4)
+ control = self.addControl(type, indexStr, coords,
+ "s" + indexStr, "r" + indexStr, filepath)
+ control.select()
+ # I'm not sure why this is necessary
+ try:
+ wxYield()
+ except:
+ pass
+ control.grab()
+ def addControl(self, type, label, pos, sSym, rSym, filepath = ""):
+ tControl = NULL
+ if (type == MBUTTONTYPE):
+ self.buttonIndex = self.buttonIndex + 1
+ tControl = mButton(self, type, -1,
+ label, pos, sSym, rSym, self.connection)
+ if (type == MTOGGLETYPE):
+ self.toggleIndex = self.toggleIndex + 1
+ tControl = mToggle(self, type, -1,
+ label, pos, sSym, rSym, self.connection)
+ if (type == MVSLIDERTYPE):
+ self.sliderIndex = self.sliderIndex + 1
+ tControl = mSlider(self, type, -1, label, pos,
+ wxSL_VERTICAL, sSym, rSym, self.connection)
+ if (type == MHSLIDERTYPE):
+ self.sliderIndex = self.sliderIndex + 1
+ tControl = mSlider(self, type, -1, label, pos,
+ wxSL_HORIZONTAL, sSym, rSym, self.connection)
+ if (type == MRECTTYPE):
+ self.rectIndex = self.rectIndex + 1
+ tControl = mRectangle(self, type, -1,
+ label, pos, sSym, rSym, self.connection)
+ if (type == MTEXTTYPE):
+ self.textIndex = self.textIndex + 1
+ tControl = mText(self, type, -1,
+ label, pos, sSym, rSym, self.connection)
+ if (type == MVGAUGETYPE):
+ self.gaugeIndex = self.gaugeIndex + 1
+ tControl = mGauge(self, type, -1, label, pos,
+ wxGA_VERTICAL, sSym, rSym, self.connection)
+ if (type == MHGAUGETYPE):
+ self.gaugeIndex = self.gaugeIndex + 1
+ tControl = mGauge(self, type, -1, label, pos,
+ wxGA_HORIZONTAL, sSym, rSym, self.connection)
+ if (type == MCHECKBOXTYPE):
+ self.checkBoxIndex = self.checkBoxIndex + 1
+ tControl = mCheckBox(self, type, -1,
+ label, pos, sSym, rSym, self.connection)
+ if (type == MRADIOBUTTONTYPE):
+ self.radioButtonIndex = self.radioButtonIndex + 1
+ tControl = mRadioButton(self, type, -1,
+ label, pos, sSym, rSym, 0, self.connection)
+ if (type == MRADIONEWTYPE):
+ self.radioButtonIndex = self.radioButtonIndex + 1
+ tControl = mRadioButton(self, type, -1,
+ label, pos, sSym, rSym, wxRB_GROUP,
+ self.connection)
+ if (type == MTEXTBOXTYPE):
+ self.textBoxIndex = self.textBoxIndex + 1
+ tControl = mTextBox(self, type, -1, label,
+ pos, sSym, rSym, self.connection)
+ if (type == MSPINBUTTONTYPE):
+ self.spinButtonIndex = self.spinButtonIndex + 1
+ tControl = mSpinButton(self, type, -1, label,
+ pos, sSym, rSym, self.connection)
+ if (type == MMOUSEAREATYPE):
+ self.mouseAreaIndex = self.mouseAreaIndex + 1
+ tControl = mMouseArea(self, type, -1,
+ pos, sSym, rSym, self.connection)
+ if (type == MIMAGETYPE):
+ if (filepath == ""):
+ filepath = label
+ filepath = makeAbsolutePath(self.filepath, filepath)
+ self.imageIndex = self.imageIndex + 1
+ try:
+ tControl = mImage(self, type, -1,
+ filepath, pos, sSym, rSym, self.connection)
+ except:
+ tControl = NULL
+ if (type == MGRAPHTYPE):
+ self.graphIndex = self.graphIndex + 1
+ tControl = mGraph(self, type, -1, label, pos, sSym,
+ rSym, self.connection)
+ if (tControl != NULL):
+ self.controlList.append(tControl)
+ return (tControl)
+ def findControlByID(self, id):
+ for control in self.controlList:
+ if (control.GetId() == id):
+ return(control)
+ def startMoveControls(self):
+ for control in self.selectedControlList:
+ control.startMove()
+ def moveSelectedControls(self, deltaPos):
+ self.edited = True
+ for control in self.selectedControlList:
+ control.move(deltaPos)
+ def endMoveControls(self):
+ for control in self.selectedControlList:
+ control.endMove()
+ def endDragMoveControls(self):
+ for control in self.selectedControlList:
+ control.endDragMove()
+ def resizeSelectedControls(self, deltaPos):
+ self.edited = True
+ for control in self.selectedControlList:
+ control.resize(deltaPos)
+ def moveKey(self, deltaPos):
+ self.moveSelectedControls(deltaPos)
+ for control in self.selectedControlList:
+ control.endMove()
+ def alignControls(self, dir):
+ otherDir = 1 - dir
+ alignVal = 1
+ alignPos = [0, 0]
+ for control in self.selectedControlList:
+ alignVal = max(alignVal, control.GetPosition()[dir])
+ alignPos[dir] = alignVal
+ for control in self.selectedControlList:
+ alignPos[otherDir] = control.GetPosition()[otherDir]
+ control.setPosition(alignPos)
+ def deselectOthers(self, calledByID):
+ # Not using selectedControlList since we are removing from it
+ # as we cycle through the list
+ for control in self.controlList:
+ if ((control.GetId() != calledByID) and control.isSelected()):
+ control.deselect()
+ def raiseControlTags(self):
+ if (self.editMode):
+ for control in self.selectedControlList:
+ control.relocateTags()
+ control.refreshTags()
+ def traverseFocus(self, multi):
+ if ((len(self.controlList) > 0) and (self.editMode)):
+ i = -1
+ newIndex = 0
+ for control in self.controlList:
+ i = i + 1
+ if (control.isSelected()):
+ newIndex = i + 1
+ newIndex = newIndex % len(self.controlList)
+ self.controlList[newIndex].select()
+ if (not multi):
+ self.deselectOthers(self.controlList[newIndex].GetId())
+ def parseReceiveBuffer(self, receiveBuffer):
+ # remove trailing PAIRSEPCHAR
+ receiveBuffer = receiveBuffer[0:-1]
+ messagePairs = split(receiveBuffer, PAIRSEPCHAR)
+ for pair in messagePairs:
+ (symName, value) = split(pair, SYMMSGSEP)
+ if (symName[0] == COMMANDCHAR):
+ if (symName == CLOSECOMMAND):
+ self.disconnect()
+ dlg = wxMessageDialog(self.mainFrame,
+ "Connection closed by PD",
+ "Connection", wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ if (symName == EXITCOMMAND):
+ self.close()
+ elif (symName == LOCKCOMMAND):
+ self.lock()
+ elif (symName == UNLOCKCOMMAND):
+ self.unlock()
+ elif (symName == SETTITLECOMMAND):
+ self.frameTitle = value
+ self.setFrameTitle(value)
+ elif (symName == HIDECOMMAND):
+ self.mainFrame.Show(False)
+ self.connection.send(HIDECOMMAND + \
+ SYMMSGSEP + "0" + \
+ PAIRSEPCHAR)
+ elif (symName == SHOWCOMMAND):
+ self.mainFrame.Show(True)
+ self.connection.send(SHOWCOMMAND + \
+ SYMMSGSEP + "0" + \
+ PAIRSEPCHAR)
+ elif (symName == PINGCOMMAND):
+ self.pingCount = 0
+ elif (symName == OPENPANELCOMMAND):
+ self.mainFrame.openpanel()
+ elif (symName == SAVEPANELCOMMAND):
+ self.mainFrame.savepanel()
+ else:
+ for control in self.controlList:
+ if (symName == control.getReceiveSymbol()):
+ control.PDAction(value)
+ def writeControls(self, list, file):
+ for control in list:
+ file.write(repr(control.getType()) + "\n")
+ if (control.type == MIMAGETYPE):
+ file.write(makeRelativePath(self.filepath,
+ control.GetLabel()) + "\n")
+ else:
+ file.write(control.GetLabel() + "\n")
+ file.write(repr(control.GetPosition()[0]) + "\n")
+ file.write(repr(control.GetPosition()[1]) + "\n")
+ file.write(repr(control.GetSize()[0]) + "\n")
+ file.write(repr(control.GetSize()[1]) + "\n")
+ file.write(control.getSendSymbol() + "\n")
+ file.write(control.getReceiveSymbol() + "\n")
+ if (control.GetBackgroundColour().Ok()):
+ file.write("#" + colorTuple2HexString((control.\
+ GetBackgroundColour().Red(),
+ control.\
+ GetBackgroundColour().Green(),
+ control.\
+ GetBackgroundColour().Blue()))\
+ + "\n")
+ else:
+ file.write("#00000\n")
+ if (control.GetForegroundColour().Ok()):
+ file.write("#" + colorTuple2HexString((control.\
+ GetForegroundColour().Red(),
+ control.\
+ GetForegroundColour().Green(),
+ control.\
+ GetForegroundColour().Blue()))\
+ + "\n")
+ else:
+ file.write("#000000\n")
+ if (not control.GetFont().Ok()):
+ control.SetFont(wxNORMAL_FONT)
+ file.write(repr(control.GetFont().GetPointSize()) + "\n")
+ file.write(repr(control.GetFont().GetFamily()) + "\n")
+ file.write(repr(control.GetFont().GetStyle()) + "\n")
+ file.write(repr(control.GetFont().GetWeight()) + "\n")
+ file.write(repr(control.GetFont().GetUnderlined()) + "\n")
+ file.write(control.GetFont().GetFaceName() + "\n")
+ if (isinstance(control, mSlider)):
+ file.write(repr(control.GetMin()) + "\n")
+ file.write(repr(control.GetMax()) + "\n")
+ file.write(repr(control.getDirection()) + "\n")
+ file.write(ENDCONTROLMARKER + "\n")
+ def readControls(self, list):
+ newList = []
+ for i in range(0, list.count(ENDCONTROLMARKER)):
+ params = list[0:list.index(ENDCONTROLMARKER)]
+ type = atoi(params[0])
+ label = params[1]
+ pos = (atoi(params[2]), atoi(params[3]))
+ size = (atoi(params[4]), atoi(params[5]))
+ sSym = params[6]
+ rSym = params[7]
+ bColor = params[8]
+ fColor = params[9]
+ try:
+ fontSize = atoi(params[10])
+ fontFam = atoi(params[11])
+ fontStyle = atoi(params[12])
+ fontWeight = atoi(params[13])
+ fontULine = atoi(params[14])
+ fontFace = params[15]
+ except:
+ print "Font Error!!!"
+ if (type == MVSLIDERTYPE or \
+ type == MHSLIDERTYPE or \
+ type == MVGAUGETYPE or \
+ type == MHGAUGETYPE):
+ min = atoi(params[16])
+ max = atoi(params[17])
+ dir = atoi(params[18])
+ label = [label, min, max, dir]
+ if (type == MGRAPHTYPE):
+ min = atof(params[16])
+ max = atof(params[17])
+ dir = eval(params[18])
+ label = [label, min, max, dir]
+ control = self.addControl(type, label, pos, sSym, rSym)
+ control.setSize(size)
+ control.SetBackgroundColour(bColor)
+ control.SetForegroundColour(fColor)
+ font = wxFont(fontSize, fontFam, fontStyle, fontWeight,
+ fontULine, fontFace, wxFONTENCODING_SYSTEM)
+ control.SetFont(font)
+ control.setEditMode(self.editMode)
+ # +1 to include ENDCONTROLMARKER
+ del list[0:(list.index(ENDCONTROLMARKER) + 1)]
+ newList.append(control)
+ return newList
+ def connect(self):
+ if (not self.locked):
+ self.mainFrame.fileMenu.Enable(ID_DISCONNECT, True)
+ if (not self.cTimer.IsRunning()):
+ self.cTimer.timeCount = 0
+ self.cTimer.Start(CONNECTINTERVAL)
+ def disconnect(self):
+ if (self.sTimer.IsRunning()):
+ self.sTimer.Stop()
+ try:
+ self.connection.send(CLOSECOMMAND + SYMMSGSEP + \
+ "0" + PAIRSEPCHAR)
+ except:
+ pass
+ self.connection.close()
+ self.connection = nullConnection()
+ for control in self.controlList:
+ control.connection = self.connection
+ self.cTimer.Stop()
+ self.pTimer.Stop()
+ self.pingCount = 0
+ if (not self.locked):
+ self.mainFrame.fileMenu.Enable(ID_CONNECT, True)
+ self.mainFrame.fileMenu.Enable(ID_DISCONNECT, False)
+ self.mainFrame.connectIcon.SetBitmap(self.connectImageX)
+ self.connected = False
+ def saveToDisk(self, filename):
+ try:
+ if (lower(filename[len(filename) - 4:len(filename)]) != ".gpd"):
+ filename = filename + ".gpd"
+ file = open(filename, 'w', -1)
+ self.filepath = getDirectory(filename)
+ self.filepath = makeAbsolutePath(self.path, self.filepath)
+ if (self.filepath == ""):
+ self.filepath = self.path
+ file.write(repr(self.mainFrame.GetSize()[0]) + "\n")
+ file.write(repr(self.mainFrame.GetSize()[1]) + "\n")
+ file.write("#" + colorTuple2HexString((self.mainFrame.mainPanel.\
+ GetBackgroundColour().Red(),
+ self.mainFrame.mainPanel.\
+ GetBackgroundColour().Green(),
+ self.mainFrame.mainPanel.\
+ GetBackgroundColour().Blue())) + "\n")
+ file.write(self.host + "\n")
+ file.write(repr(self.port) + FILETOKENSEP +
+ self.joyDevice1 + FILETOKENSEP +
+ self.joyDevice2 + FILETOKENSEP +
+ repr(self.pollTime) + FILETOKENSEP +
+ repr(self.joyPollTime) + FILETOKENSEP +
+ repr(self.joystickEnabled) + FILETOKENSEP +
+ repr(self.sendKeys) + FILETOKENSEP +
+ self.frameTitle + FILETOKENSEP +
+ repr(self.alwaysOnTop) + FILETOKENSEP +
+ repr(self.showGrid) + FILETOKENSEP +
+ repr(self.snapToGrid) + FILETOKENSEP +
+ repr(self.midiDevice1) + FILETOKENSEP +
+ repr(self.midiDevice2) + FILETOKENSEP +
+ repr(self.midiPollTime) + FILETOKENSEP +
+ repr(self.midiEnabled) + "\n")
+ self.writeControls(self.controlList, file)
+ file.close()
+ self.edited = False
+ except Exception:
+ strerror = str(sys.exc_info()[1])
+ dlg = wxMessageDialog(self.mainFrame, "Unable to save to " + \
+ filename + ":\n\n" + strerror,
+ "File Error", wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ def openFromDisk(self, filename):
+ try:
+ file = open(filename, 'r', -1)
+ try:
+ self.filepath = getDirectory(filename)
+ self.filepath = makeAbsolutePath(self.path, self.filepath)
+ fullFileList = file.readlines()
+ for control in self.controlList:
+ control.mDestroy()
+ self.controlList = []
+ self.selectedControlList = []
+ self.resetControlIndecies()
+ # remove line endings (need Perl's chomp())
+ for i in range(0, len(fullFileList)):
+ fullFileList[i] = replace(fullFileList[i], "\n", "")
+ frameSize = (atoi(fullFileList[0]), atoi(fullFileList[1]))
+ panelColor = (fullFileList[2])
+ panelHost = (fullFileList[3])
+ otherArgs = split(fullFileList[4], FILETOKENSEP)
+ if (len(otherArgs) > 0):
+ panelPort = otherArgs[0]
+ if (len(otherArgs) > 1):
+ jDev1 = otherArgs[1]
+ else:
+ jDev1 = DEFJOYDEVICE1
+ if (len(otherArgs) > 2):
+ jDev2 = otherArgs[2]
+ else:
+ jDev2 = DEFJOYDEVICE2
+ if (len(otherArgs) > 3):
+ sockPollTime = atoi(otherArgs[3])
+ else:
+ sockPollTime = DEFSOCKETTIMERTIME
+ if (len(otherArgs) > 4):
+ joyPollTime = atoi(otherArgs[4])
+ else:
+ joyPollTime = DEFJOYPOLLTIME
+ if (len(otherArgs) > 5 and self.joystickAvailable):
+ self.joystickEnabled = atoi(otherArgs[5])
+ if (self.joystickEnabled):
+ self.startJoystick()
+ else:
+ self.stopJoystick()
+ if (not self.locked):
+ self.mainFrame.optionsMenu.Check(ID_ENABLEJOY,
+ self.joystickEnabled)
+ if (len(otherArgs) > 6):
+ self.sendKeys = atoi(otherArgs[6])
+ if (not self.locked):
+ self.mainFrame.optionsMenu.Check(ID_ENABLEKEY,
+ self.sendKeys)
+ if (len(otherArgs) > 7):
+ self.setFrameTitle(otherArgs[7])
+ if (len(otherArgs) > 8):
+ self.alwaysOnTop = atoi(otherArgs[8])
+ if (len(otherArgs) > 9):
+ self.showGrid = atoi(otherArgs[9])
+ if (len(otherArgs) > 10):
+ self.snapToGrid = atoi(otherArgs[10])
+ if (len(otherArgs) > 11):
+ self.midiDevice1 = atoi(otherArgs[11])
+ if (len(otherArgs) > 12):
+ self.midiDevice2 = atoi(otherArgs[12])
+ if (len(otherArgs) > 13):
+ self.midiPollTime = atoi(otherArgs[13])
+ if (len(otherArgs) > 14 and self.midiAvailable):
+ self.midiEnabled = atoi(otherArgs[14])
+ if (self.midiEnabled):
+ self.startMidi()
+ else:
+ self.stopMidi()
+ if (not self.locked):
+ self.mainFrame.optionsMenu.Check(ID_ENABLEMIDI,
+ self.midiEnabled)
+
+ self.mainFrame.SetSize(frameSize)
+ self.mainFrame.mainPanel.SetBackgroundColour(panelColor)
+ self.host = panelHost
+ self.port = atoi(panelPort)
+ self.joyDevice1 = jDev1
+ self.joyDevice2 = jDev2
+ self.pollTime = sockPollTime
+ self.joyPollTime = joyPollTime
+ del fullFileList[0:5]
+ self.readControls(fullFileList)
+ self.edited = False
+ self.recreateFrame()
+ self.mainFrame.mainPanel.Refresh()
+ except Exception:
+ strerror = "File is invalid"
+ #FIXME
+ strerror = str(sys.exc_info()[1])
+ dlg = wxMessageDialog(self.mainFrame, "Unable to open file " + \
+ filename + ":\n\n" + strerror,
+ "File Error", wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ except Exception:
+ strerror = str(sys.exc_info()[1])
+ dlg = wxMessageDialog(self.mainFrame, "Unable to open file " + \
+ filename + ":\n\n" + strerror,
+ "File Error", wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ self.mainFrame.positionIcons()
+ self.setEditMode(False)
+ def resetControlIndecies(self):
+ self.buttonIndex = 0
+ self.toggleIndex = 0
+ self.sliderIndex = 0
+ self.textIndex = 0
+ self.rectIndex = 0
+ self.gaugeIndex = 0
+ self.checkBoxIndex = 0
+ self.textBoxIndex = 0
+ self.spinButtonIndex = 0
+ self.mouseAreaIndex = 0
+ self.radioButtonIndex = 0
+ self.imageIndex = 0
+ self.graphIndex = 0
+ def startJoystick(self):
+ self.joystickEnabled = True
+ self.joyID1 = joystick.openDevice(self.joyDevice1)
+ self.joyID2 = joystick.openDevice(self.joyDevice2)
+ if ((self.joyID1 > -1) or (self.joyID2 > -1)):
+ self.joyTimer.Start(self.joyPollTime)
+ if (self.joyID1 == -1):
+ self.jsOn1 = False
+ if (not self.locked):
+ self.mainFrame.jsIcon1.SetBitmap(self.jsImageX)
+ else:
+ self.jsOn1 = True
+ if (not self.locked):
+ self.mainFrame.jsIcon1.SetBitmap(self.jsImage)
+ if (self.joyID2 == -1):
+ self.jsOn2 = False
+ if (not self.locked):
+ self.mainFrame.jsIcon2.SetBitmap(self.jsImageX)
+ else:
+ self.jsOn2 = True
+ if (not self.locked):
+ self.mainFrame.jsIcon2.SetBitmap(self.jsImage)
+ if (not self.locked):
+ self.mainFrame.positionIcons()
+ self.mainFrame.jsIcon1.Show(not self.locked)
+ self.mainFrame.jsIcon1.Refresh()
+ self.mainFrame.jsIcon2.Show(not self.locked)
+ self.mainFrame.jsIcon2.Refresh()
+ def stopJoystick(self):
+ self.joyTimer.Stop()
+ joystick.closeDevice(self.joyID1)
+ joystick.closeDevice(self.joyID2)
+ self.joystickEnabled = False
+ self.jsOn1 = False
+ self.jsOn2 = False
+ if (not self.locked):
+ self.mainFrame.jsIconFlasher1.Stop()
+ self.mainFrame.jsIconFlasher2.Stop()
+ self.mainFrame.positionIcons()
+ self.mainFrame.jsIcon1.Show(False)
+ self.mainFrame.jsIcon2.Show(False)
+ def showJoystickActive(self, jsNum):
+ if (self.joystickEnabled and not self.locked):
+ if (jsNum == 1):
+ self.mainFrame.jsIconFlasher1.Start(250)
+ else:
+ self.mainFrame.jsIconFlasher2.Start(250)
+ def startMidi(self):
+ self.midiEnabled = True
+ self.midiID1 = midi.openDevice(self.midiDevice1)
+ self.midiID2 = midi.openDevice(self.midiDevice2)
+ if ((self.midiID1 > -1) or (self.midiID2 > -1)):
+ self.midiTimer.Start(self.midiPollTime)
+ if (self.midiID1 == -1):
+ self.midiOn1 = False
+ if (not self.locked):
+ self.mainFrame.midiIcon1.SetBitmap(self.midiImageX)
+ else:
+ self.midiOn1 = True
+ if (not self.locked):
+ self.mainFrame.midiIcon1.SetBitmap(self.midiImage)
+ if (self.midiID2 == -1):
+ self.midiOn2 = False
+ if (not self.locked):
+ self.mainFrame.midiIcon2.SetBitmap(self.midiImageX)
+ else:
+ self.midiOn2 = True
+ if (not self.locked):
+ self.mainFrame.midiIcon2.SetBitmap(self.midiImage)
+ if (not self.locked):
+ self.mainFrame.positionIcons()
+ self.mainFrame.midiIcon1.Show(not self.locked)
+ self.mainFrame.midiIcon1.Refresh()
+ self.mainFrame.midiIcon2.Show(not self.locked)
+ self.mainFrame.midiIcon2.Refresh()
+ def stopMidi(self):
+ self.midiTimer.Stop()
+ midi.closeDevice(self.midiID1)
+ midi.closeDevice(self.midiID2)
+ self.midiEnabled = False
+ self.midiOn1 = False
+ self.midiOn2 = False
+ if (not self.locked):
+ self.mainFrame.midiIconFlasher1.Stop()
+ self.mainFrame.midiIconFlasher2.Stop()
+ self.mainFrame.positionIcons()
+ self.mainFrame.midiIcon1.Show(False)
+ self.mainFrame.midiIcon2.Show(False)
+ def showMidiActive(self, midiNum):
+ if (self.midiEnabled and not self.locked):
+ if (midiNum == 1):
+ self.mainFrame.midiIconFlasher1.Start(250)
+ else:
+ self.mainFrame.midiIconFlasher2.Start(250)
+ def sendCharDown(self, charCode):
+ self.sendChar(charCode, 1)
+ def sendCharUp(self, charCode):
+ self.sendChar(charCode, 0)
+ def sendChar(self, charCode, downOrUp):
+ if (self.sendKeys):
+ self.connection.send("keystroke" +
+ SYMMSGSEP +
+ repr(charCode) +
+ " " +
+ repr(downOrUp) +
+ PAIRSEPCHAR)
+ def lock(self):
+ if (not self.locked):
+ if (self.editMode):
+ self.setEditMode(False)
+ self.locked = True
+ self.recreateFrame()
+ def unlock(self):
+ if (self.locked):
+ self.locked = False
+ self.recreateFrame()
+ def setEditMode(self, value):
+ self.editMode = value
+ self.resizable = value
+ self.mainFrame.SetCursor(wxHOURGLASS_CURSOR)
+ self.mainFrame.mainPanel.SetCursor(wxHOURGLASS_CURSOR)
+ try:
+ wxYield()
+ except:
+ pass
+ self.recreateFrame()
+ if (value):
+ EVT_PAINT(self.mainFrame.mainPanel, self.ePaint)
+ EVT_LEFT_DOWN(self.mainFrame.mainPanel, self.eLeftDown)
+ EVT_LEFT_UP(self.mainFrame.mainPanel, self.eLeftUp)
+ EVT_RIGHT_DOWN(self.mainFrame.mainPanel, self.eRightPopUp)
+ for control in self.controlList:
+ control.setEditMode(True)
+ self.editMode = True
+ if (not self.locked):
+ self.mainFrame.editMenu.Enable(ID_ADD, True)
+ self.mainFrame.editMenu.Enable(ID_EDIT, True)
+ self.mainFrame.editMenu.Enable(ID_DELETE, True)
+ self.mainFrame.editMenu.Enable(ID_SELECTALL, True)
+ self.mainFrame.editMenu.Enable(ID_DUPLICATE, True)
+ self.mainFrame.editMenu.Enable(ID_ALIGNVERT, True)
+ self.mainFrame.editMenu.Enable(ID_ALIGNHORZ, True)
+ self.mainFrame.setEditModeText("Edit Mode")
+ self.mainFrame.positionIcons()
+ self.selectedControlList = []
+ self.edited = True
+ if (self.showGrid):
+ self.mainFrame.mainPanel.Refresh()
+ else:
+ self.mainFrame.mainPanel.Disconnect(-1, wxEVT_PAINT)
+ self.mainFrame.mainPanel.Disconnect(-1, wxEVT_LEFT_DOWN)
+ self.mainFrame.mainPanel.Disconnect(-1, wxEVT_LEFT_UP)
+ self.mainFrame.mainPanel.Disconnect(-1, wxEVT_RIGHT_DOWN)
+ for control in self.controlList:
+ control.setEditMode(False)
+ self.editMode = False
+ if (not self.locked):
+ self.mainFrame.editMenu.Enable(ID_ADD, False)
+ self.mainFrame.editMenu.Enable(ID_EDIT, False)
+ self.mainFrame.editMenu.Enable(ID_DELETE, False)
+ self.mainFrame.editMenu.Enable(ID_SELECTALL, False)
+ self.mainFrame.editMenu.Enable(ID_DUPLICATE, False)
+ self.mainFrame.editMenu.Enable(ID_ALIGNVERT, False)
+ self.mainFrame.editMenu.Enable(ID_ALIGNHORZ, False)
+ self.mainFrame.setEditModeText("Performance Mode")
+ self.mainFrame.positionIcons()
+ for control in self.controlList:
+ control.Refresh()
+ self.mainFrame.SetCursor(wxSTANDARD_CURSOR)
+ self.mainFrame.mainPanel.SetCursor(wxSTANDARD_CURSOR)
+ self.mainFrame.mainPanel.SetFocus()
+ def recreateFrame(self):
+ position = self.mainFrame.GetPosition()
+ newWindow = gripdFrame(self,
+ -1,
+ self.frameTitle,
+ position,
+ self.resizable,
+ self.locked,
+ self.alwaysOnTop)
+ shown = self.mainFrame.IsShown()
+ self.copyFrame(newWindow)
+ if (shown):
+ self.mainFrame.Show(True)
+ try:
+ wxYield()
+ except:
+ pass
+ self.setFrameTitle(self.frameTitle)
+ def copyFrame(self, newWindow):
+ newWindow.SetSize(self.mainFrame.GetSize())
+ if (not self.locked):
+ newWindow.editMenu.Check(ID_EDITMODE,
+ self.editMode)
+ newWindow.optionsMenu.Check(ID_ENABLEJOY,
+ self.joystickEnabled)
+ newWindow.optionsMenu.Check(ID_ENABLEMIDI,
+ self.midiEnabled)
+ newWindow.optionsMenu.Check(ID_ENABLEKEY,
+ self.sendKeys)
+ newWindow.positionIcons()
+ newWindow.jsIcon1.Show(self.joystickEnabled)
+ newWindow.jsIcon2.Show(self.joystickEnabled)
+ newWindow.midiIcon1.Show(self.midiEnabled)
+ newWindow.midiIcon2.Show(self.midiEnabled)
+ if (self.jsOn1 and not self.locked):
+ newWindow.jsIcon1.SetBitmap(self.jsImage)
+ elif (not self.locked):
+ newWindow.jsIcon1.SetBitmap(self.jsImageX)
+ if (self.jsOn2 and not self.locked):
+ newWindow.jsIcon2.SetBitmap(self.jsImage)
+ elif (not self.locked):
+ newWindow.jsIcon2.SetBitmap(self.jsImageX)
+ if (self.midiOn1 and not self.locked):
+ newWindow.midiIcon1.SetBitmap(self.midiImage)
+ elif (not self.locked):
+ newWindow.midiIcon1.SetBitmap(self.midiImageX)
+ if (self.midiOn2 and not self.locked):
+ newWindow.midiIcon2.SetBitmap(self.midiImage)
+ elif (not self.locked):
+ newWindow.midiIcon2.SetBitmap(self.midiImageX)
+ newWindow.mainPanel.SetBackgroundColour(\
+ self.mainFrame.mainPanel.GetBackgroundColour())
+ self.mainFrame.Destroy()
+ if (self.connected and not self.locked):
+ newWindow.fileMenu.Enable(ID_CONNECT, False)
+ newWindow.fileMenu.Enable(ID_DISCONNECT, True)
+ newWindow.connectIcon.SetBitmap(self.connectImage)
+ elif (not self.locked):
+ newWindow.fileMenu.Enable(ID_CONNECT, True)
+ newWindow.fileMenu.Enable(ID_DISCONNECT, False)
+ newWindow.connectIcon.SetBitmap(self.connectImageX)
+ self.SetTopWindow(newWindow)
+ self.mainFrame = newWindow
+ EVT_KEY_UP(self.mainFrame.mainPanel, self.eKeyUp)
+ EVT_KEY_DOWN(self.mainFrame.mainPanel, self.eKeyDown)
+ EVT_CHAR(self.mainFrame.mainPanel, self.eChar)
+ if (not os.name == "posix"):
+ EVT_CHAR_HOOK(self.mainFrame, self.eChar)
+ EVT_CLOSE(self.mainFrame, self.eClose)
+ EVT_SIZE(self.mainFrame, self.eSize)
+ list = []
+ container = duplicationContainer()
+ for control in self.controlList:
+ list.append(control)
+ self.controlList = []
+ self.writeControls(list, container)
+ container.chomp()
+ self.readControls(container.getList())
+ def setFrameTitle(self, value):
+ self.frameTitle = value
+ if (self.editMode):
+ self.mainFrame.SetTitle(value + " [ Edit ]")
+ else:
+ self.mainFrame.SetTitle(value)
+ def pingTimeout(self):
+ if (self.openAuto):
+ debugLog("timeout")
+ self.disconnect()
+ self.close()
+ else:
+ self.disconnect()
+ def getNearestGridPoint(self, point):
+ x = self.gridSpace * round((float(point[0]) / self.gridSpace))
+ y = self.gridSpace * round((float(point[1]) / self.gridSpace))
+ gridPoint = (int(x), int(y))
+ return gridPoint
+ def close(self):
+ self.openAuto = False
+ if ((self.edited) and (len(self.controlList) > 0)):
+ self.mainFrame.Show(True)
+ dlg = wxMessageDialog(self.mainFrame,
+ "Current GUI not saved. Close anyway?",
+ "GUI Not Saved", wxOK | wxCANCEL)
+ if (dlg.ShowModal() == wxID_OK):
+ dlg.Destroy()
+ self.mainFrame.Destroy()
+ try:
+ self.disconnect()
+ except:
+ pass
+ else:
+ return
+ else:
+ self.mainFrame.Show(True)
+ self.mainFrame.Destroy()
+ try:
+ self.disconnect()
+ except:
+ pass
+ if (self.joystickEnabled):
+ self.stopJoystick()
+ if (self.midiEnabled):
+ self.stopMidi()
+ self.ExitMainLoop()
+
+## Events ##
+
+ def eOpenConnection(self, event):
+ cString = "Connect to " + self.host + ":" + repr(self.port) + "\n "
+ dlg = wxMessageDialog(self.mainFrame.mainPanel, cString, "Connect",
+ wxOK | wxCANCEL)
+ if (dlg.ShowModal() == wxID_OK):
+ self.connect()
+ dlg.Destroy()
+ def eCloseConnection(self, event):
+ self.disconnect()
+ def eToggleJoystick(self, event):
+ if (not self.locked):
+ self.joystickEnabled = self.mainFrame.optionsMenu.\
+ IsChecked(ID_ENABLEJOY)
+ if (self.joystickEnabled):
+ self.startJoystick()
+ else:
+ self.stopJoystick()
+ def eToggleMidi(self, event):
+ if (not self.locked):
+ self.midiEnabled = self.mainFrame.optionsMenu.\
+ IsChecked(ID_ENABLEMIDI)
+ if (self.midiEnabled):
+ self.startMidi()
+ else:
+ self.stopMidi()
+ def eToggleKeySend(self, event):
+ if (not self.locked):
+ self.sendKeys = self.mainFrame.optionsMenu.IsChecked(ID_ENABLEKEY)
+ def eToggleAlwaysOnTop(self, event):
+ if (not self.locked and os.name != "posix"):
+ self.alwaysOnTop = self.mainFrame.optionsMenu.\
+ IsChecked(ID_ALWAYSONTOP)
+ self.recreateFrame()
+ def eToggleShowGrid(self, event):
+ self.showGrid = self.mainFrame.optionsMenu.IsChecked(ID_SHOWGRID)
+ if (not self.showGrid):
+ self.snapToGrid = False
+ if (not self.locked):
+ self.mainFrame.optionsMenu.Check(ID_SNAPTOGRID, False)
+ else:
+ if (self.editMode):
+ self.mainFrame.mainPanel.Refresh()
+ self.mainFrame.mainPanel.Refresh()
+ def eToggleSnapToGrid(self, event):
+ self.snapToGrid = self.mainFrame.optionsMenu.IsChecked(ID_SNAPTOGRID)
+ if (self.snapToGrid):
+ self.showGrid = True
+ if (not self.locked):
+ self.mainFrame.optionsMenu.Check(ID_SHOWGRID, True)
+ if (self.editMode):
+ self.mainFrame.mainPanel.Refresh()
+ def eRightPopUp(self, event):
+ if ((not self.locked) and (not self.selecting)):
+ self.mainFrame.PopupMenuXY(self.mainFrame.editMenu,
+ event.GetX(),
+ event.GetY())
+ def eLeftDown(self, event):
+ # Editing stuff (mostly for selectRect)
+ if (self.editMode):
+ EVT_MOTION(self.mainFrame.mainPanel, self.eMotion)
+ self.mouseDownPos = event.GetPosition()
+ self.mainFrame.mainPanel.CaptureMouse()
+ self.leftDownOnPanel = True
+ if (not event.m_controlDown):
+ self.deselectOthers(-1)
+ def eLeftUp(self, event):
+ if (self.editMode):
+ if (self.leftDownOnPanel):
+ self.mainFrame.mainPanel.ReleaseMouse()
+ self.mainFrame.mainPanel.Disconnect(-1, wxEVT_MOTION)
+ if (self.selecting):
+ self.selecting = False
+ for control in self.controlList:
+ if (selectIntersect(control.GetRect(),
+ self.mainFrame.selectRect)):
+ control.select()
+ elif ((not event.m_controlDown) and control.isSelected()):
+ control.deselect()
+ self.mainFrame.mainPanel.Refresh()
+ self.leftDownOnPanel = False
+ def eMotion(self, event):
+ if (event.LeftIsDown() and self.editMode and self.leftDownOnPanel):
+ self.selecting = True
+ width = abs(event.GetPosition()[0] - self.mouseDownPos[0])
+ height = abs(event.GetPosition()[1] - self.mouseDownPos[1])
+ leftBound = min(self.mouseDownPos[0], event.GetPosition()[0])
+ topBound = min(self.mouseDownPos[1], event.GetPosition()[1])
+ clearRegion = wxRegion(self.mainFrame.selectRect[0],
+ self.mainFrame.selectRect[1],
+ self.mainFrame.selectRect[2],
+ self.mainFrame.selectRect[3])
+ self.mainFrame.selectRect = [leftBound, topBound,
+ width, height]
+ clearRegion.Union(leftBound, topBound, width, height)
+ self.mainFrame.mainPanel.Refresh(False, clearRegion.GetBox())
+ def ePaint(self, event):
+ event.Skip()
+ myDC = wxPaintDC(self.mainFrame.mainPanel)
+ myDC.BeginDrawing()
+ if (self.editMode):
+ if (self.showGrid):
+ self.mainFrame.drawGrid(myDC)
+ else:
+ self.mainFrame.drawCleanBackground(myDC)
+ if (self.selecting):
+ self.mainFrame.drawSelectRect(myDC)
+ myDC.EndDrawing()
+ def eAddButton(self, event):
+ self.createControl(MBUTTONTYPE, self.buttonIndex, "button")
+ def eAddToggle(self, event):
+ self.createControl(MTOGGLETYPE, self.toggleIndex, "toggle")
+ def eAddVSlider(self, event):
+ self.createControl(MVSLIDERTYPE, self.sliderIndex, "slider")
+ def eAddHSlider(self, event):
+ self.createControl(MHSLIDERTYPE, self.sliderIndex, "slider")
+ def eAddRect(self, event):
+ self.createControl(MRECTTYPE, self.rectIndex, "rectangle")
+ def eAddText(self, event):
+ self.createControl(MTEXTTYPE, self.textIndex, "text")
+ def eAddVGauge(self, event):
+ self.createControl(MVGAUGETYPE, self.gaugeIndex, "gauge")
+ def eAddHGauge(self, event):
+ self.createControl(MHGAUGETYPE, self.gaugeIndex, "gauge")
+ def eAddCheckBox(self, event):
+ self.createControl(MCHECKBOXTYPE, self.checkBoxIndex, "checkbox")
+ def eAddRadioButtons(self, event):
+ if (self.editMode and not self.dragging):
+ txtDialog = wxTextEntryDialog(self.mainFrame.mainPanel,
+ "Number of radio buttons to add:",
+ "Create Radio Buttons", "2")
+ if (txtDialog.ShowModal() == wxID_OK):
+ numRadButs = atoi(txtDialog.GetValue())
+ txtDialog.Destroy()
+ if (numRadButs > 1):
+ indexStr = "radiobutton" + repr(self.radioButtonIndex)
+ pos = self.mainFrame.mainPanel.ScreenToClient( \
+ wxGetMousePosition())
+ controlN = self.addControl(MRADIONEWTYPE,
+ indexStr,
+ pos,
+ "s" + indexStr,
+ "r" + indexStr)
+ coords = pos
+ for i in range(1, numRadButs):
+ indexStr = "radiobutton" + repr(self.radioButtonIndex)
+ coords = [coords[0], coords[1] + 25]
+ maxPos = self.mainFrame.mainPanel.GetSize()[1] - 10
+ minPos = 0
+ if (coords[1] > maxPos):
+ coords[0] = pos[0] + 40
+ coords[1] = pos[1]
+ control = self.addControl(MRADIOBUTTONTYPE,
+ indexStr,
+ coords,
+ "s" + indexStr,
+ "r" + indexStr)
+ control.select()
+ controlN.select()
+ try:
+ wxYield()
+ except:
+ pass
+ controlN.grab()
+ def eAddTextBox(self, event):
+ self.createControl(MTEXTBOXTYPE, self.textBoxIndex, "textbox")
+ def eAddSpinButton(self, event):
+ self.createControl(MSPINBUTTONTYPE, self.spinButtonIndex, "spinbutton")
+ def eAddMouseArea(self, event):
+ self.createControl(MMOUSEAREATYPE, self.mouseAreaIndex, "mousearea")
+ def eAddImage(self, event):
+ if (self.editMode and not self.dragging):
+ dlg = wxFileDialog(self.mainFrame, "Open file", self.filepath,
+ "", "*.*", wxOPEN)
+ if (dlg.ShowModal() == wxID_OK):
+ filepath = dlg.GetPath()
+ self.createControl(MIMAGETYPE,
+ self.imageIndex,
+ "image",
+ filepath)
+ dlg.Destroy()
+ def eAddGraph(self, event):
+ self.createControl(MGRAPHTYPE, self.graphIndex, "graph")
+ def eEditMode(self, event):
+ if (not self.locked):
+ newEditMode = self.mainFrame.editMenu.IsChecked(ID_EDITMODE)
+ self.setEditMode(newEditMode)
+ def eEditControl(self, event):
+ self.edited = True
+ if (len(self.selectedControlList) > 0):
+ self.selectedControlList[0].eEdit(event)
+ # extra array needed because we're removing items from the array
+ # we are cycling through (selectedControlList)
+ def eDeleteControl(self, event):
+ deleteList = []
+ for control in self.selectedControlList:
+ deleteList.append(control)
+ for control in deleteList:
+ self.controlList.remove(control)
+ self.selectedControlList.remove(control)
+ control.mDestroy()
+ def eSelectAll(self, event):
+ for control in self.controlList:
+ control.select()
+ def eDuplicate(self, event):
+ list = []
+ container = duplicationContainer()
+ # Not using selectedControlList since we are removing from it
+ # as we cycle through the list
+ for control in self.controlList:
+ if (control.isSelected()):
+ list.append(control)
+ control.deselect()
+ self.writeControls(list, container)
+ container.chomp()
+ for control in self.readControls(container.getList()):
+ control.select()
+ control.move(DUPPOSOFFSET)
+ def eAlignVertical(self, event):
+ self.alignControls(0)
+ def eAlignHorizontal(self, event):
+ self.alignControls(1)
+ def eRefresh(self, event):
+ for control in self.controlList:
+ control.Refresh()
+ if (control.isSelected()):
+ control.relocateTags()
+ self.mainFrame.mainPanel.Refresh(True)
+ def eNew(self, event):
+ flag = 0;
+ if ((self.edited) and (len(self.controlList) > 0)):
+ flag = 1
+ dlg = wxMessageDialog(self.mainFrame,
+ "Current GUI not saved. Clear anyway?",
+ "GUI Not Saved", wxOK | wxCANCEL)
+ if (dlg.ShowModal() == wxID_OK):
+ flag = 0
+ if (not flag):
+ for control in self.controlList:
+ control.mDestroy()
+ self.controlList = []
+ self.selectedControlList = []
+ self.resetControlIndecies()
+ self.mainFrame.mainPanel.SetBackgroundColour(\
+ self.mainFrame.defBgColor)
+ self.mainFrame.mainPanel.Refresh()
+ self.filepath = ""
+ def eOpen(self, event):
+ if ((self.edited) and (len(self.controlList) > 0)):
+ dlg2 = wxMessageDialog(self.mainFrame,
+ "Current GUI not saved. Open anyway?",
+ "GUI Not Saved", wxOK | wxCANCEL)
+ if (dlg2.ShowModal() == wxID_OK):
+ dlg = wxFileDialog(self.mainFrame,
+ "Open file", self.filepath, "", "*.gpd",
+ wxOPEN)
+ if (dlg.ShowModal() == wxID_OK):
+ self.openFromDisk(dlg.GetPath())
+ # FIXME
+ # dlg.Destroy()
+ # FIXME
+ # dlg2.Destroy()
+ else:
+ dlg = wxFileDialog(self.mainFrame,
+ "Open file", self.filepath, "", "*.gpd",
+ wxOPEN)
+ if (dlg.ShowModal() == wxID_OK):
+ self.openFromDisk(dlg.GetPath())
+ # FIXME
+ # dlg.Destroy()
+ self.mainFrame.mainPanel.Refresh()
+ def eSave(self, event):
+ dlg = wxFileDialog(self.mainFrame, "Save file", self.filepath,
+ "", "*.gpd", wxSAVE)
+ if (dlg.ShowModal() == wxID_OK):
+ filename = dlg.GetPath()
+ try:
+ file = open(filename, 'r', -1)
+ file.close()
+ dlg2 = wxMessageDialog(self.mainFrame, "File " + filename \
+ + " already exists. Overwrite?",
+ "File Exists", wxOK | wxCANCEL)
+ if (dlg2.ShowModal() == wxID_OK):
+ self.saveToDisk(filename)
+ dlg2.Destroy()
+ except:
+ self.saveToDisk(filename)
+ dlg.Destroy()
+ def eSetOptions(self, event):
+ dlg = optionsDialog(self)
+ dlg.ShowModal()
+ self.host = dlg.addrBox.GetValue()
+ try:
+ self.port = atoi(dlg.portBox.GetValue())
+ except:
+ errDlg = wxMessageDialog(self.mainFrame,
+ "Invalid Port",
+ "Options Error",
+ wxOK)
+ errDlg.ShowModal()
+ errDlg.Destroy()
+ try:
+ self.pollTime = atoi(dlg.pollBox.GetValue())
+ except:
+ errDlg = wxMessageDialog(self.mainFrame,
+ "Invalid Socket Poll Time",
+ "Options Error",
+ wxOK)
+ errDlg.ShowModal()
+ errDlg.Destroy()
+ self.joyDevice1 = dlg.joyDevBox1.GetValue()
+ self.joyDevice2 = dlg.joyDevBox2.GetValue()
+ try:
+ self.joyPollTime = atoi(dlg.joyPollBox.GetValue())
+ except:
+ errDlg = wxMessageDialog(self.mainFrame,
+ "Invalid Joystick Poll Time",
+ "Options Error",
+ wxOK)
+ errDlg.ShowModal()
+ errDlg.Destroy()
+ try:
+ self.midiDevice1 = atoi(dlg.midiDevBox1.GetValue())
+ except:
+ errDlg = wxMessageDialog(self.mainFrame,
+ "Invalid MIDI Device 0\nShould be an integer.",
+ "Options Error",
+ wxOK)
+ errDlg.ShowModal()
+ errDlg.Destroy()
+ try:
+ self.midiDevice2 = atoi(dlg.midiDevBox2.GetValue())
+ except:
+ errDlg = wxMessageDialog(self.mainFrame,
+ "Invalid MIDI Device 1\nShould be an integer.",
+ "Options Error",
+ wxOK)
+ errDlg.ShowModal()
+ errDlg.Destroy()
+ try:
+ self.midiPollTime = atoi(dlg.midiPollBox.GetValue())
+ except:
+ errDlg = wxMessageDialog(self.mainFrame,
+ "Invalid MIDI Poll Time",
+ "Options Error",
+ wxOK)
+ errDlg.ShowModal()
+ errDlg.Destroy()
+ self.setFrameTitle(dlg.titleBox.GetValue())
+ if (self.sTimer.IsRunning):
+ self.sTimer.Stop()
+ self.sTimer.Start(self.pollTime)
+ if (not self.locked):
+ if (self.mainFrame.optionsMenu.IsChecked(ID_ENABLEJOY)):
+ self.stopJoystick()
+ self.startJoystick()
+ if (self.mainFrame.optionsMenu.IsChecked(ID_ENABLEMIDI)):
+ self.stopMidi()
+ self.startMidi()
+ dlg.Destroy()
+ self.mainFrame.Refresh(True)
+ self.mainFrame.mainPanel.Refresh(True)
+ for control in self.controlList:
+ control.Refresh()
+ def eAbout(self, event):
+ aboutString = "GrIPD v" + VERSION + ": "
+ aboutString = aboutString \
+ + "Graphical Interface for Pure Data\n\n"
+ aboutString = aboutString \
+ + "(C) Copyright 2003 Joseph A. Sarlo\nGNU "
+ aboutString = aboutString \
+ + "General Public License\njsarlo@ucsd.edu"
+ dlg = wxMessageDialog(self.mainFrame, aboutString , "About GrIPD",
+ wxOK | wxICON_INFORMATION)
+ dlg.ShowModal()
+ dlg.Destroy()
+ def eQuit(self, event):
+ self.mainFrame.Close(True)
+ def eKeyDown(self, event):
+ # already depressed
+ try:
+ self.keysDown.index(event.GetKeyCode())
+ # first time
+ except:
+ self.keysDown.append(event.GetKeyCode())
+ if (not self.editMode):
+ self.sendCharDown(event.GetKeyCode())
+ event.Skip()
+ def eKeyUp(self, event):
+ try:
+ self.keysDown.remove(event.GetKeyCode())
+ self.sendCharUp(event.GetKeyCode())
+ except:
+ pass
+ event.Skip()
+ def eChar(self, event):
+ if (self.editMode and not self.dragging):
+ if (event.m_controlDown):
+ deltaPos = LARGECHARMOVE
+ else:
+ deltaPos = SMALLCHARMOVE
+ if (event.GetKeyCode() == WXK_LEFT):
+ self.moveKey((-deltaPos, 0))
+ return
+ if (event.GetKeyCode() == WXK_RIGHT):
+ self.moveKey((deltaPos, 0))
+ return
+ if (event.GetKeyCode() == WXK_UP):
+ self.moveKey((0, -deltaPos))
+ return
+ if (event.GetKeyCode() == WXK_DOWN):
+ self.moveKey((0, deltaPos))
+ return
+ if (event.GetKeyCode() == WXK_TAB):
+ self.traverseFocus(event.m_controlDown)
+ return
+ if (not self.editMode or (self.editMode and not self.dragging)):
+ # Allow accelerators to be called
+ event.Skip()
+ def eRepaintControlTags(self, event):
+ event.getControl().refreshTags()
+ def eClose(self, event):
+ if (self.openAuto and self.connected):
+ self.mainFrame.Show(False)
+ try:
+ self.connection.send(HIDECOMMAND + SYMMSGSEP + \
+ "0" + PAIRSEPCHAR)
+ except:
+ self.close()
+ else:
+ self.close()
+ def eSize(self, event):
+ self.mainFrame.positionIcons()
+ event.Skip()
+
+# Frame class
+class gripdFrame(wxFrame):
+# Setup
+ def __init__(self, parent, ID, title, position,
+ resizable, locked, alwaysOnTop):
+ self.mParent = parent
+ self.resizable = resizable
+ self.alwaysOnTop = alwaysOnTop
+ self.locked = locked
+ if (self.resizable):
+ style = wxDEFAULT_FRAME_STYLE
+ else:
+ style = wxDEFAULT_FRAME_STYLE & (~wxRESIZE_BORDER) & \
+ (~wxMAXIMIZE_BOX)
+ if (self.alwaysOnTop):
+ style = style | wxSTAY_ON_TOP
+ if (position == (-1, -1)):
+ position = wxDefaultPosition
+ wxFrame.__init__(self, NULL, ID, title, position,
+ DEFMAINFRAMESIZE,
+ style)
+ if (not os.name == "posix"):
+ self.SetIcon(self.mParent.icon)
+ if (not self.locked):
+ # Menu accelerator stuff
+ aclList = []
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL,
+ WXK_DELETE,
+ ID_DELETE))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F1,
+ ID_BUTTON))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F2,
+ ID_TOGGLE))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F3,
+ ID_SPINBUTTON))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F4,
+ ID_RADIOBUTTON))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F5,
+ ID_VSLIDER))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F6,
+ ID_HSLIDER))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F7,
+ ID_VGAUGE))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F8,
+ ID_HGAUGE))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F9,
+ ID_CHECKBOX))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F10,
+ ID_TEXTBOX))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F11,
+ ID_MOUSEAREA))
+ aclList.append(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F12,
+ ID_RECT))
+ aclList.append(wxAcceleratorEntry(wxACCEL_ALT, ord("1"),
+ ID_TEXT))
+ aclList.append(wxAcceleratorEntry(wxACCEL_ALT, ord("2"),
+ ID_IMAGE))
+ self.SetAcceleratorTable(wxAcceleratorTable(aclList))
+ self.menuBar = wxMenuBar()
+ self.SetMenuBar(self.menuBar)
+ self.createMenu()
+ self.CreateStatusBar(3)
+ self.jsIcon1 = wxStaticBitmap(self.GetStatusBar(), -1,
+ self.mParent.jsImageX, (0, 0),
+ wxDefaultSize)
+ self.jsIcon2 = wxStaticBitmap(self.GetStatusBar(), -1,
+ self.mParent.jsImageX, (0, 0),
+ wxDefaultSize)
+ self.midiIcon1 = wxStaticBitmap(self.GetStatusBar(), -1,
+ self.mParent.midiImageX, (0, 0),
+ wxDefaultSize)
+ self.midiIcon2 = wxStaticBitmap(self.GetStatusBar(), -1,
+ self.mParent.midiImageX, (0, 0),
+ wxDefaultSize)
+ self.connectIcon = wxStaticBitmap(self.GetStatusBar(),
+ -1,
+ self.mParent.connectImageX,
+ (0, 0),
+ wxDefaultSize)
+ # timers to flash icons
+ self.jsIconFlasher1 = iconFlasher(self.jsIcon1,
+ self.mParent.jsImage,
+ self.mParent.jsImageA,
+ 1)
+ self.jsIconFlasher2 = iconFlasher(self.jsIcon2,
+ self.mParent.jsImage,
+ self.mParent.jsImageA,
+ 1)
+ self.midiIconFlasher1 = iconFlasher(self.midiIcon1,
+ self.mParent.midiImage,
+ self.mParent.midiImageA,
+ 1)
+ self.midiIconFlasher2 = iconFlasher(self.midiIcon2,
+ self.mParent.midiImage,
+ self.mParent.midiImageA,
+ 1)
+ self.editModeText = wxStaticText(self.GetStatusBar(),
+ -1,
+ "Performance Mode",
+ (0, 0),
+ wxDefaultSize,
+ wxALIGN_CENTRE | \
+ wxST_NO_AUTORESIZE)
+ self.editModeText.Show(True)
+ self.jsIcon1.Show(False)
+ self.jsIcon2.Show(False)
+ self.midiIcon1.Show(False)
+ self.midiIcon2.Show(False)
+ self.connectIcon.Show(True)
+ # left, top, width, height of selection rect (for drawing)
+ self.selectRect = [0, 0, 0, 0]
+ # mainPanel stuff
+ self.mainPanel = wxPanel(self, -1, wxDefaultPosition,
+ wxDefaultSize,
+ wxSTATIC_BORDER)
+ self.defBgColor = wxColour(self.mainPanel.GetBackgroundColour().Red() \
+ - BGCOLORDIF,
+ self.mainPanel.GetBackgroundColour().Green() \
+ - BGCOLORDIF,
+ self.mainPanel.GetBackgroundColour().Blue() \
+ - BGCOLORDIF)
+ self.mainPanel.SetBackgroundColour(self.defBgColor)
+ self.mainPanel.Show(True)
+ if (self.locked):
+ self.lock()
+ else:
+ self.unlock()
+ def createMenu(self):
+ self.fileMenu = wxMenu()
+ self.fileMenu.Append(ID_NEW, "&New\tCtrl-N", "Clear current GUI")
+ self.fileMenu.Append(ID_OPEN, "&Open\tCtrl-O", "Open a GUI")
+ self.fileMenu.Append(ID_SAVE, "&Save\tCtrl-S", "Save current GUI")
+ self.fileMenu.AppendSeparator()
+ self.fileMenu.Append(ID_CONNECT, "&Connect\tAlt-C",
+ "Connect to PD")
+ self.fileMenu.Append(ID_DISCONNECT, "&Disconnect\tAlt-D",
+ "Disconnect from PD")
+ self.fileMenu.AppendSeparator()
+ self.fileMenu.Append(ID_EXIT, "E&xit\tCtrl-Q", "Quit GrIPD")
+ self.editMenu = wxMenu()
+ self.editMenu.Append(ID_EDITMODE, "Edit &mode\tCtrl-E",
+ "Toggle Edit/Performance Modes", True)
+ self.editMenu.AppendSeparator()
+ self.addMenu = wxMenu()
+ self.buttonMenu = wxMenu()
+ self.buttonMenu.Append(ID_BUTTON, "&Push Button\tF1",
+ "Add a push button")
+ self.buttonMenu.Append(ID_TOGGLE, "&Toggle Button\tF2",
+ "Add a toggle button")
+ self.buttonMenu.Append(ID_SPINBUTTON, "&Spin Button\tF3",
+ "Add a spin button")
+ self.buttonMenu.Append(ID_RADIOBUTTON, "&Radio Buttons\tF4",
+ "Add radio buttons")
+ self.addMenu.AppendMenu(ID_BUTTONMENU, "&Button", self.buttonMenu);
+ self.sliderMenu = wxMenu()
+ self.sliderMenu.Append(ID_VSLIDER, "&Vertical Slider\tF5",
+ "Add a vertical slider")
+ self.sliderMenu.Append(ID_HSLIDER, "&Horizontal Slider\tF6",
+ "Add a horizontal slider")
+ self.addMenu.AppendMenu(ID_SLIDERMENU, "&Slider", self.sliderMenu);
+ self.gaugeMenu = wxMenu()
+ self.gaugeMenu.Append(ID_VGAUGE, "&Vertical Gauge\tF7",
+ "Add a vertical gauge")
+ self.gaugeMenu.Append(ID_HGAUGE, "&Horizontal Gauge\tF8",
+ "Add a horizontal gauge")
+ self.addMenu.AppendMenu(ID_GAUGEMENU, "&Gauge", self.gaugeMenu);
+ self.addMenu.Append(ID_CHECKBOX, "&Checkbox\tF9",
+ "Add a labeld checkbox")
+ self.addMenu.Append(ID_TEXTBOX, "Te&xtbox\tF10",
+ "Add a box for entering text")
+ self.addMenu.Append(ID_MOUSEAREA, "&Mouse Area\tF11",
+ "Add a mouse capture area")
+ self.addMenu.Append(ID_RECT, "&Rectangle\tF12",
+ "Add a boundary rectangle")
+ self.addMenu.Append(ID_TEXT, "&Text\tAlt-1", "Add text")
+ self.addMenu.Append(ID_IMAGE, "&Image\tAlt-2", "Add an image")
+ self.addMenu.Append(ID_GRAPH, "&Graph\tAlt-3", "Add a graph")
+ self.editMenu.AppendMenu(ID_ADD, "&Add", self.addMenu)
+ self.editMenu.Append(ID_EDIT, "&Edit", "Edit selected controls")
+ self.editMenu.Append(ID_DELETE, "&Delete", "Delete selected controls")
+ self.editMenu.AppendSeparator()
+ self.editMenu.Append(ID_SELECTALL, "&Select All\tCtrl-A",
+ "Select all controls")
+ self.editMenu.Append(ID_DUPLICATE, "D&uplicate\tCtrl-D",
+ "Duplicate selected controls")
+ self.editMenu.AppendSeparator()
+ self.editMenu.Append(ID_ALIGNVERT, "Align &Vertical\tCtrl-V",
+ "Vertically align selected controls")
+ self.editMenu.Append(ID_ALIGNHORZ, "Align &Horizontal\tCtrl-H",
+ "Horizontally align selected controls")
+ self.editMenu.AppendSeparator()
+ self.editMenu.Append(ID_REFRESH, "&Refresh\tCtrl-R", "Refresh screen")
+ self.optionsMenu = wxMenu()
+ if (os.name != "posix"):
+ self.optionsMenu.Append(ID_ALWAYSONTOP, "Always On Top",
+ "Window will stay above all other windows",
+ True)
+ self.optionsMenu.AppendSeparator()
+ self.optionsMenu.Append(ID_ENABLEMIDI, "Enable &MIDI",
+ "Enables the use of MIDI input",
+ True)
+ self.optionsMenu.Append(ID_ENABLEJOY, "Enable &Joystick(s)",
+ "Enables the use of a joystick",
+ True)
+ self.optionsMenu.Append(ID_ENABLEKEY, "Send &Keystrokes",
+ "Send all keystrokes to PD 'keystroke' symbol",
+ True)
+ self.optionsMenu.AppendSeparator()
+ self.optionsMenu.Append(ID_SHOWGRID, "Show Grid",
+ "Show Edit Grid", True)
+ self.optionsMenu.Append(ID_SNAPTOGRID, "Snap To Grid",
+ "Snap controls to edit grid", True)
+ self.optionsMenu.AppendSeparator()
+ self.optionsMenu.Append(ID_SETOPTS, "&Configure\tCtrl-C",
+ "Set GUI options")
+ self.helpMenu = wxMenu()
+ self.helpMenu.Append(ID_ABOUT, "&About",
+ "GrIPD: Graphical Interface for Pure Data")
+ self.menuBar.Append(self.fileMenu, "&File")
+ self.menuBar.Append(self.editMenu, "&Edit")
+ self.menuBar.Append(self.optionsMenu, "&Options")
+ self.menuBar.Append(self.helpMenu, "&Help")
+ self.fileMenu.Enable(ID_DISCONNECT, False)
+ self.editMenu.Enable(ID_ADD, False)
+ self.editMenu.Enable(ID_EDIT, False)
+ self.editMenu.Enable(ID_DELETE, False)
+ self.editMenu.Enable(ID_SELECTALL, False)
+ self.editMenu.Enable(ID_DUPLICATE, False)
+ self.editMenu.Enable(ID_ALIGNVERT, False)
+ self.editMenu.Enable(ID_ALIGNHORZ, False)
+ if (self.mParent.joystickAvailable):
+ self.optionsMenu.Check(ID_ENABLEJOY, self.mParent.joystickEnabled)
+ if (self.mParent.midiAvailable):
+ self.optionsMenu.Check(ID_ENABLEMIDI, self.mParent.midiEnabled)
+ self.optionsMenu.Check(ID_ENABLEKEY, self.mParent.sendKeys)
+ if (os.name != "posix"):
+ self.optionsMenu.Check(ID_ALWAYSONTOP, self.alwaysOnTop)
+ self.optionsMenu.Check(ID_SHOWGRID, self.mParent.showGrid)
+ self.optionsMenu.Check(ID_SNAPTOGRID, self.mParent.snapToGrid)
+ self.optionsMenu.Enable(ID_ENABLEJOY,
+ self.mParent.joystickAvailable)
+ self.optionsMenu.Enable(ID_ENABLEMIDI,
+ self.mParent.midiAvailable)
+ EVT_MENU(self, ID_NEW, self.mParent.eNew)
+ EVT_MENU(self, ID_ABOUT, self.mParent.eAbout)
+ EVT_MENU(self, ID_EXIT, self.mParent.eQuit)
+ EVT_MENU(self, ID_CONNECT, self.mParent.eOpenConnection)
+ EVT_MENU(self, ID_DISCONNECT, self.mParent.eCloseConnection)
+ EVT_MENU(self, ID_OPEN, self.mParent.eOpen)
+ EVT_MENU(self, ID_SAVE, self.mParent.eSave)
+ EVT_MENU(self, ID_BUTTON, self.mParent.eAddButton)
+ EVT_MENU(self, ID_TOGGLE, self.mParent.eAddToggle)
+ EVT_MENU(self, ID_SPINBUTTON, self.mParent.eAddSpinButton)
+ EVT_MENU(self, ID_VSLIDER, self.mParent.eAddVSlider)
+ EVT_MENU(self, ID_HSLIDER, self.mParent.eAddHSlider)
+ EVT_MENU(self, ID_RECT, self.mParent.eAddRect)
+ EVT_MENU(self, ID_VGAUGE, self.mParent.eAddVGauge)
+ EVT_MENU(self, ID_HGAUGE, self.mParent.eAddHGauge)
+ EVT_MENU(self, ID_CHECKBOX, self.mParent.eAddCheckBox)
+ EVT_MENU(self, ID_RADIOBUTTON, self.mParent.eAddRadioButtons)
+ EVT_MENU(self, ID_TEXTBOX, self.mParent.eAddTextBox)
+ EVT_MENU(self, ID_TEXT, self.mParent.eAddText)
+ EVT_MENU(self, ID_IMAGE, self.mParent.eAddImage)
+ EVT_MENU(self, ID_MOUSEAREA, self.mParent.eAddMouseArea)
+ EVT_MENU(self, ID_GRAPH, self.mParent.eAddGraph)
+ EVT_MENU(self, ID_EDITMODE, self.mParent.eEditMode)
+ EVT_MENU(self, ID_EDIT, self.mParent.eEditControl)
+ EVT_MENU(self, ID_DELETE, self.mParent.eDeleteControl)
+ EVT_MENU(self, ID_SELECTALL, self.mParent.eSelectAll)
+ EVT_MENU(self, ID_DUPLICATE, self.mParent.eDuplicate)
+ EVT_MENU(self, ID_ALIGNVERT, self.mParent.eAlignVertical)
+ EVT_MENU(self, ID_ALIGNHORZ, self.mParent.eAlignHorizontal)
+ EVT_MENU(self, ID_REFRESH, self.mParent.eRefresh)
+ EVT_MENU(self, ID_SETOPTS, self.mParent.eSetOptions)
+ EVT_MENU(self, ID_ENABLEJOY, self.mParent.eToggleJoystick)
+ EVT_MENU(self, ID_ENABLEMIDI, self.mParent.eToggleMidi)
+ EVT_MENU(self, ID_ENABLEKEY, self.mParent.eToggleKeySend)
+ if (os.name != "posix"):
+ EVT_MENU(self, ID_ALWAYSONTOP, self.mParent.eToggleAlwaysOnTop)
+ EVT_MENU(self, ID_SHOWGRID, self.mParent.eToggleShowGrid)
+ EVT_MENU(self, ID_SNAPTOGRID, self.mParent.eToggleSnapToGrid)
+ def createLockedMenu(self):
+ self.fileMenu = wxMenu()
+ self.fileMenu.Append(ID_EXIT, "E&xit\tCtrl-Q", "Quit GrIPD")
+ self.helpMenu = wxMenu()
+ self.helpMenu.Append(ID_ABOUT, "&About",
+ "GrIPD: Graphical Interface for Pure Data")
+ self.menuBar.Append(self.fileMenu, "&File")
+ self.menuBar.Append(self.helpMenu, "&Help")
+ EVT_MENU(self, ID_ABOUT, self.mParent.eAbout)
+ EVT_MENU(self, ID_EXIT, self.mParent.eQuit)
+ def removeMenu(self):
+ for i in range(0, self.GetMenuBar().GetMenuCount()):
+ self.GetMenuBar().Remove(0)
+ def drawCleanBackground(self, myDC, rect = ()):
+ box = self.mainPanel.GetUpdateRegion().GetBox()
+ if (rect == ()):
+ rect = tuple((box[0],
+ box[1],
+ box[0] + box[2],
+ box[1] + box[3]))
+ myDC.SetPen(wxPen(self.mainPanel.GetBackgroundColour(),
+ 1,
+ wxTRANSPARENT))
+ myDC.SetBrush(wxBrush(self.mainPanel.GetBackgroundColour(), wxSOLID))
+ myDC.DrawRectangle(rect[0],
+ rect[1],
+ rect[2],
+ rect[3])
+ def drawGrid(self, myDC, rect = ()):
+ box = self.mainPanel.GetUpdateRegion().GetBox()
+ if (rect == ()):
+ rect = tuple((box[0],
+ box[1],
+ box[0] + box[2],
+ box[1] + box[3]))
+ color = self.mainPanel.GetBackgroundColour()
+ newColorTuple = [color.Red() - 50,
+ color.Green() - 50,
+ color.Blue() - 50]
+ if (newColorTuple[0] < 0 or \
+ newColorTuple[1] < 0 or \
+ newColorTuple[2] < 0):
+ newColorTuple = [color.Red() + 50,
+ color.Green() + 50,
+ color.Blue() + 50]
+ for i in range(0, 3):
+ if (newColorTuple[i] > 255 or newColorTuple[i] < 0):
+ newColorTuple[i] = 0
+ myDC.SetPen(wxPen(self.mainPanel.GetBackgroundColour(),
+ 1,
+ wxTRANSPARENT))
+ myDC.SetBrush(wxBrush(self.mainPanel.GetBackgroundColour(), wxSOLID))
+ myDC.DrawRectangle(rect[0],
+ rect[1],
+ rect[2],
+ rect[3])
+ myDC.SetPen(wxPen(wxColour(newColorTuple[0],
+ newColorTuple[1],
+ newColorTuple[2]),
+ 1,
+ wxSOLID))
+ myDC.SetBrush(wxBrush("#000000", wxTRANSPARENT))
+ for i in range(rect[0], rect[2]):
+ if (i% self.mParent.gridSpace == 0):
+ myDC.DrawLine(i, rect[1], i, rect[3])
+ for i in range(rect[1], rect[3]):
+ if (i % self.mParent.gridSpace == 0):
+ myDC.DrawLine(rect[0], i, rect[2], i)
+ def drawSelectRect(self, myDC):
+ myDC.SetPen(wxPen("#000000", 1, wxDOT))
+ myDC.SetBrush(wxBrush(self.mainPanel.GetBackgroundColour(),
+ wxTRANSPARENT))
+ myDC.DrawRectangle(self.selectRect[0], self.selectRect[1],
+ self.selectRect[2], self.selectRect[3])
+ def setEditModeText(self, text):
+ if (not self.locked):
+ self.editModeText.SetLabel(text)
+ self.editModeText.SetSize(( \
+ self.GetStatusBar().GetFieldRect(1)[2] - 10,
+ self.editModeText.GetSize()[1]))
+ self.editModeText.Show(True)
+ pos = (((self.GetStatusBar().GetFieldRect(1)[2] - \
+ self.editModeText.GetSize()[0]) / 2) + \
+ self.GetStatusBar().GetFieldRect(1)[0] + 1,
+ ((self.GetStatusBar().GetFieldRect(1)[3] - \
+ self.editModeText.GetSize()[1]) / 2) + \
+ self.GetStatusBar().GetFieldRect(1)[1] + \
+ -1 * (FUGEFACTOR - 2))
+ self.editModeText.Move(pos)
+ def lock(self):
+ self.locked = True
+ def unlock(self):
+ self.locked = False
+ def positionIcons(self):
+ if (not self.locked):
+ self.setEditModeText(self.editModeText.GetLabel())
+ pos = (self.GetStatusBar().GetFieldRect(2)[0] + 3,
+ self.GetStatusBar().GetFieldRect(2)[3] - \
+ self.connectIcon.GetSize()[1] + 1)
+ self.connectIcon.Move(pos)
+ self.midiIcon1.Move((self.connectIcon.GetPosition()[0] + \
+ self.connectIcon.GetSize()[0] + 5,
+ pos[1]))
+ self.midiIcon2.Move((self.midiIcon1.GetPosition()[0] + \
+ self.midiIcon1.GetSize()[0] + 3, pos[1]))
+ if (self.mParent.midiEnabled):
+ self.jsIcon1.Move((self.midiIcon2.GetPosition()[0] + \
+ self.midiIcon2.GetSize()[0] + 5,
+ pos[1]))
+ else:
+ self.jsIcon1.Move((self.connectIcon.GetPosition()[0] + \
+ self.connectIcon.GetSize()[0] + 5,
+ pos[1]))
+ self.jsIcon2.Move((self.jsIcon1.GetPosition()[0] + \
+ self.jsIcon1.GetSize()[0] + 3, pos[1]))
+
+ self.Refresh()
+ def openpanel(self):
+ dlg = wxFileDialog(self, "Open file", self.mParent.filepath,
+ "", "*.*", wxOPEN)
+ if (dlg.ShowModal() == wxID_OK):
+ filename = dlg.GetPath()
+ self.mParent.connection.send('openpanel' \
+ + SYMMSGSEP \
+ + filename \
+ + PAIRSEPCHAR)
+
+
+ def savepanel(self):
+ dlg = wxFileDialog(self, "Save file", self.mParent.filepath,
+ "", "*.*", wxSAVE)
+ if (dlg.ShowModal() == wxID_OK):
+ filename = dlg.GetPath()
+ self.mParent.connection.send('savepanel' \
+ + SYMMSGSEP \
+ + filename \
+ + PAIRSEPCHAR)
+ def stopIconFlashers(self):
+ self.jsIconFlasher1.Stop()
+ self.jsIconFlasher2.Stop()
+ self.midiIconFlasher1.Stop()
+ self.midiIconFlasher2.Stop()
+ def Destroy(self):
+ if (not self.locked):
+ self.stopIconFlashers()
+ wxFrame.Destroy(self)
+
+
+# Classes used by mainFrame
+# Class to poll for connection to server
+class connectionTimer(wxTimer):
+ def __init__(self, parent):
+ wxTimer.__init__(self)
+ self.mParent = parent
+ self.timeCount = 0
+ def connect(self):
+ try:
+ if (not self.mParent.locked):
+ self.mParent.mainFrame.fileMenu.Enable(ID_CONNECT, False)
+ tempConn = socket(AF_INET, SOCK_STREAM)
+ tempConn.connect((self.mParent.host, self.mParent.port))
+ tempConn.setblocking(0)
+ rcvrList = self.mParent.connection.rcvrList
+ self.mParent.connection = tempConn
+ self.Stop()
+ self.mParent.sTimer.Start(self.mParent.pollTime)
+ self.mParent.connection.send(rcvrList)
+ for control in self.mParent.controlList:
+ control.connection = self.mParent.connection
+ self.mParent.connected = True
+ self.mParent.pingCount = 0
+ self.mParent.pTimer.Start(PINGPOLLTIME)
+ if (not self.mParent.locked):
+ self.mParent.mainFrame.connectIcon.SetBitmap(\
+ self.mParent.connectImage)
+ self.mParent.mainFrame.connectIcon.Refresh()
+ self.mParent.connection.send(SHOWCOMMAND + \
+ SYMMSGSEP + "0" + \
+ PAIRSEPCHAR)
+ self.mParent.mainFrame.Show(True)
+ except:
+ self.timeCount = self.timeCount + 1
+ def Notify(self):
+ self.connect()
+ if (self.timeCount >= TIMEOUT):
+ self.Stop()
+ dlg = wxMessageDialog(self.mParent.mainFrame, "Connection Timeout",
+ "Connection", wxOK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ if (not self.mParent.locked):
+ self.mParent.mainFrame.fileMenu.Enable(ID_CONNECT, True)
+
+# Class to poll socket for receive string
+class socketTimer(wxTimer):
+ def __init__(self, parent):
+ wxTimer.__init__(self)
+ self.mParent = parent
+ def Notify(self):
+ try:
+ receiveBuffer = self.mParent.connection.recv(16384)
+ numBytes = len(strip(receiveBuffer))
+ if (numBytes > 0):
+ self.mParent.parseReceiveBuffer(receiveBuffer)
+ except:
+ pass
+
+# Class to check connection status
+class pingTimer(wxTimer):
+ def __init__(self, parent):
+ wxTimer.__init__(self)
+ self.mParent = parent
+ def Notify(self):
+ try:
+ self.mParent.connection.send(PINGCOMMAND + SYMMSGSEP + \
+ "0" + PAIRSEPCHAR)
+
+ except:
+ self.Stop()
+ self.mParent.pingTimeout()
+
+# Class to poll joystick
+class joystickTimer(wxTimer):
+ def __init__(self, parent):
+ wxTimer.__init__(self)
+ self.mParent = parent
+ def Notify(self):
+ if (self.mParent.joyID1 > -1):
+ numEvents1 = joystick.readEvents(self.mParent.joyID1)
+ if (numEvents1 > 0):
+ self.mParent.showJoystickActive(1)
+ for i in range(0, numEvents1):
+ if (joystick.getEventType(self.mParent.joyID1, i) == 0):
+ try:
+ self.mParent.connection.send('joy0axis'
+ + repr(joystick.getEventNumber(
+ self.mParent.joyID1,
+ i)) \
+ + SYMMSGSEP \
+ + repr(joystick.getEventValue(
+ self.mParent.joyID1,
+ i)) \
+ + PAIRSEPCHAR)
+ except:
+ self.mParent.close()
+ if (joystick.getEventType(self.mParent.joyID1,i) == 1):
+ try:
+ self.mParent.connection.send('joy0button'
+ + repr(joystick.getEventNumber(
+ self.mParent.joyID1,
+ i)) \
+ + SYMMSGSEP \
+ + repr(joystick.getEventValue(
+ self.mParent.joyID1,
+ i)) \
+ + PAIRSEPCHAR)
+ except:
+ self.mParent.close()
+ if (self.mParent.joyID2 > -1):
+ numEvents2 = joystick.readEvents(self.mParent.joyID2)
+ if (numEvents2 > 0):
+ self.mParent.showJoystickActive(2)
+ for i in range(0, numEvents2):
+ if (joystick.getEventType(self.mParent.joyID2, i) == 0):
+ try:
+ self.mParent.connection.send('joy1axis'
+ + repr(joystick.getEventNumber(
+ self.mParent.joyID2,
+ i)) \
+ + SYMMSGSEP \
+ + repr(joystick.getEventValue(
+ self.mParent.joyID2,
+ i)) \
+ + PAIRSEPCHAR)
+ except:
+ self.mParent.close()
+ if (joystick.getEventType(self.mParent.joyID2,i) == 1):
+ try:
+ self.mParent.connection.send('joy1button'
+ + repr(joystick.getEventNumber(
+ self.mParent.joyID2,
+ i)) \
+ + SYMMSGSEP \
+ + repr(joystick.getEventValue(
+ self.mParent.joyID2,
+ i)) \
+ + PAIRSEPCHAR)
+ except:
+ self.mParent.close()
+
+# Class to poll midi
+class midiTimer(wxTimer):
+ def __init__(self, parent):
+ wxTimer.__init__(self)
+ self.mParent = parent
+ def Notify(self):
+ if (self.mParent.midiID1 > -1):
+ numEvents1 = midi.readEvents(self.mParent.midiID1)
+ if (numEvents1 > 0):
+ self.mParent.showMidiActive(1)
+ for i in range(0, numEvents1):
+ midiCommand = midi.getEventCommand(self.mParent.midiID1, i)
+ midiCommand = hex(midiCommand)
+ midiP1 = midi.getEventP1(self.mParent.midiID1, i)
+ midiP2 = midi.getEventP2(self.mParent.midiID1, i)
+ messageType = midiCommand[2]
+ channel = repr(atoi(midiCommand[3]) + 1)
+ try:
+ if (messageType == MIDINOTEMESSAGE):
+ self.mParent.connection.send('midi0note'
+ + SYMMSGSEP \
+ + repr(midiP1) \
+ + " " \
+ + repr(midiP2) \
+ + " " \
+ + channel \
+ + PAIRSEPCHAR)
+ elif (messageType == MIDICTLMESSAGE):
+ self.mParent.connection.send('midi0ctl'
+ + SYMMSGSEP \
+ + repr(midiP1) \
+ + " " \
+ + repr(midiP2) \
+ + " " \
+ + channel \
+ + PAIRSEPCHAR)
+ elif (messageType == MIDIPGMMESSAGE):
+ self.mParent.connection.send('midi0pgm'
+ + SYMMSGSEP \
+ + repr(midiP1) \
+ + " " \
+ + channel \
+ + PAIRSEPCHAR)
+ except:
+ self.mParent.close()
+ if (self.mParent.midiID2 > -1):
+ numEvents2 = midi.readEvents(self.mParent.midiID2)
+ if (numEvents2 > 0):
+ self.mParent.showMidiActive(2)
+ for i in range(0, numEvents2):
+ midiCommand = midi.getEventCommand(self.mParent.midiID2, i)
+ midiCommand = hex(midiCommand)
+ midiP1 = midi.getEventP1(self.mParent.midiID2, i)
+ midiP2 = midi.getEventP2(self.mParent.midiID2, i)
+ messageType = midiCommand[2]
+ channel = repr(atoi(midiCommand[3]) + 1)
+ try:
+ if (messageType == MIDINOTEMESSAGE):
+ self.mParent.connection.send('midi1note'
+ + SYMMSGSEP \
+ + repr(midiP1) \
+ + " " \
+ + repr(midiP2) \
+ + " " \
+ + channel \
+ + PAIRSEPCHAR)
+ elif (messageType == MIDICTLMESSAGE):
+ self.mParent.connection.send('midi1ctl'
+ + SYMMSGSEP \
+ + repr(midiP1) \
+ + " " \
+ + repr(midiP2) \
+ + " " \
+ + channel \
+ + PAIRSEPCHAR)
+ elif (messageType == MIDIPGMMESSAGE):
+ self.mParent.connection.send('midi1pgm'
+ + SYMMSGSEP \
+ + repr(midiP1) \
+ + " " \
+ + channel \
+ + PAIRSEPCHAR)
+ except:
+ self.mParent.close()
+
+# Class to flash icon between 2 bitmaps
+class iconFlasher(wxTimer):
+ def __init__(self, icon, bitmap1, bitmap2, nFlashes):
+ wxTimer.__init__(self)
+ self.icon = icon
+ self.bitmap1 = bitmap1
+ self.bitmap2 = bitmap2
+ self.nFlashes = nFlashes
+ self.running = False
+ def Start(self, ms):
+ if (not self.running):
+ self.running = True
+ self.flashCount = 0
+ self.activeBitmap = 1
+ wxTimer.Start(self, ms)
+ def Stop(self):
+ self.running = False
+ self.icon.SetBitmap(self.bitmap1)
+ wxTimer.Stop(self)
+ def Notify(self):
+ if (self.flashCount >= self.nFlashes):
+ self.icon.SetBitmap(self.bitmap1)
+ self.icon.Refresh()
+ self.Stop()
+ else:
+ if (self.activeBitmap == 1):
+ self.icon.SetBitmap(self.bitmap2)
+ self.icon.Refresh()
+ self.activeBitmap = 2
+ self.flashCount = self.flashCount + 1
+ else:
+ self.icon.SetBitmap(self.bitmap1)
+ self.activeBitmap = 1
+ self.icon.Refresh()
+
+# Class to hold commands (receive names) while not connected
+class nullConnection:
+ def __init__(self):
+ self.rcvrList = ""
+ def send(self, receiveBuffer):
+ (symName, value) = split(receiveBuffer,SYMMSGSEP)
+ if (symName[0] == COMMANDCHAR):
+ if (symName == SETRCVRCOMMAND):
+ self.rcvrList = self.rcvrList + receiveBuffer
+ def close(self):
+ pass
+
+# Class for holding control info for duplicate (sort of emulates file object)
+class duplicationContainer:
+ def __init__(self):
+ self.list = []
+ def write(self, string):
+ self.list.append(string)
+ def chomp(self):
+ for i in range(0, len(self.list)):
+ self.list[i] = replace(self.list[i], "\n", "")
+ def getList(self):
+ return self.list
+
+# Class for setting options
+class optionsDialog(wxDialog):
+ def __init__(self, parent):
+ self.parent = parent
+ wxDialog.__init__(self, parent.mainFrame, -1, "Configure",
+ wxDefaultPosition, wxDefaultSize,
+ wxDIALOG_MODAL | wxCAPTION)
+
+ titleText = wxStaticText(self, -1, "Window Title:",
+ (DEFOPTIONSPOS[0] + 10,
+ DEFOPTIONSPOS[1] + 20))
+ self.titleBox = wxTextCtrl(self, -1, parent.frameTitle,
+ (titleText.GetPosition()[0] \
+ + titleText.GetSize()[0] + 80,
+ titleText.GetPosition()[1] - 4))
+
+ addrText = wxStaticText(self, -1, "Connection Address:",
+ (titleText.GetPosition()[0],
+ titleText.GetPosition()[1] \
+ + titleText.GetSize()[1] + 15))
+ self.addrBox = wxTextCtrl(self, -1, parent.host,
+ (self.titleBox.GetPosition()[0],
+ addrText.GetPosition()[1] - 4))
+
+ portText = wxStaticText(self, -1, "Connection Port:",
+ (addrText.GetPosition()[0],
+ addrText.GetPosition()[1] \
+ + addrText.GetSize()[1] + 15))
+ self.portBox = wxTextCtrl(self, -1, repr(parent.port),
+ (self.titleBox.GetPosition()[0],
+ portText.GetPosition()[1] - 4))
+
+ pollText = wxStaticText(self, -1, "Socket Poll Time (ms): ",
+ (addrText.GetPosition()[0],
+ portText.GetPosition()[1] \
+ + portText.GetSize()[1] + 15))
+ self.pollBox = wxTextCtrl(self, -1, repr(parent.pollTime),
+ (self.titleBox.GetPosition()[0],
+ pollText.GetPosition()[1] - 4))
+
+ joyDevText1 = wxStaticText(self, -1, "Joystick Device 0: ",
+ (addrText.GetPosition()[0],
+ pollText.GetPosition()[1] \
+ + pollText.GetSize()[1] + 15))
+ self.joyDevBox1 = wxTextCtrl(self, -1, parent.joyDevice1,
+ (self.titleBox.GetPosition()[0],
+ joyDevText1.GetPosition()[1] - 4))
+
+ joyDevText2 = wxStaticText(self, -1, "Joystick Device 1: ",
+ (addrText.GetPosition()[0],
+ joyDevText1.GetPosition()[1] \
+ + joyDevText1.GetSize()[1] + 15))
+ self.joyDevBox2 = wxTextCtrl(self, -1, parent.joyDevice2,
+ (self.titleBox.GetPosition()[0],
+ joyDevText2.GetPosition()[1] - 4))
+
+ joyPollText = wxStaticText(self, -1, "Joystick Poll Time (ms): ",
+ (addrText.GetPosition()[0],
+ joyDevText2.GetPosition()[1] \
+ + joyDevText2.GetSize()[1] + 15))
+ self.joyPollBox = wxTextCtrl(self, -1, repr(parent.joyPollTime),
+ (self.titleBox.GetPosition()[0],
+ joyPollText.GetPosition()[1] - 4))
+
+ midiDevText1 = wxStaticText(self, -1, "MIDI Device 0: ",
+ (addrText.GetPosition()[0],
+ joyPollText.GetPosition()[1] \
+ + joyPollText.GetSize()[1] + 15))
+ self.midiDevBox1 = wxTextCtrl(self, -1, repr(parent.midiDevice1),
+ (self.titleBox.GetPosition()[0],
+ midiDevText1.GetPosition()[1] - 4))
+
+ midiDevText2 = wxStaticText(self, -1, "MIDI Device 1: ",
+ (addrText.GetPosition()[0],
+ midiDevText1.GetPosition()[1] \
+ + midiDevText1.GetSize()[1] + 15))
+ self.midiDevBox2 = wxTextCtrl(self, -1, repr(parent.midiDevice2),
+ (self.titleBox.GetPosition()[0],
+ midiDevText2.GetPosition()[1] - 4))
+
+ midiPollText = wxStaticText(self, -1, "MIDI Poll Time (ms): ",
+ (addrText.GetPosition()[0],
+ midiDevText2.GetPosition()[1] \
+ + midiDevText2.GetSize()[1] + 15))
+ self.midiPollBox = wxTextCtrl(self, -1, repr(parent.midiPollTime),
+ (self.titleBox.GetPosition()[0],
+ midiPollText.GetPosition()[1] - 4))
+
+ bColorText = wxStaticText(self, -1, "Background Color:",
+ (addrText.GetPosition()[0],
+ midiPollText.GetPosition()[1] \
+ + midiPollText.GetSize()[1] + 15))
+ bColorButton = wxButton(self, -1, "Set",
+ (self.titleBox.GetPosition()[0],
+ bColorText.GetPosition()[1] - 4),
+ self.midiPollBox.GetSize())
+
+ rect = wxStaticBox(self, -1, "Options", DEFOPTIONSPOS,
+ (self.addrBox.GetPosition()[0] \
+ + self.addrBox.GetSize()[0] + 10,
+ bColorButton.GetPosition()[1] + \
+ bColorButton.GetSize()[1] + 20))
+ line = wxStaticLine(self, -1, (DEFOPTIONSPOS[0],
+ bColorButton.GetPosition()[1] \
+ + bColorButton.GetSize()[1] + 30),
+ (rect.GetSize()[0], 1))
+ okButton = wxButton(self, -1, "OK", (0, line.GetPosition()[1] + 10))
+ self.SetSize((rect.GetSize()[0] + 15,
+ okButton.GetPosition()[1] + \
+ (FUGEFACTOR * okButton.GetSize()[1]) + \
+ (okButton.GetPosition()[1] - line.GetPosition()[1]) + 4))
+ okButton.Center(wxHORIZONTAL)
+ okButton.Move((okButton.GetPosition()[0], line.GetPosition()[1] + 10))
+ EVT_BUTTON(self, okButton.GetId(), self.eOK)
+ EVT_BUTTON(self, bColorButton.GetId(), self.eBColor)
+ def eOK(self, event):
+ self.EndModal(wxID_OK)
+ def eBColor(self, event):
+ color = getColorFromDialog(self,
+ self.parent.mainFrame.mainPanel.GetBackgroundColour())
+ self.parent.mainFrame.mainPanel.SetBackgroundColour(color)
+ for control in self.parent.controlList:
+ if (control.resetBackground):
+ control.SetBackgroundColour(color)
diff --git a/icon.pic b/icon.pic
new file mode 100644
index 0000000..26e8bb2
--- /dev/null
+++ b/icon.pic
Binary files differ
diff --git a/joystick.xpm b/joystick.xpm
new file mode 100644
index 0000000..bd52354
--- /dev/null
+++ b/joystick.xpm
@@ -0,0 +1,68 @@
+/* XPM */
+static char * joystick_xpm[] = {
+"17 16 49 1",
+" c None",
+". c #000000",
+"+ c #9C9C9C",
+"@ c #FFFFFF",
+"# c #444444",
+"$ c #4C4C4C",
+"% c #323232",
+"& c #464646",
+"* c #F9F9F9",
+"= c #252525",
+"- c #474747",
+"; c #E0E0E0",
+"> c #DADADA",
+", c #E1E1E1",
+"' c #7C0000",
+") c #380000",
+"! c #8A8A8A",
+"~ c #DEDEDE",
+"{ c #A4A4A4",
+"] c #ADADAD",
+"^ c #D0D0D0",
+"/ c #F7FFFF",
+"( c #800000",
+"_ c #603B3B",
+": c #C4C4C4",
+"< c #81ABAB",
+"[ c #4C5858",
+"} c #969696",
+"| c #4E4E4E",
+"1 c #E9E9E9",
+"2 c #5A5A5A",
+"3 c #F4F4F4",
+"4 c #BFBFBF",
+"5 c #353535",
+"6 c #5D5D5D",
+"7 c #818181",
+"8 c #BDBDBD",
+"9 c #131313",
+"0 c #181818",
+"a c #5E5E5E",
+"b c #838383",
+"c c #8D8D8D",
+"d c #535353",
+"e c #E8E8E8",
+"f c #696969",
+"g c #8B8B8B",
+"h c #AAAAAA",
+"i c #6A6A6A",
+"j c #070707",
+" .. ",
+" +@@. ",
+" +@#. ",
+" +@#. ",
+" +@#. ",
+" +@#. ",
+" $%+@#.%% ",
+" &%**+@##@@%%= ",
+" -%;>,@.@..@')@@.",
+"!@~{]^@@.@,/(_@!.",
+"-@@@@:,,,,@@@<[}.",
+"|12}3@@@]@4@5678.",
+"9@@@}2}@@@0ab}c..",
+"..dee@@}}.f}g.. ",
+" h..he@@i!.. ",
+" hj.... "};
diff --git a/joystickA.xpm b/joystickA.xpm
new file mode 100644
index 0000000..9e41b76
--- /dev/null
+++ b/joystickA.xpm
@@ -0,0 +1,45 @@
+/* XPM */
+static char * joystickA_xpm[] = {
+"17 16 26 1",
+" c None",
+". c #000000",
+"+ c #008200",
+"@ c #00FF08",
+"# c #003300",
+"$ c #4C4C4C",
+"% c #323232",
+"& c #464646",
+"* c #252525",
+"= c #474747",
+"- c #00C400",
+"; c #7C0000",
+"> c #380000",
+", c #8A8A8A",
+"' c #026602",
+") c #009E00",
+"! c #800000",
+"~ c #603B3B",
+"{ c #81ABAB",
+"] c #004400",
+"^ c #4E4E4E",
+"/ c #005600",
+"( c #131313",
+"_ c #181818",
+": c #AAAAAA",
+"< c #070707",
+" .. ",
+" +@@. ",
+" +@#. ",
+" +@#. ",
+" +@#. ",
+" +@#. ",
+" $%+@#.%% ",
+" &%@@+@##@@%%* ",
+" =%---@.@..@;>@@.",
+",@-'')@@.@-@!~@'.",
+"=@@@@+----@@@{]+.",
+"^-]/@@@@'@)@#]/).",
+"(@@@/]'@@@_]/+'..",
+"..]--@@''.]+'.. ",
+" :..+-@@]+.. ",
+" :<.... "};
diff --git a/joystickX.xpm b/joystickX.xpm
new file mode 100644
index 0000000..820e56e
--- /dev/null
+++ b/joystickX.xpm
@@ -0,0 +1,57 @@
+/* XPM */
+static char * joystickX_xpm[] = {
+"17 16 38 1",
+" c None",
+". c #000000",
+"+ c #9C9C9C",
+"@ c #FFFFFF",
+"# c #FF0000",
+"$ c #FF8484",
+"% c #444444",
+"& c #323232",
+"* c #383838",
+"= c #464646",
+"- c #EAEAEA",
+"; c #7C8F8F",
+"> c #252525",
+", c #474747",
+"' c #CACACA",
+") c #E0E0E0",
+"! c #DADADA",
+"~ c #7C0000",
+"{ c #380000",
+"] c #8A8A8A",
+"^ c #DEDEDE",
+"/ c #A4A4A4",
+"( c #603B3B",
+"_ c #4C5858",
+": c #969696",
+"< c #4E4E4E",
+"[ c #E9E9E9",
+"} c #5A5A5A",
+"| c #818181",
+"1 c #BDBDBD",
+"2 c #131313",
+"3 c #8D8D8D",
+"4 c #535353",
+"5 c #696969",
+"6 c #AAAAAA",
+"7 c #E8E8E8",
+"8 c #6A6A6A",
+"9 c #070707",
+" .. ",
+" +@@. ",
+" ##$ +@%.$## ",
+" ###$+@%$### ",
+" ####$@$#### ",
+" $####$####$ ",
+" $#######$& ",
+" *=-$#####$@@;> ",
+" ,')!$#####$~{@@.",
+"]@^/$#######$(@].",
+",@@$####$####$_:.",
+"<[}####$@$####|1.",
+"2@@###$@@@$###3..",
+"..4##$@::.5$##. ",
+" 6..67@@8].. ",
+" 69.... "};
diff --git a/log.txt b/log.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/log.txt
diff --git a/midi.xpm b/midi.xpm
new file mode 100644
index 0000000..cb1215c
--- /dev/null
+++ b/midi.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char * midi_xpm[] = {
+"17 16 5 1",
+" c None",
+". c #000000",
+"+ c #808080",
+"@ c #FFFFFF",
+"# c #C0C0C0",
+" ",
+" ... ... ... ",
+"+++............++",
+"+@@...#...#...#@+",
+"+@@...#...#...#@+",
+"+@@...#...#...#@+",
+"+@@...#...#...#@+",
+"+@@...#...#...#@+",
+"+@@...#...#...#@+",
+"+@@@.##@.##@.##@+",
+"+@@@.#@@.#@@.#@@+",
+"+@@@.#@@.#@@.#@@+",
+"+@@@.#@@.#@@.#@@+",
+"+@@@.#@@.#@@.#@@+",
+".+++.+++.+++.+++.",
+"................."};
diff --git a/midiA.xpm b/midiA.xpm
new file mode 100644
index 0000000..6779a39
--- /dev/null
+++ b/midiA.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char * midiA_xpm[] = {
+"17 16 5 1",
+" c None",
+". c #000000",
+"+ c #045B0E",
+"@ c #00FF08",
+"# c #07BA1F",
+" ",
+" ... ... ... ",
+"+++............++",
+"+@@...#...#...#@+",
+"+@@...#...#...#@+",
+"+@@...#...#...#@+",
+"+@@...#...#...#@+",
+"+@@...#...#...#@+",
+"+@@...#...#...#@+",
+"+@@@.##@.##@.##@+",
+"+@@@.#@@.#@@.#@@+",
+"+@@@.#@@.#@@.#@@+",
+"+@@@.#@@.#@@.#@@+",
+"+@@@.#@@.#@@.#@@+",
+".+++.+++.+++.+++.",
+"................."};
diff --git a/midiX.xpm b/midiX.xpm
new file mode 100644
index 0000000..8ee69f9
--- /dev/null
+++ b/midiX.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char * midiX_xpm[] = {
+"17 16 7 1",
+" c None",
+". c #000000",
+"+ c #808080",
+"@ c #FF0000",
+"# c #FF8484",
+"$ c #FFFFFF",
+"% c #C0C0C0",
+" ",
+" ... ... ... ",
+"+++@@#.....#@@.++",
+"+$$@@@#...#@@@%$+",
+"+$$@@@@#.#@@@@%$+",
+"+$$#@@@@#@@@@#%$+",
+"+$$.#@@@@@@@#.%$+",
+"+$$..#@@@@@#..%$+",
+"+$$..#@@@@@#..%$+",
+"+$$$#@@@@@@@#%%$+",
+"+$$#@@@@#@@@@#$$+",
+"+$$@@@@#.#@@@@$$+",
+"+$$@@@#$.%#@@@$$+",
+"+$$@@#$$.%$#@@$$+",
+".+++.+++.+++.+++.",
+"................."};
diff --git a/src/Makefile.Linux b/src/Makefile.Linux
new file mode 100644
index 0000000..999bc91
--- /dev/null
+++ b/src/Makefile.Linux
@@ -0,0 +1,48 @@
+include makefile
+
+current: all
+
+all: gripd.pd_linux joystickmodule.so midimodule.so
+
+LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer \
+ -Wall -W -Wshadow -Wstrict-prototypes -Werror \
+ -Wno-unused -Wno-parentheses -Wno-switch
+MIDIDEFINES = -D$(MIDIOSSUBTYPE) -DLINUX
+MIDICOMPILEFLAGS = -O6 -I./midiio/include $(MIDIDEFINES)
+MIDILINKFLAGS = -L$(SYSTEMLIBDIR) -lpthread -L./midiio/lib -lmidiio
+ifeq ($(MIDIOSSUBTYPE), ALSA)
+MIDILINKFLAGS += -lasound
+endif
+
+gripd.pd_linux:
+ cc $(LINUXCFLAGS) $(PDINCLUDE) -o gripd.o -c gripd.c
+ ld -export_dynamic -lm -shared -o gripd.pd_linux gripd.o -lc -lm
+ strip --strip-unneeded gripd.pd_linux
+ cp gripd.pd_linux ..
+
+joystickmodule.so:
+ifeq ($(JOYSTICK), TRUE)
+ cc -c joystick.c
+ cc $(LINUXPYTHONINCLUDE) -c -DHAVE_CONFIG_H joystick_wrap.c
+ ld -shared joystick.o joystick_wrap.o -o joystickmodule.so
+ cp joystickmodule.so ..
+endif
+ echo "joystick = "$(JOYSTICK) > ../gripd.opt
+
+midimodule.so:
+ifeq ($(MIDI), TRUE)
+ make -f Makefile.midiioLibrary.$(MIDIOSSUBTYPE)
+ g++ -c $(MIDICOMPILEFLAGS) midi.cpp
+ g++ $(LINUXPYTHONINCLUDE) -c -DHAVE_CONFIG_H midi_wrap.c
+ g++ -shared midi.o midi_wrap.o $(MIDILINKFLAGS) -o midimodule.so
+ cp midimodule.so ..
+endif
+ echo "midi = "$(MIDI) >> ../gripd.opt
+
+linux_clean:
+ rm *.o
+ rm gripd.pd_linux
+ rm joystickmodule.so
+ rm midimodule.so
+ make -f Makefile.midiioLibrary.$(MIDIOSSUBTYPE) clean
+
diff --git a/src/Makefile.NT b/src/Makefile.NT
new file mode 100644
index 0000000..4974592
--- /dev/null
+++ b/src/Makefile.NT
@@ -0,0 +1,86 @@
+!INCLUDE makefile
+
+current: all
+all: gripd.dll joystick.dll midi.dll
+
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
+
+PDNTINCLUDE = /I. /I\tcl\include /I$(PDNTSRCDIR) /I$(VC)\include
+JOYINCLUDE = /I$(PYTHONHOME)\include /I$(VC)\INCLUDE
+MIDIINCLUDE = /I$(PYTHONHOME)\include /I$(VC)\INCLUDE /I.\midiio\include
+PDNTLIB = $(VC)\lib\libc.lib \
+ $(VC)\lib\oldnames.lib \
+ $(VC)\lib\kernel32.lib \
+ $(VC)\lib\wsock32.lib \
+ $(VC)\lib\uuid.lib \
+ $(PDNTLDIR)\pd.lib
+JOYLIBS = $(VC)\LIB\kernel32.lib \
+ $(VC)\LIB\advapi32.lib \
+ $(VC)\LIB\user32.lib \
+ $(VC)\LIB\gdi32.lib \
+ $(VC)\LIB\libcmt.lib \
+ $(VC)\LIB\comdlg32.lib \
+ $(VC)\LIB\oldnames.lib \
+ $(VC)\LIB\winmm.lib \
+ $(VC)\LIB\winspool.lib \
+ $(PYTHONHOME)\libs\python$(PYTHONVER).lib
+MIDILIBS = midiio\lib\midiio.lib \
+ $(PYTHONHOME)\libs\python$(PYTHONVER).lib \
+ $(VC)\lib\kernel32.lib \
+ $(VC)\lib\advapi32.lib \
+ $(VC)\lib\user32.lib \
+ $(VC)\lib\gdi32.lib \
+ $(VC)\lib\comdlg32.lib \
+ $(VC)\lib\oldnames.lib \
+ $(VC)\lib\winmm.lib \
+ $(VC)\lib\winspool.lib
+JOYLOPT = -debug:full -debugtype:cv /NODEFAULTLIB /RELEASE /NOLOGO \
+ /MACHINE:IX86 -entry:_DllMainCRTStartup@12 -dll
+MIDILOPT = -debug:full -debugtype:cv /RELEASE /NOLOGO /NODEFAULTLIB:msvcrt.lib \
+ /MACHINE:IX86 -entry:_DllMainCRTStartup@12 -dll
+
+gripd.dll:
+ cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c gripd.c
+ link /dll /export:gripd_setup gripd.obj $(PDNTLIB)
+ copy gripd.dll ..
+
+joystick.dll:
+!IF "$(JOYSTICK)" == "TRUE"
+ cl /TP /DNT /c $(JOYINCLUDE) joystick.c
+ cl /Z7 /Od /c /nologo /D__WIN32__ $(JOYINCLUDE) joystick_wrap.c
+ link $(JOYLOPT) -out:joystick.dll $(JOYLIBS) joystick_wrap.obj \
+ joystick.obj
+ copy joystick.dll ..
+!ENDIF
+ echo joystick = $(JOYSTICK) > ..\gripd.opt
+
+midi.dll:
+!IF "$(MIDI)" == "TRUE"
+ nmake -f Makefile.midiioLibrary.NT
+ cl /DVISUAL /TP /DNT /c /GX $(MIDIINCLUDE) midi.cpp
+ cl /TP /DVISUAL /Z7 /Od /c /nologo /D__WIN32__ $(MIDIINCLUDE) midi_wrap.c
+ link $(MIDILOPT) -out:midi.dll $(MIDILIBS) midi_wrap.obj midi.obj
+ copy midi.dll ..
+!ENDIF
+ echo midi = $(MIDI) >> ..\gripd.opt
+
+nt_clean:
+ del gripd.obj
+ del gripd.exp
+ del gripd.lib
+ del joystick.pdb
+ del joystick.obj
+ del joystick.lib
+ del joystick.exp
+ del joystick_wrap.obj
+ del midi.pdb
+ del midi.obj
+ del midi.lib
+ del midi.exp
+ del midi_wrap.obj
+ del gripd.dll
+ del joystick.dll
+ del midi.dll
+ nmake -f Makefile.midiioLibrary.NT CLEAN
+
+
diff --git a/src/Makefile.midiioLibrary.ALSA b/src/Makefile.midiioLibrary.ALSA
new file mode 100644
index 0000000..5a5a7b2
--- /dev/null
+++ b/src/Makefile.midiioLibrary.ALSA
@@ -0,0 +1,205 @@
+## midiio library GNU makefile for linux.
+##
+## Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+## Creation Date: Sat Nov 2 19:49:57 PST 2002
+## Last Modified: Sat Nov 2 19:50:00 PST 2002
+## Filename: ...midiio/Makefile.library
+##
+## Description: This Makefile creates the midiio library lib/libmidiio.a
+## for linux, using gcc 2.7.2.1 or higher
+##
+## To run this makefile, type (without quotes) "make -f Makefile.library"
+##
+
+###########################################################################
+# #
+# #
+# Operating System OSTYPEs available in the midiio library compilation: #
+#
+# LINUX = Linux running on intel computers
+# VISUAL = Windows 95/NT using Microsoft Visual C++ 5/6
+# OSX = Apple Mac OS X (10.2 or higher when it is ready)
+#
+# The file "sigConfiguration.h" in the include directory contains additional
+# defines which will be activated by the OS given by the OSTYPE variable
+# below. Look at the sigConfiguration.h file for various things which need
+# to be defined specifically for each OS.
+#
+OSTYPE = LINUX
+
+# The OSSUBTYPE is for determining which type of sound drivers
+# are being used in linux. There are three possibilities:
+# OSSUBTYPE = ALSA # ALSA 0.9 interface (http://www.alsa-project.org)
+# OSSUBTYPE = ALSA05 # ALSA 0.5 interface (http://www.alsa-project.org)
+# OSSUBTYPE = OSS # OSS interface (http://www.4front-tech.com)
+# Note: The Improv library accesses the internal/external MIDI devices
+# in OSS, but only the external MIDI devices in ALSA. OSS can be
+# emulated in ALSA 0.9.
+#
+OSSUBTYPE = ALSA
+
+OBJDIR = ./midiio/obj
+SRCDIR = ./midiio/src
+INCDIR = ./midiio/include
+LIBDIR = ./midiio/lib
+LIBFILE = libmidiio.a
+
+COMPILER = g++
+# MAC OSX 10.2 needs this compiler:
+# COMPILER = g++2
+
+DEFINES = $(addprefix -D,$(OSTYPE)) $(addprefix -D,$(OSSUBTYPE))
+FLAGS = -Wall -c -O3 $(DEFINES) -I$(INCDIR)
+
+# #
+# End of user-modifiable variables. #
+# #
+###########################################################################
+
+
+# setting up the directory paths to search for dependency files
+vpath %.h $(INCDIR):$(SRCDIR)
+vpath %.cpp $(SRCDIR):$(INCDIR)
+vpath %.o $(OBJDIR)
+
+# generating a list of the object files
+OBJS = $(notdir $(patsubst %.cpp,%.o,$(wildcard $(SRCDIR)/*.cpp)))
+
+# targets which don't actually refer to files
+.PHONY : all linux makeobjdir
+
+
+###########################################################################
+# #
+# Hardware Configurations: #
+# #
+
+all: makeobjdir $(OBJS)
+
+ ifeq ($(OSTYPE),LINUX)
+ @echo Making midiio library file for linux ...
+ -mkdir -p $(LIBDIR)
+ -rm -f $(LIBDIR)/$(LIBFILE)
+ ar r $(LIBDIR)/$(LIBFILE) $(OBJDIR)/*.o
+ ranlib $(LIBDIR)/$(LIBFILE)
+ endif
+
+ ifeq ($(OSTYPE),VISUAL)
+ echo "this makefile doesn't work with Visual C++."
+ endif
+
+clean:
+ @echo Erasing object files:
+ -rm -f $(OBJDIR)/*.o
+ @echo Erasing obj directory:
+ -rmdir $(OBJDIR)
+
+makeobjdir:
+ -mkdir -p $(OBJDIR)
+
+# defining an explicit rule for object file dependencies
+%.o : %.cpp
+ $(COMPILER) $(FLAGS) -o $(OBJDIR)/$(notdir $@) $<
+
+
+# #
+###########################################################################
+
+
+
+###########################################################################
+# #
+# Dependencies -- generated with the following command in #
+# the src directory (in csh shell): #
+# #
+# foreach i (*.cpp) #
+# cc -I../include -MM $i | sed 's/\.\.\/include\///g' #
+# echo "" #
+# end #
+# #
+
+FileIO.o: FileIO.cpp FileIO.h sigConfiguration.h
+
+MidiFile.o: MidiFile.cpp MidiFile.h FileIO.h Array.h Collection.h \
+ Collection.cpp Array.cpp
+
+MidiFileWrite.o: MidiFileWrite.cpp MidiFileWrite.h FileIO.h SigTimer.h
+
+MidiIO.o: MidiIO.cpp MidiIO.h MidiInput.h MidiInPort.h MidiMessage.h \
+ MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \
+ Array.h Collection.h Collection.cpp Array.cpp MidiOutput.h MidiOutPort.h \
+ MidiOutPort_unsupported.h FileIO.h SigTimer.h
+
+MidiInPort_alsa.o: MidiInPort_alsa.cpp
+
+MidiInPort_alsa05.o: MidiInPort_alsa05.cpp
+
+MidiInPort_linux.o: MidiInPort_linux.cpp
+
+MidiInPort_oss.o: MidiInPort_oss.cpp
+
+MidiInPort_unsupported.o: MidiInPort_unsupported.cpp \
+ MidiInPort_unsupported.h MidiMessage.h CircularBuffer.h \
+ CircularBuffer.cpp Array.h Collection.h Collection.cpp \
+ Array.cpp
+
+MidiInPort_visual.o: MidiInPort_visual.cpp
+
+MidiInput.o: MidiInput.cpp MidiInput.h MidiInPort.h MidiMessage.h \
+ MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \
+ Array.h Collection.h Collection.cpp Array.cpp
+
+MidiMessage.o: MidiMessage.cpp MidiMessage.h
+
+MidiOutPort_alsa.o: MidiOutPort_alsa.cpp
+
+MidiOutPort_linux.o: MidiOutPort_linux.cpp
+
+MidiOutPort_oss.o: MidiOutPort_oss.cpp
+
+MidiOutPort_unsupported.o: MidiOutPort_unsupported.cpp \
+ MidiOutPort_unsupported.h
+
+MidiOutPort_visual.o: MidiOutPort_visual.cpp
+
+MidiOutput.o: MidiOutput.cpp MidiOutput.h MidiOutPort.h \
+ MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h Collection.h \
+ Collection.cpp Array.cpp
+
+MidiPerform.o: MidiPerform.cpp MidiPerform.h MidiFile.h FileIO.h Array.h \
+ Collection.h Collection.cpp Array.cpp CircularBuffer.h \
+ CircularBuffer.cpp SigTimer.h MidiOutput.h MidiOutPort.h \
+ MidiOutPort_unsupported.h
+
+MidiPort.o: MidiPort.cpp MidiPort.h MidiInPort.h MidiMessage.h \
+ MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \
+ Array.h Collection.h Collection.cpp Array.cpp MidiOutPort.h \
+ MidiOutPort_unsupported.h
+
+MultiStageEvent.o: MultiStageEvent.cpp MultiStageEvent.h Event.h \
+ OneStageEvent.h MidiEvent.h TwoStageEvent.h NoteEvent.h \
+ EventBuffer.h CircularBuffer.h CircularBuffer.cpp MidiOutput.h \
+ MidiOutPort.h MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h \
+ Collection.h Collection.cpp Array.cpp FunctionEvent.h
+
+Options.o: Options.cpp Options.h Array.h Collection.h Collection.cpp \
+ Array.cpp Options_private.h
+
+Options_private.o: Options_private.cpp Options_private.h
+
+Sequencer_alsa.o: Sequencer_alsa.cpp
+
+Sequencer_alsa05.o: Sequencer_alsa05.cpp
+
+Sequencer_oss.o: Sequencer_oss.cpp
+
+SigTimer.o: SigTimer.cpp SigTimer.h
+
+Voice.o: Voice.cpp Voice.h MidiOutput.h MidiOutPort.h \
+ MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h Collection.h \
+ Collection.cpp Array.cpp
+
+
+
+
+
diff --git a/src/Makefile.midiioLibrary.NT b/src/Makefile.midiioLibrary.NT
new file mode 100644
index 0000000..a0900b0
--- /dev/null
+++ b/src/Makefile.midiioLibrary.NT
@@ -0,0 +1,462 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on midiio.dsp
+!IF "$(CFG)" == ""
+CFG = midiio - Win32 Release
+!ENDIF
+
+!IF "$(CFG)" != "midiio - Win32 Release" && "$(CFG)" != "midiio - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "midiio.mak" CFG="midiio - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "midiio - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "midiio - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "midiio - Win32 Release"
+
+OUTDIR=.\midiio\lib
+INTDIR=.\midiio\obj
+# Begin Custom Macros
+OutDir=.\midiio\lib
+# End Custom Macros
+
+ALL : "$(OUTDIR)\midiio.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\Array.obj"
+ -@erase "$(INTDIR)\CircularBuffer.obj"
+ -@erase "$(INTDIR)\Collection.obj"
+ -@erase "$(INTDIR)\FileIO.obj"
+ -@erase "$(INTDIR)\MidiFile.obj"
+ -@erase "$(INTDIR)\MidiFileWrite.obj"
+ -@erase "$(INTDIR)\MidiInPort_alsa.obj"
+ -@erase "$(INTDIR)\MidiInPort_alsa05.obj"
+ -@erase "$(INTDIR)\MidiInPort_linux.obj"
+ -@erase "$(INTDIR)\MidiInPort_oss.obj"
+ -@erase "$(INTDIR)\MidiInPort_unsupported.obj"
+ -@erase "$(INTDIR)\MidiInPort_visual.obj"
+ -@erase "$(INTDIR)\MidiInput.obj"
+ -@erase "$(INTDIR)\MidiIO.obj"
+ -@erase "$(INTDIR)\MidiMessage.obj"
+ -@erase "$(INTDIR)\MidiOutPort_alsa.obj"
+ -@erase "$(INTDIR)\MidiOutPort_linux.obj"
+ -@erase "$(INTDIR)\MidiOutPort_oss.obj"
+ -@erase "$(INTDIR)\MidiOutPort_unsupported.obj"
+ -@erase "$(INTDIR)\MidiOutPort_visual.obj"
+ -@erase "$(INTDIR)\MidiOutput.obj"
+ -@erase "$(INTDIR)\MidiPort.obj"
+ -@erase "$(INTDIR)\Options.obj"
+ -@erase "$(INTDIR)\Options_private.obj"
+ -@erase "$(INTDIR)\Sequencer_alsa.obj"
+ -@erase "$(INTDIR)\Sequencer_alsa05.obj"
+ -@erase "$(INTDIR)\Sequencer_oss.obj"
+ -@erase "$(INTDIR)\SigTimer.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\Voice.obj"
+ -@erase "$(INTDIR)\midiio.pch"
+ -@erase "$(OUTDIR)\midiio.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /I ".\midiio\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "VISUAL" /Fp"$(INTDIR)\midiio.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\midiio.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\midiio.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\Array.obj" \
+ "$(INTDIR)\CircularBuffer.obj" \
+ "$(INTDIR)\Collection.obj" \
+ "$(INTDIR)\FileIO.obj" \
+ "$(INTDIR)\MidiFile.obj" \
+ "$(INTDIR)\MidiFileWrite.obj" \
+ "$(INTDIR)\MidiInPort_alsa.obj" \
+ "$(INTDIR)\MidiInPort_alsa05.obj" \
+ "$(INTDIR)\MidiInPort_linux.obj" \
+ "$(INTDIR)\MidiInPort_oss.obj" \
+ "$(INTDIR)\MidiInPort_unsupported.obj" \
+ "$(INTDIR)\MidiInPort_visual.obj" \
+ "$(INTDIR)\MidiInput.obj" \
+ "$(INTDIR)\MidiIO.obj" \
+ "$(INTDIR)\MidiMessage.obj" \
+ "$(INTDIR)\MidiOutPort_alsa.obj" \
+ "$(INTDIR)\MidiOutPort_linux.obj" \
+ "$(INTDIR)\MidiOutPort_oss.obj" \
+ "$(INTDIR)\MidiOutPort_unsupported.obj" \
+ "$(INTDIR)\MidiOutPort_visual.obj" \
+ "$(INTDIR)\MidiOutput.obj" \
+ "$(INTDIR)\MidiPort.obj" \
+ "$(INTDIR)\Options.obj" \
+ "$(INTDIR)\Options_private.obj" \
+ "$(INTDIR)\Sequencer_alsa.obj" \
+ "$(INTDIR)\Sequencer_alsa05.obj" \
+ "$(INTDIR)\Sequencer_oss.obj" \
+ "$(INTDIR)\SigTimer.obj" \
+ "$(INTDIR)\Voice.obj"
+
+"$(OUTDIR)\midiio.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "midiio - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "$(OUTDIR)\midiio.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\Array.obj"
+ -@erase "$(INTDIR)\CircularBuffer.obj"
+ -@erase "$(INTDIR)\Collection.obj"
+ -@erase "$(INTDIR)\FileIO.obj"
+ -@erase "$(INTDIR)\MidiFile.obj"
+ -@erase "$(INTDIR)\MidiFileWrite.obj"
+ -@erase "$(INTDIR)\MidiInPort_alsa.obj"
+ -@erase "$(INTDIR)\MidiInPort_alsa05.obj"
+ -@erase "$(INTDIR)\MidiInPort_linux.obj"
+ -@erase "$(INTDIR)\MidiInPort_oss.obj"
+ -@erase "$(INTDIR)\MidiInPort_unsupported.obj"
+ -@erase "$(INTDIR)\MidiInPort_visual.obj"
+ -@erase "$(INTDIR)\MidiInput.obj"
+ -@erase "$(INTDIR)\MidiIO.obj"
+ -@erase "$(INTDIR)\MidiMessage.obj"
+ -@erase "$(INTDIR)\MidiOutPort_alsa.obj"
+ -@erase "$(INTDIR)\MidiOutPort_linux.obj"
+ -@erase "$(INTDIR)\MidiOutPort_oss.obj"
+ -@erase "$(INTDIR)\MidiOutPort_unsupported.obj"
+ -@erase "$(INTDIR)\MidiOutPort_visual.obj"
+ -@erase "$(INTDIR)\MidiOutput.obj"
+ -@erase "$(INTDIR)\MidiPort.obj"
+ -@erase "$(INTDIR)\Options.obj"
+ -@erase "$(INTDIR)\Options_private.obj"
+ -@erase "$(INTDIR)\Sequencer_alsa.obj"
+ -@erase "$(INTDIR)\Sequencer_alsa05.obj"
+ -@erase "$(INTDIR)\Sequencer_oss.obj"
+ -@erase "$(INTDIR)\SigTimer.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\Voice.obj"
+ -@erase "$(OUTDIR)\midiio.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MLd /W3 /Gm /GX /ZI /Od /I ".\midiio\include" /D "VISUAL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /Fp"$(INTDIR)\midiio.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\midiio.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\midiio.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\Array.obj" \
+ "$(INTDIR)\CircularBuffer.obj" \
+ "$(INTDIR)\Collection.obj" \
+ "$(INTDIR)\FileIO.obj" \
+ "$(INTDIR)\MidiFile.obj" \
+ "$(INTDIR)\MidiFileWrite.obj" \
+ "$(INTDIR)\MidiInPort_alsa.obj" \
+ "$(INTDIR)\MidiInPort_alsa05.obj" \
+ "$(INTDIR)\MidiInPort_linux.obj" \
+ "$(INTDIR)\MidiInPort_oss.obj" \
+ "$(INTDIR)\MidiInPort_unsupported.obj" \
+ "$(INTDIR)\MidiInPort_visual.obj" \
+ "$(INTDIR)\MidiInput.obj" \
+ "$(INTDIR)\MidiIO.obj" \
+ "$(INTDIR)\MidiMessage.obj" \
+ "$(INTDIR)\MidiOutPort_alsa.obj" \
+ "$(INTDIR)\MidiOutPort_linux.obj" \
+ "$(INTDIR)\MidiOutPort_oss.obj" \
+ "$(INTDIR)\MidiOutPort_unsupported.obj" \
+ "$(INTDIR)\MidiOutPort_visual.obj" \
+ "$(INTDIR)\MidiOutput.obj" \
+ "$(INTDIR)\MidiPort.obj" \
+ "$(INTDIR)\Options.obj" \
+ "$(INTDIR)\Options_private.obj" \
+ "$(INTDIR)\Sequencer_alsa.obj" \
+ "$(INTDIR)\Sequencer_alsa05.obj" \
+ "$(INTDIR)\Sequencer_oss.obj" \
+ "$(INTDIR)\SigTimer.obj" \
+ "$(INTDIR)\Voice.obj"
+
+"$(OUTDIR)\midiio.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("midiiolib.dep")
+!INCLUDE "midiiolib.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "midiio - Win32 Release" || "$(CFG)" == "midiio - Win32 Debug"
+SOURCE=".\midiio\include\Array.cpp"
+
+"$(INTDIR)\Array.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Collection.cpp"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\include\CircularBuffer.cpp"
+
+"$(INTDIR)\CircularBuffer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\include\Collection.cpp"
+
+"$(INTDIR)\Collection.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\FileIO.cpp"
+
+"$(INTDIR)\FileIO.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiFile.cpp"
+
+"$(INTDIR)\MidiFile.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiFileWrite.cpp"
+
+"$(INTDIR)\MidiFileWrite.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiInPort_alsa.cpp"
+
+"$(INTDIR)\MidiInPort_alsa.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiInPort_alsa05.cpp"
+
+"$(INTDIR)\MidiInPort_alsa05.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiInPort_linux.cpp"
+
+"$(INTDIR)\MidiInPort_linux.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiInPort_oss.cpp"
+
+"$(INTDIR)\MidiInPort_oss.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiInPort_unsupported.cpp"
+
+"$(INTDIR)\MidiInPort_unsupported.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\CircularBuffer.cpp"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiInPort_visual.cpp"
+
+"$(INTDIR)\MidiInPort_visual.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiInput.cpp"
+
+"$(INTDIR)\MidiInput.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiIO.cpp"
+
+"$(INTDIR)\MidiIO.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiMessage.cpp"
+
+"$(INTDIR)\MidiMessage.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiOutPort_alsa.cpp"
+
+"$(INTDIR)\MidiOutPort_alsa.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiOutPort_linux.cpp"
+
+"$(INTDIR)\MidiOutPort_linux.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiOutPort_oss.cpp"
+
+"$(INTDIR)\MidiOutPort_oss.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiOutPort_unsupported.cpp"
+
+"$(INTDIR)\MidiOutPort_unsupported.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiOutPort_visual.cpp"
+
+"$(INTDIR)\MidiOutPort_visual.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiOutput.cpp"
+
+"$(INTDIR)\MidiOutput.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\MidiPort.cpp"
+
+"$(INTDIR)\MidiPort.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\Options.cpp"
+
+"$(INTDIR)\Options.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\Options_private.cpp"
+
+"$(INTDIR)\Options_private.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\Sequencer_alsa.cpp"
+
+"$(INTDIR)\Sequencer_alsa.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\Sequencer_alsa05.cpp"
+
+"$(INTDIR)\Sequencer_alsa05.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\Sequencer_oss.cpp"
+
+"$(INTDIR)\Sequencer_oss.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\SigTimer.cpp"
+
+"$(INTDIR)\SigTimer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=".\midiio\src\Voice.cpp"
+
+"$(INTDIR)\Voice.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/src/Makefile.midiioLibrary.OSS b/src/Makefile.midiioLibrary.OSS
new file mode 100644
index 0000000..2f1e6e2
--- /dev/null
+++ b/src/Makefile.midiioLibrary.OSS
@@ -0,0 +1,205 @@
+## midiio library GNU makefile for linux.
+##
+## Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+## Creation Date: Sat Nov 2 19:49:57 PST 2002
+## Last Modified: Sat Nov 2 19:50:00 PST 2002
+## Filename: ...midiio/Makefile.library
+##
+## Description: This Makefile creates the midiio library lib/libmidiio.a
+## for linux, using gcc 2.7.2.1 or higher
+##
+## To run this makefile, type (without quotes) "make -f Makefile.library"
+##
+
+###########################################################################
+# #
+# #
+# Operating System OSTYPEs available in the midiio library compilation: #
+#
+# LINUX = Linux running on intel computers
+# VISUAL = Windows 95/NT using Microsoft Visual C++ 5/6
+# OSX = Apple Mac OS X (10.2 or higher when it is ready)
+#
+# The file "sigConfiguration.h" in the include directory contains additional
+# defines which will be activated by the OS given by the OSTYPE variable
+# below. Look at the sigConfiguration.h file for various things which need
+# to be defined specifically for each OS.
+#
+OSTYPE = LINUX
+
+# The OSSUBTYPE is for determining which type of sound drivers
+# are being used in linux. There are three possibilities:
+# OSSUBTYPE = ALSA # ALSA 0.9 interface (http://www.alsa-project.org)
+# OSSUBTYPE = ALSA05 # ALSA 0.5 interface (http://www.alsa-project.org)
+# OSSUBTYPE = OSS # OSS interface (http://www.4front-tech.com)
+# Note: The Improv library accesses the internal/external MIDI devices
+# in OSS, but only the external MIDI devices in ALSA. OSS can be
+# emulated in ALSA 0.9.
+#
+OSSUBTYPE = OSS
+
+OBJDIR = ./midiio/obj
+SRCDIR = ./midiio/src
+INCDIR = ./midiio/include
+LIBDIR = ./midiio/lib
+LIBFILE = libmidiio.a
+
+COMPILER = g++
+# MAC OSX 10.2 needs this compiler:
+# COMPILER = g++2
+
+DEFINES = $(addprefix -D,$(OSTYPE)) $(addprefix -D,$(OSSUBTYPE))
+FLAGS = -Wall -c -O3 $(DEFINES) -I$(INCDIR)
+
+# #
+# End of user-modifiable variables. #
+# #
+###########################################################################
+
+
+# setting up the directory paths to search for dependency files
+vpath %.h $(INCDIR):$(SRCDIR)
+vpath %.cpp $(SRCDIR):$(INCDIR)
+vpath %.o $(OBJDIR)
+
+# generating a list of the object files
+OBJS = $(notdir $(patsubst %.cpp,%.o,$(wildcard $(SRCDIR)/*.cpp)))
+
+# targets which don't actually refer to files
+.PHONY : all linux makeobjdir
+
+
+###########################################################################
+# #
+# Hardware Configurations: #
+# #
+
+all: makeobjdir $(OBJS)
+
+ ifeq ($(OSTYPE),LINUX)
+ @echo Making midiio library file for linux ...
+ -mkdir -p $(LIBDIR)
+ -rm -f $(LIBDIR)/$(LIBFILE)
+ ar r $(LIBDIR)/$(LIBFILE) $(OBJDIR)/*.o
+ ranlib $(LIBDIR)/$(LIBFILE)
+ endif
+
+ ifeq ($(OSTYPE),VISUAL)
+ echo "this makefile doesn't work with Visual C++."
+ endif
+
+clean:
+ @echo Erasing object files:
+ -rm -f $(OBJDIR)/*.o
+ @echo Erasing obj directory:
+ -rmdir $(OBJDIR)
+
+makeobjdir:
+ -mkdir -p $(OBJDIR)
+
+# defining an explicit rule for object file dependencies
+%.o : %.cpp
+ $(COMPILER) $(FLAGS) -o $(OBJDIR)/$(notdir $@) $<
+
+
+# #
+###########################################################################
+
+
+
+###########################################################################
+# #
+# Dependencies -- generated with the following command in #
+# the src directory (in csh shell): #
+# #
+# foreach i (*.cpp) #
+# cc -I../include -MM $i | sed 's/\.\.\/include\///g' #
+# echo "" #
+# end #
+# #
+
+FileIO.o: FileIO.cpp FileIO.h sigConfiguration.h
+
+MidiFile.o: MidiFile.cpp MidiFile.h FileIO.h Array.h Collection.h \
+ Collection.cpp Array.cpp
+
+MidiFileWrite.o: MidiFileWrite.cpp MidiFileWrite.h FileIO.h SigTimer.h
+
+MidiIO.o: MidiIO.cpp MidiIO.h MidiInput.h MidiInPort.h MidiMessage.h \
+ MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \
+ Array.h Collection.h Collection.cpp Array.cpp MidiOutput.h MidiOutPort.h \
+ MidiOutPort_unsupported.h FileIO.h SigTimer.h
+
+MidiInPort_alsa.o: MidiInPort_alsa.cpp
+
+MidiInPort_alsa05.o: MidiInPort_alsa05.cpp
+
+MidiInPort_linux.o: MidiInPort_linux.cpp
+
+MidiInPort_oss.o: MidiInPort_oss.cpp
+
+MidiInPort_unsupported.o: MidiInPort_unsupported.cpp \
+ MidiInPort_unsupported.h MidiMessage.h CircularBuffer.h \
+ CircularBuffer.cpp Array.h Collection.h Collection.cpp \
+ Array.cpp
+
+MidiInPort_visual.o: MidiInPort_visual.cpp
+
+MidiInput.o: MidiInput.cpp MidiInput.h MidiInPort.h MidiMessage.h \
+ MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \
+ Array.h Collection.h Collection.cpp Array.cpp
+
+MidiMessage.o: MidiMessage.cpp MidiMessage.h
+
+MidiOutPort_alsa.o: MidiOutPort_alsa.cpp
+
+MidiOutPort_linux.o: MidiOutPort_linux.cpp
+
+MidiOutPort_oss.o: MidiOutPort_oss.cpp
+
+MidiOutPort_unsupported.o: MidiOutPort_unsupported.cpp \
+ MidiOutPort_unsupported.h
+
+MidiOutPort_visual.o: MidiOutPort_visual.cpp
+
+MidiOutput.o: MidiOutput.cpp MidiOutput.h MidiOutPort.h \
+ MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h Collection.h \
+ Collection.cpp Array.cpp
+
+MidiPerform.o: MidiPerform.cpp MidiPerform.h MidiFile.h FileIO.h Array.h \
+ Collection.h Collection.cpp Array.cpp CircularBuffer.h \
+ CircularBuffer.cpp SigTimer.h MidiOutput.h MidiOutPort.h \
+ MidiOutPort_unsupported.h
+
+MidiPort.o: MidiPort.cpp MidiPort.h MidiInPort.h MidiMessage.h \
+ MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \
+ Array.h Collection.h Collection.cpp Array.cpp MidiOutPort.h \
+ MidiOutPort_unsupported.h
+
+MultiStageEvent.o: MultiStageEvent.cpp MultiStageEvent.h Event.h \
+ OneStageEvent.h MidiEvent.h TwoStageEvent.h NoteEvent.h \
+ EventBuffer.h CircularBuffer.h CircularBuffer.cpp MidiOutput.h \
+ MidiOutPort.h MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h \
+ Collection.h Collection.cpp Array.cpp FunctionEvent.h
+
+Options.o: Options.cpp Options.h Array.h Collection.h Collection.cpp \
+ Array.cpp Options_private.h
+
+Options_private.o: Options_private.cpp Options_private.h
+
+Sequencer_alsa.o: Sequencer_alsa.cpp
+
+Sequencer_alsa05.o: Sequencer_alsa05.cpp
+
+Sequencer_oss.o: Sequencer_oss.cpp
+
+SigTimer.o: SigTimer.cpp SigTimer.h
+
+Voice.o: Voice.cpp Voice.h MidiOutput.h MidiOutPort.h \
+ MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h Collection.h \
+ Collection.cpp Array.cpp
+
+
+
+
+
diff --git a/src/gripd.c b/src/gripd.c
new file mode 100644
index 0000000..fce1aa5
--- /dev/null
+++ b/src/gripd.c
@@ -0,0 +1,1031 @@
+/* GrIPD v0.1. - Graphical Interface for Pure Data
+** Copyright (C) 2003 Joseph A. Sarlo
+**
+** This program is free software; you can redistribute it and/orsig
+** modify it under the terms of the GNU General Public License
+** as published by the Free Software Foundation; either version 2
+** of the License, or (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** jsarlo@ucsd.edu
+*/
+
+#include "gripd.h"
+
+void gripd_setup(void)
+{
+ post (" \n");
+ post (" .______________________________________.");
+ post (" | |");
+ post (" | GrIPD: v%s |", VERSION);
+ post (" | Graphical Interface for Pure Data |");
+ post (" | (C) Copyright 2003 Joseph A. Sarlo |");
+ post (" | GNU General Public License |");
+ post (" |______________________________________|");
+ post (" \n");
+#ifndef NT
+ signal(SIGCHLD, gripd_sigChild);
+#endif
+ gripd_class = class_new(gensym("gripd"), (t_newmethod)gripd_new,
+ (t_method)gripd_free, sizeof(t_gripd), 0,
+ A_DEFFLOAT, 0);
+ gripdRcvr_class = class_new(gensym("gripdRcvr"),0,0,sizeof(t_gripd),
+ 0, 0);
+ class_addmethod(gripd_class, (t_method)gripd_connect,
+ gensym("connect"), 0);
+ class_addmethod(gripd_class, (t_method)gripd_disconnect,
+ gensym("disconnect"), 0);
+ class_addmethod(gripd_class, (t_method)gripd_open,
+ gensym("open"), A_GIMME, 0);
+ class_addmethod(gripd_class, (t_method)gripd_openLocked,
+ gensym("open_locked"), A_GIMME, 0);
+ class_addmethod(gripd_class, (t_method)gripd_setPythonPath,
+ gensym("set_python_path"), A_GIMME, 0);
+ class_addmethod(gripd_class, (t_method)gripd_setPath,
+ gensym("set_path"), A_GIMME, 0);
+ class_addmethod(gripd_class, (t_method)gripd_setSTime,
+ gensym("poll_send"), A_DEFFLOAT, 0);
+ class_addmethod(gripd_class, (t_method)gripd_setRTime,
+ gensym("poll_receive"), A_DEFFLOAT, 0);
+ class_addmethod(gripd_class, (t_method)gripd_lock,
+ gensym("lock"), 0);
+ class_addmethod(gripd_class, (t_method)gripd_unlock,
+ gensym("unlock"), 0);
+ class_addmethod(gripd_class, (t_method)gripd_setTitle,
+ gensym("set_title"), A_GIMME, 0);
+ class_addmethod(gripd_class, (t_method)gripd_hide,
+ gensym("hide"), A_GIMME, 0);
+ class_addmethod(gripd_class, (t_method)gripd_show,
+ gensym("show"), A_GIMME, 0);
+ class_addmethod(gripd_class, (t_method)gripd_openpanel,
+ gensym("openpanel"), A_GIMME, 0);
+ class_addmethod(gripd_class, (t_method)gripd_savepanel,
+ gensym("savepanel"), A_GIMME, 0);
+ class_addbang(gripdRcvr_class, (t_method)gripdR_bang);
+ class_addfloat(gripdRcvr_class, (t_method)gripdR_float);
+ class_addsymbol(gripdRcvr_class, (t_method)gripdR_symbol);
+ class_addanything(gripdRcvr_class, (t_method)gripdR_anything);
+ class_addlist(gripdRcvr_class, (t_method)gripdR_list);
+}
+
+void *gripd_new(t_floatarg port)
+{
+ t_gripd *x = (t_gripd *)pd_new(gripd_class);
+
+ if (port == 0)
+ x->x_port = DEFPORT;
+ else
+ x->x_port = (int)port;
+ x->x_bound = 0;
+ x->x_connected = 0;
+#ifdef NT
+ x->x_localOpened = (int *)malloc(sizeof(int));
+#else
+ x->x_childPID = 0;
+ x->x_localOpened = (int *)shmat(shmget(IPC_PRIVATE,sizeof(int),
+ IPC_CREAT | SHM_R | SHM_W), 0,
+ 0);
+#endif
+ *(x->x_localOpened) = 0;
+ x->x_rdeltime = DEFRDELTIME;
+ x->x_sdeltime = DEFSDELTIME;
+ x->x_rclock = clock_new(x, (t_method)gripd_recv);
+ x->x_sclock = clock_new(x, (t_method)gripd_send);
+ x->x_connectionClock = clock_new(x, (t_method)gripd_trySocket);
+ x->x_bindClock = clock_new(x, (t_method)gripd_connect);
+#ifdef NT
+ strcpy(x->x_pythExec, "c:\\program files\\python\\");
+ strcpy(x->x_pythFile, "..\\gripd\\");
+ x->x_wsockInitByMe = 0;
+#else
+ strcpy(x->x_pythExec, "");
+ strcpy(x->x_pythFile, "../gripd/");
+#endif
+ x->x_rcvrListMaxSize = DEFLISTSIZE;
+ x->x_rcvrs = (t_gripdRcvr **)calloc(x->x_rcvrListMaxSize,
+ sizeof(t_gripdRcvr *));
+ x->x_rcvrListSize = 0;
+ x->x_sendBuffer[0] = '\0';
+ outlet_new(&x->t_ob, &s_float);
+ x->x_outlet2 = outlet_new(&x->t_ob, &s_float);
+ gripd_getApplicationPath(x);
+ return (void *)x;
+}
+
+void gripd_connect(t_gripd *x)
+{
+ gripd_openSocket(x);
+ clock_delay(x->x_rclock, x->x_rdeltime);
+ clock_delay(x->x_sclock, x->x_sdeltime);
+}
+
+void gripd_openSocket(t_gripd *x)
+{
+#ifdef NT
+ char my_name[DEFSTRSIZE];
+ struct sockaddr_in my_addr;
+ struct sockaddr_in new_addr;
+ struct hostent *hp;
+ WSADATA wsaData;
+ int nSize, temp = 1;
+ unsigned long on = 1;
+
+ if (!x->x_bound)
+ {
+ memset(&my_addr, 0, sizeof(struct sockaddr_in));
+ memset(&new_addr, 0, sizeof(struct sockaddr_in));
+ gethostname(my_name, sizeof(my_name));
+ hp = gethostbyname(my_name);
+ if (hp == NULL)
+ {
+ if (WSAGetLastError() == WSANOTINITIALISED)
+ {
+ if (WSAStartup (MAKEWORD(1,1), &wsaData) != 0)
+ post("GrIPD: Failed to initialize winsock");
+ else
+ {
+ x->x_wsockInitByMe = 1;
+ gripd_openSocket(x);
+ return;
+ }
+ }
+ else
+ {
+ post("GrIPD: Gethostname Error %d", WSAGetLastError());
+ gripd_disconnect(x);
+ }
+ }
+ my_addr.sin_family = hp->h_addrtype;
+ my_addr.sin_port = htons(x->x_port);
+ x->x_sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (x->x_sock == INVALID_SOCKET)
+ {
+ post("GrIPD: Socket Error %d", WSAGetLastError());
+ gripd_disconnect(x);
+ }
+ else
+ {
+ ioctlsocket(x->x_sock, FIONBIO, &on);
+ setsockopt(x->x_sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&temp, sizeof(temp));
+ }
+ if (bind(x->x_sock, (struct sockaddr *)&my_addr,
+ sizeof(struct sockaddr)) == SOCKET_ERROR)
+ {
+ post("GrIPD: Bind Error %d", WSAGetLastError());
+ post("GrIPD: Attempting to re-bind");
+ clock_delay(x->x_bindClock, REBINDTIME);
+ }
+ else
+ {
+ nSize = sizeof(struct sockaddr_in);
+ getsockname(x->x_sock, (struct sockaddr *)&new_addr, &nSize);
+ x->x_port = (int)ntohs(new_addr.sin_port);
+ post("GrIPD: Using port %d", x->x_port);
+ x->x_bound = 1;
+ listen(x->x_sock, BACKLOG);
+ post("GrIPD: Waiting for a connection...");
+ clock_delay(x->x_connectionClock, CONNECTIONPOLLTIME);
+ }
+ }
+ else
+ post("GrIPD: Already waiting for a connection");
+#else
+ char portstr[MAXPORTSTRLEN];
+ struct sockaddr_in my_addr, new_addr;
+ int nSize, temp = 1;
+
+ if (!x->x_bound)
+ {
+ x->x_sock = -1;
+ if ((x->x_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+ perror("GrIPD: Socket Error");
+ gripd_disconnect(x);
+ }
+ setsockopt(x->x_sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&temp, sizeof(temp));
+ fcntl(x->x_sock, F_SETFL, O_NONBLOCK);
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_port = htons(x->x_port);
+ my_addr.sin_addr.s_addr = INADDR_ANY;
+ bzero(&(my_addr.sin_zero), 8);
+ if (bind(x->x_sock, (struct sockaddr *)&my_addr,
+ sizeof(struct sockaddr)) == -1)
+ {
+ perror("GrIPD: Bind Error");
+ clock_delay(x->x_bindClock, REBINDTIME);
+ }
+ else
+ {
+ nSize = sizeof(struct sockaddr_in);
+ getsockname(x->x_sock, (struct sockaddr *)&new_addr, &nSize);
+ x->x_port = ntohs(new_addr.sin_port);
+ post("GrIPD: Using port %d", x->x_port);
+ x->x_bound = 1;
+ if (listen(x->x_sock, BACKLOG) == -1)
+ {
+ perror("GrIPD: Listen Error");
+ gripd_disconnect(x);
+ }
+ post("GrIPD: Waiting for a connection...");
+ clock_delay(x->x_connectionClock, CONNECTIONPOLLTIME);
+ }
+ }
+ else
+ post("GrIPD: Already waiting for a connection");
+#endif
+}
+
+void gripd_disconnect(t_gripd *x)
+{
+ int numbytes;
+ char buf[MAXDATASIZE];
+
+ clock_unset(x->x_sclock);
+ clock_unset(x->x_rclock);
+ clock_unset(x->x_bindClock);
+ clock_unset(x->x_connectionClock);
+ if (*(x->x_localOpened))
+ {
+ gripd_closePyth(x);
+ }
+ else
+ {
+ sprintf(buf, "%s%c0%c", CLOSECOMMAND, SYMMSGSEP, PAIRSEPCHAR);
+ send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL);
+ numbytes = recv(x->x_newSock, buf, MAXDATASIZE, MSG_NOSIGNAL);
+ }
+ if (x->x_bound)
+ {
+ gripd_closeSocket(x);
+ }
+}
+
+void gripd_trySocket(t_gripd *x)
+{
+#ifdef NT
+ fd_set rfds;
+ struct timeval tv;
+ unsigned long on;
+
+ on = 1;
+ tv.tv_sec = 0;
+ tv.tv_usec = WAITTIME;
+ FD_ZERO(&rfds);
+ FD_SET(x->x_sock, &rfds);
+ if (select(x->x_sock + 1, &rfds, NULL, NULL, &tv) > 0)
+ {
+ x->x_newSock = accept(x->x_sock, NULL, NULL);
+ if (x->x_newSock == INVALID_SOCKET)
+ {
+ post("GrIPD: Accept Error %d", WSAGetLastError());
+ gripd_disconnect(x);
+ }
+ else
+ {
+ ioctlsocket(x->x_newSock, FIONBIO, &on);
+ x->x_connected = 1;
+ outlet_float(x->t_ob.ob_outlet, 1);
+ post("GrIPD: Connected");
+ }
+ }
+ else
+ clock_delay(x->x_connectionClock, CONNECTIONPOLLTIME);
+#else
+ fd_set rfds;
+ struct timeval tv;
+ struct sockaddr_in their_addr;
+ int new_fd, sin_size;
+
+ sin_size = sizeof(struct sockaddr_in);
+ tv.tv_sec = 0;
+ tv.tv_usec = WAITTIME;
+ FD_ZERO(&rfds);
+ FD_SET(x->x_sock, &rfds);
+ if (select(x->x_sock + 1, &rfds, NULL, NULL, &tv))
+ {
+ if ((x->x_newSock = accept(x->x_sock,
+ (struct sockaddr *)&their_addr,
+ &sin_size)) == -1)
+ {
+ perror("GrIPD: Accept Error");
+ gripd_disconnect(x);
+ }
+ else
+ {
+ x->x_connected = 1;
+ outlet_float(x->t_ob.ob_outlet, 1);
+ post("GrIPD: Connected");
+ }
+ }
+ else
+ clock_delay(x->x_connectionClock, CONNECTIONPOLLTIME);
+#endif
+}
+
+void gripd_closeSocket(t_gripd *x)
+{
+#ifdef NT
+ closesocket(x->x_newSock);
+ closesocket(x->x_sock);
+#else
+ shutdown(x->x_newSock, 2);
+ close(x->x_newSock);
+ shutdown(x->x_sock, 2);
+ close(x->x_sock);
+#endif
+ x->x_bound = 0;
+ x->x_connected = 0;
+ *(x->x_localOpened) = 0;
+ outlet_float(x->t_ob.ob_outlet, 0);
+ outlet_float(x->x_outlet2, 0);
+}
+
+void gripd_recv(t_gripd *x)
+{
+ int numbytes, count, idx, i, j, argc;
+ char buf[MAXDATASIZE], symName[MAXSYMNAMELEN],
+ symValue[MAXSYMVALUELEN],
+ tempString[MAXDATASIZE];
+ t_symbol *tempSym;
+ t_atom atomList[MAXALISTLEN];
+ numbytes = count = idx = i = j = argc = 0;
+ tempSym = gensym("");
+
+ if (x->x_connected)
+ {
+ numbytes = recv(x->x_newSock, buf, MAXDATASIZE,
+ MSG_DONTWAIT | MSG_NOSIGNAL);
+ if (numbytes > 0)
+ {
+ buf[numbytes] = '\0';
+ while (count <= numbytes)
+ {
+ while ((buf[count] != SYMMSGSEP) && (count <= numbytes))
+ {
+ symName[i] = buf[count];
+ count++;
+ i++;
+ }
+ symName[i] = '\0';
+ i = 0;
+ count++;
+ while ((buf[count] != PAIRSEPCHAR) && (count <= numbytes))
+ {
+ symValue[i] = buf[count];
+ count ++;
+ i++;
+ }
+ symValue[i] = '\0';
+ count++;
+ i = 0;
+ if (symName[0] == COMMANDCHAR)
+ {
+ if ((strcmp(SETRCVRSTRING, symName) == 0) \
+ && (gripd_checkExistance(x, symValue) == 0))
+ {
+ if (x->x_rcvrListSize \
+ == (x->x_rcvrListMaxSize - 1))
+ gripd_expandRcvrList(x);
+ gripd_makeGripdRcvr(x, gensym(symValue));
+ x->x_rcvrListSize++;
+ }
+ if (strcmp(CLOSECOMMAND, symName) == 0)
+ {
+ post("GrIPD: Connection closed remotely");
+ gripd_disconnect(x);
+ }
+ if (strcmp(HIDECOMMAND, symName) == 0)
+ {
+ outlet_float(x->x_outlet2, 0);
+ }
+ if (strcmp(SHOWCOMMAND, symName) == 0)
+ {
+ outlet_float(x->x_outlet2, 1);
+ }
+ if (strcmp(PINGCOMMAND, symName) == 0)
+ {
+ char pingCommandStr[64];
+
+ sprintf(pingCommandStr,
+ "%s%c0%c",
+ PINGCOMMAND,
+ SYMMSGSEP,
+ PAIRSEPCHAR);
+ gripd_appendSendBuffer(x, pingCommandStr);
+ gripd_send(x);
+ }
+ }
+ else
+ {
+ tempSym = gensym(symName);
+ if (tempSym->s_thing)
+ {
+ if (strcmp(BANGSTRING, symValue) == 0)
+ pd_bang(tempSym->s_thing);
+ else
+ {
+ if (strchr(symValue, ' ') == NULL)
+ {
+ if (gripd_isNumeric(symValue))
+ pd_float(tempSym->s_thing,
+ (float)atof(symValue));
+ else
+ typedmess(tempSym->s_thing,
+ gensym(symValue),
+ 0,
+ NULL);
+ }
+ else
+ {
+ idx = 0;
+ argc = 0;
+ for (j = 0; j < (int)strlen(symValue); j++)
+ {
+ if (symValue[j] != ' ')
+ {
+ tempString[idx] = symValue[j];
+ idx++;
+ }
+ if ((symValue[j] == ' ')
+ || (j == (int)strlen(symValue) -1))
+ {
+ tempString[idx] = '\0';
+ if (gripd_isNumeric(tempString))
+ {
+ atomList[argc].a_type = A_FLOAT;
+ atomList[argc].a_w.w_float =
+ (float)atof(tempString);
+ }
+ else
+ {
+ atomList[argc].a_type = A_SYMBOL;
+ atomList[argc].a_w.w_symbol
+ = gensym(tempString);
+ }
+ argc++;
+ idx = 0;
+ }
+ }
+ if (atomList[0].a_type == A_FLOAT)
+ pd_list(tempSym->s_thing,
+ atomList[0].a_w.w_symbol,
+ argc, atomList);
+ else
+ typedmess(tempSym->s_thing,
+ atomList[0].a_w.w_symbol,
+ argc - 1, &(atomList[1]));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ clock_delay(x->x_rclock, x->x_rdeltime);
+}
+
+void gripd_send(t_gripd *x)
+{
+ int charsSent, endPos;
+ if (x->x_connected && (strlen(x->x_sendBuffer) > 0))
+ {
+ charsSent = send(x->x_newSock, x->x_sendBuffer,
+ strlen(x->x_sendBuffer),
+ MSG_DONTWAIT | MSG_NOSIGNAL);
+ if (charsSent == SOCKET_ERROR)
+ {
+ post("GrIPD: Client is not responding");
+ gripd_disconnect(x);
+ return;
+ }
+ else if ((charsSent <= (signed int)strlen(x->x_sendBuffer)) &&
+ (charsSent > -1))
+ {
+ endPos = strlen(x->x_sendBuffer) - charsSent;
+ strcpy(x->x_sendBuffer, &(x->x_sendBuffer[charsSent]));
+ x->x_sendBuffer[endPos] = '\0';
+ }
+ }
+ clock_delay(x->x_sclock, x->x_sdeltime);
+}
+
+/* this does NOT take care of separator strings, sending function must
+ do that */
+void gripd_appendSendBuffer(t_gripd *x, char *aString)
+{
+ if (x->x_connected)
+ {
+ /* +1 below since strlen does not include '\0' */
+ if ((strlen(x->x_sendBuffer) + strlen(aString)) + 1 > MAXDATASIZE)
+ post("GrIPD: Send buffer overflow");
+ else
+ strcat(x->x_sendBuffer, aString);
+ }
+}
+
+void gripd_open(t_gripd *x, t_symbol *sym, int argc, t_atom *argv)
+{
+ gripd_openPyth(x, sym, argc, argv, 0);
+}
+void gripd_openLocked(t_gripd *x, t_symbol *sym, int argc, t_atom *argv)
+{
+ gripd_openPyth(x, sym, argc, argv, 1);
+}
+
+void gripd_openPyth(t_gripd *x, t_symbol *sym, int argc,
+ t_atom *argv, int locked)
+{
+#ifdef NT
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ char pythExec[DEFSTRSIZE], filename[DEFSTRSIZE], tempStr[DEFSTRSIZE];
+ int i;
+
+ if (!x->x_connected && !(*(x->x_localOpened)))
+ {
+ gripd_connect(x);
+ *(x->x_localOpened) = 1;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ ZeroMemory(&pi, sizeof(pi));
+ if (argc > 0)
+ {
+ if (argv[0].a_type == A_SYMBOL)
+ {
+ strcpy(filename, argv[0].a_w.w_symbol->s_name);
+ for (i = 1; i < argc; i++)
+ if (argv[i].a_type == A_SYMBOL)
+ sprintf(filename, "%s %s", filename,
+ argv[i].a_w.w_symbol->s_name);
+ }
+ else
+ strcpy(filename, "0");
+ }
+ else
+ strcpy(filename, "0");
+ for (i = 0; i < (int)strlen(x->x_pythExec); i++)
+ if (x->x_pythExec[i] == '/')
+ x->x_pythExec[i] = '\\';
+ for (i = 0; i < (int)strlen(x->x_pythFile); i++)
+ if (x->x_pythFile[i] == '/')
+ x->x_pythFile[i] = '\\';
+ for (i = 0; i < (int)strlen(filename); i++)
+ if (filename[i] == '/')
+ filename[i] = '\\';
+ if (filename[0] == '.' &&
+ (filename[1] == '\\' ||
+ (filename[1] == '.' && filename[2] == '\\')))
+ {
+ sprintf(tempStr, "%s%s", x->x_appPath, filename);
+ strcpy(filename, tempStr);
+ }
+ if (x->x_pythFile[0] == '.' &&
+ (x->x_pythFile[1] == '\\' ||
+ (x->x_pythFile[1] == '.' && x->x_pythFile[2] == '\\')))
+ {
+ sprintf(tempStr, "%s%s", x->x_appPath, x->x_pythFile);
+ strcpy(x->x_pythFile, tempStr);
+ }
+ sprintf(pythExec, "\"%sgripd.exe\" \"%s\" %d 1 %d", x->x_pythFile,
+ filename, x->x_port, locked);
+ if (!(CreateProcess(NULL, pythExec, NULL, NULL, FALSE, 0, NULL, NULL,
+ &si, &(x->x_childProcessInfo)) != 0))
+ {
+ post("GrIPD: Failed to execute %sgripd.exe", x->x_pythFile);
+ sprintf(pythExec, "\"%spython.exe\" \"%sgripd.py\" \"%s\" %d 1 %d",
+ x->x_pythExec, x->x_pythFile, filename, x->x_port, locked);
+ if (!(CreateProcess(NULL, pythExec, NULL, NULL, FALSE, 0, NULL,
+ NULL, &si, &(x->x_childProcessInfo)) != 0))
+ {
+ post("GrIPD: Failed to execute %spython.exe", x->x_pythExec);
+ gripd_disconnect(x);
+ *(x->x_localOpened) = 0;
+ }
+ }
+ }
+#else
+ char pythExec[DEFSTRSIZE], filename[DEFSTRSIZE], portString[DEFSTRSIZE],
+ lockedString[DEFSTRSIZE], tempStr[DEFSTRSIZE];
+ int i, pid;
+
+ if (!x->x_connected && !(*(x->x_localOpened)))
+ {
+ gripd_connect(x);
+ pid = fork();
+ if (pid == 0)
+ {
+ struct sched_param par;
+ int p1;
+
+ /* Lose setuid priveliges */
+ seteuid(getuid());
+ *(x->x_localOpened) = 1;
+ /* set lowest priority, SCHED_OTHER policy, unlock mem*/
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ p1 = sched_get_priority_min(SCHED_OTHER);
+ par.sched_priority = p1;
+ if (sched_setscheduler(0, SCHED_OTHER, &par) == -1)
+ post("GrIPD: unable to set priority %d scheduling.", p1);
+#endif
+#ifdef _POSIX_MEMLOCK
+ if ((munlockall() == -1) && (!getuid()))
+ post("GrIPD: unable to unlock memory.");
+#endif
+ clock_free(x->x_rclock);
+ clock_free(x->x_sclock);
+ clock_free(x->x_connectionClock);
+ clock_free(x->x_bindClock);
+ for (i = 0; i < x->x_rcvrListSize; i++)
+ pd_unbind(&(x->x_rcvrs[i])->r_obj.ob_pd,
+ x->x_rcvrs[i]->r_sym);
+ free(x->x_rcvrs);
+ sprintf(pythExec, "%sgripd", x->x_pythFile);
+ if (argc > 0)
+ {
+ strcpy(filename, argv[0].a_w.w_symbol->s_name);
+ for (i = 1; i < argc; i++)
+ if (argv[i].a_type == A_SYMBOL)
+ sprintf(filename, "%s %s", filename,
+ argv[i].a_w.w_symbol->s_name);
+ }
+ else
+ strcpy(filename, "0");
+ if (filename[0] == '.' &&
+ (filename[1] == '/' ||
+ (filename[1] == '.' && filename[2] == '/')))
+ {
+ sprintf(tempStr, "%s%s", x->x_appPath, filename);
+ strcpy(filename, tempStr);
+ }
+ if (pythExec[0] == '.' &&
+ (pythExec[1] == '/' ||
+ (pythExec[1] == '.' && pythExec[2] == '/')))
+ {
+ sprintf(tempStr, "%s%s", x->x_appPath, pythExec);
+ strcpy(pythExec, tempStr);
+ }
+ /* set x_localOpened before opened since execlp will exit
+ process on success */
+ sprintf(portString, "%d", x->x_port);
+ sprintf(lockedString, "%d", locked);
+ if ((execlp(pythExec, pythExec, filename, portString,
+ "1", lockedString, (char *)0)) == -1)
+ {
+ post("GrIPD: Error launching %s", pythExec);
+ perror(" ");
+ *(x->x_localOpened) = 0;
+ exit(1);
+ }
+ exit(1);
+ }
+ else
+ {
+ x->x_childPID = pid;
+ }
+ }
+#endif
+ else
+ {
+ gripd_show(x);
+ }
+}
+
+void gripd_closePyth(t_gripd *x)
+{
+ char buf[MAXDATASIZE];
+
+ if (*(x->x_localOpened))
+ {
+ sprintf(buf, "%s%c0%c", CLOSECOMMAND, SYMMSGSEP, PAIRSEPCHAR);
+ send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL);
+ *(x->x_localOpened) = 0;
+#ifdef NT
+ TerminateProcess(x->x_childProcessInfo.hProcess, 0);
+#else
+ kill(x->x_childPID, SIGKILL);
+ x->x_childPID = 0;
+#endif
+ }
+}
+
+void gripd_lock(t_gripd *x)
+{
+ char buf[MAXDATASIZE];
+
+ if (x->x_connected)
+ {
+ sprintf(buf, "%s%c0%c", LOCKCOMMAND, SYMMSGSEP, PAIRSEPCHAR);
+ send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL);
+ }
+}
+
+void gripd_unlock(t_gripd *x)
+{
+ char buf[MAXDATASIZE];
+
+ if (x->x_connected)
+ {
+ sprintf(buf, "%s%c0%c", UNLOCKCOMMAND, SYMMSGSEP, PAIRSEPCHAR);
+ send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL);
+ }
+}
+
+void gripd_hide(t_gripd *x)
+{
+ char buf[MAXDATASIZE];
+
+ if (x->x_connected)
+ {
+ sprintf(buf, "%s%c0%c", HIDECOMMAND, SYMMSGSEP, PAIRSEPCHAR);
+ send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL);
+ }
+}
+
+void gripd_show(t_gripd *x)
+{
+ char buf[MAXDATASIZE];
+
+ if (x->x_connected)
+ {
+ sprintf(buf, "%s%c0%c", SHOWCOMMAND, SYMMSGSEP, PAIRSEPCHAR);
+ send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL);
+ }
+}
+
+void gripd_openpanel(t_gripd *x)
+{
+ char buf[MAXDATASIZE];
+
+ if (x->x_connected)
+ {
+ sprintf(buf, "%s%c0%c", OPENPANELCOMMAND, SYMMSGSEP, PAIRSEPCHAR);
+ send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL);
+ }
+}
+
+void gripd_savepanel(t_gripd *x)
+{
+ char buf[MAXDATASIZE];
+
+ if (x->x_connected)
+ {
+ sprintf(buf, "%s%c0%c", SAVEPANELCOMMAND, SYMMSGSEP, PAIRSEPCHAR);
+ send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL);
+ }
+}
+
+void gripd_setTitle(t_gripd *x, t_symbol *sym, int argc, t_atom *argv)
+{
+ int i;
+ char title[DEFSTRSIZE];
+ char buf[MAXDATASIZE];
+
+ if (x->x_connected) {
+ if (argc > 0)
+ strcpy(title, argv[0].a_w.w_symbol->s_name);
+ for (i = 1; i < argc; i++)
+ if (argv[i].a_type == A_SYMBOL)
+ sprintf(title, "%s %s", title,
+ argv[i].a_w.w_symbol->s_name);
+ sprintf(buf,
+ "%s%c%s%c",
+ SETTITLECOMMAND,
+ SYMMSGSEP,
+ title,
+ PAIRSEPCHAR);
+ send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL);
+ }
+}
+
+void gripd_setPath(t_gripd *x, t_symbol *sym, int argc, t_atom *argv)
+{
+ int i;
+ if (argc > 0)
+ strcpy(x->x_pythFile, argv[0].a_w.w_symbol->s_name);
+ for (i = 1; i < argc; i++)
+ if (argv[i].a_type == A_SYMBOL)
+ sprintf(x->x_pythFile, "%s %s", x->x_pythFile,
+ argv[i].a_w.w_symbol->s_name);
+ sprintf(x->x_pythFile, "%s/", x->x_pythFile);
+}
+
+void gripd_setPythonPath(t_gripd *x, t_symbol *sym, int argc, t_atom *argv)
+{
+ int i;
+ if (argc >0)
+ strcpy(x->x_pythExec, argv[0].a_w.w_symbol->s_name);
+ for (i = 1; i < argc; i++)
+ if (argv[i].a_type == A_SYMBOL)
+ sprintf(x->x_pythExec, "%s %s", x->x_pythExec,
+ argv[i].a_w.w_symbol->s_name);
+ sprintf(x->x_pythExec, "%s/", x->x_pythExec);
+}
+
+void gripd_setSTime(t_gripd *x, t_floatarg val)
+{
+ if (val > 0)
+ x->x_sdeltime = val;
+ else
+ post("GrIPD: Illegal update time");
+}
+
+void gripd_setRTime(t_gripd *x, t_floatarg val)
+{
+ if (val > 0)
+ x->x_rdeltime = val;
+ else
+ post("GrIPD: Illegal update time");
+}
+
+void gripdR_bang(t_gripdRcvr *r)
+{
+ char aString[MAXDATASIZE];
+ char valueString[MAXDATASIZE];
+
+ strcpy(aString, r->r_sym->s_name);
+ sprintf(valueString,"%cbang%c", SYMMSGSEP, PAIRSEPCHAR);
+ strcat(aString, valueString);
+
+ gripd_appendSendBuffer((t_gripd *)(r->r_x), aString);
+}
+
+void gripdR_float(t_gripdRcvr *r, t_float floatValue)
+{
+ char aString[MAXDATASIZE];
+ char valueString[MAXDATASIZE];
+
+ strcpy(aString, r->r_sym->s_name);
+ sprintf(valueString,"%c%g%c", SYMMSGSEP, floatValue, PAIRSEPCHAR);
+ strcat(aString, valueString);
+
+ gripd_appendSendBuffer((t_gripd *)(r->r_x), aString);
+}
+
+void gripdR_symbol(t_gripdRcvr *r, t_symbol *sym)
+{
+ char aString[MAXDATASIZE];
+ char valueString[MAXDATASIZE];
+
+ strcpy(aString, r->r_sym->s_name);
+ sprintf(valueString,"%c%s%c", SYMMSGSEP, sym->s_name, PAIRSEPCHAR);
+ strcat(aString, valueString);
+
+ gripd_appendSendBuffer((t_gripd *)(r->r_x), aString);
+}
+
+void gripdR_anything(t_gripdRcvr *r, t_symbol *sym, int argc, t_atom *argv)
+{
+ char aString[MAXDATASIZE];
+ char valueString[MAXDATASIZE];
+ int i;
+
+ strcpy(aString, r->r_sym->s_name);
+ sprintf(valueString, "%c%s", SYMMSGSEP, sym->s_name);
+ strcat(aString, valueString);
+ for (i = 0; i < argc; i++)
+ {
+ if (argv[i].a_type == A_SYMBOL)
+ {
+ sprintf(valueString, " %s", argv[i].a_w.w_symbol->s_name);
+ strcat(aString, valueString);
+ }
+ else if (argv[i].a_type == A_FLOAT)
+ {
+ sprintf(valueString, " %g", argv[i].a_w.w_float);
+ strcat(aString, valueString);
+ }
+ }
+ sprintf(aString, "%s%c", aString, PAIRSEPCHAR);
+ gripd_appendSendBuffer((t_gripd *)(r->r_x), aString);
+}
+
+void gripdR_list(t_gripdRcvr *r, t_symbol *sym, int argc, t_atom *argv)
+{
+ char aString[MAXDATASIZE];
+ char valueString[MAXDATASIZE];
+ int i;
+
+ strcpy(aString, r->r_sym->s_name);
+ sprintf(valueString, "%c", SYMMSGSEP);
+ strcat(aString, valueString);
+ for (i = 0; i < argc; i++)
+ {
+ if (argv[i].a_type == A_SYMBOL)
+ {
+ sprintf(valueString, " %s", argv[i].a_w.w_symbol->s_name);
+ strcat(aString, valueString);
+ }
+ else if (argv[i].a_type == A_FLOAT)
+ {
+ sprintf(valueString, " %g", argv[i].a_w.w_float);
+ strcat(aString, valueString);
+ }
+ }
+ sprintf(aString, "%s%c", aString, PAIRSEPCHAR);
+ gripd_appendSendBuffer((t_gripd *)(r->r_x), aString);
+}
+
+void gripd_makeGripdRcvr(t_gripd *x, t_symbol *s)
+{
+ t_gripdRcvr *r = (t_gripdRcvr *)pd_new(gripdRcvr_class);
+ r->r_sym = s;
+ pd_bind(&r->r_obj.ob_pd, s);
+ r->r_x = (t_gripd *)x;
+ x->x_rcvrs[x->x_rcvrListSize] = r;
+}
+
+int gripd_checkExistance(t_gripd *x, char *name)
+{
+ int i, flag;
+
+ flag = 0;
+ for (i = 0; i < x->x_rcvrListSize; i++)
+ {
+ if (strcmp(name, x->x_rcvrs[i]->r_sym->s_name) == 0)
+ flag = 1;
+ }
+ return flag;
+}
+
+void gripd_expandRcvrList(t_gripd *x)
+{
+ x->x_rcvrListMaxSize *= 2;
+ x->x_rcvrs = (t_gripdRcvr **)realloc(x->x_rcvrs,
+ x->x_rcvrListMaxSize \
+ * sizeof(t_gripdRcvr *));
+}
+
+void gripd_free(t_gripd *x)
+{
+ int i;
+
+ if (*(x->x_localOpened))
+ gripd_closePyth(x);
+ if (x->x_connected)
+ gripd_disconnect(x);
+ else if (x->x_bound)
+ gripd_closeSocket(x);
+ clock_free(x->x_rclock);
+ clock_free(x->x_sclock);
+ clock_free(x->x_connectionClock);
+ clock_free(x->x_bindClock);
+#ifdef NT
+ free(x->x_localOpened);
+ if (x->x_wsockInitByMe != 0)
+ WSACleanup();
+#endif
+ for (i = 0; i < x->x_rcvrListSize; i++)
+ pd_unbind(&(x->x_rcvrs[i])->r_obj.ob_pd, x->x_rcvrs[i]->r_sym);
+ free(x->x_rcvrs);
+}
+
+int gripd_isNumeric(char *string)
+{
+ if ((strspn(string, "0123456789.+-") == strlen(string)) &&
+ (strchr(string, '+') == strrchr(string, '+')) &&
+ (strchr(string, '-') == strrchr(string, '-')) &&
+ (strchr(string, '.') == strrchr(string, '.')) &&
+ (!((strchr(string, '+') != NULL) &&
+ (strchr(string, '-') != NULL))))
+ return 1;
+ else
+ return 0;
+}
+
+#ifndef NT
+void gripd_sigChild(int sig)
+{
+ wait(NULL);
+}
+#endif
+
+void gripd_getApplicationPath(t_gripd *x)
+{
+ char rawStr[MAXDATASIZE];
+#ifdef NT
+ GetModuleFileName(NULL, rawStr, sizeof(rawStr));
+ rawStr[strrchr(rawStr, '\\') - rawStr + 1] = '\0';
+ strcpy(x->x_appPath, rawStr);
+#else
+ char *pathStr;
+ FILE *fp;
+ fp = fopen("/proc/self/maps", "r");
+ fgets(rawStr, MAXDATASIZE, fp);
+ fclose(fp);
+ pathStr = index(rawStr, '/');
+ pathStr[index(pathStr, '\n') - pathStr] = '\0';
+ pathStr[rindex(pathStr, '/') - pathStr + 1] = '\0';
+ strcpy(x->x_appPath, pathStr);
+#endif
+}
+
diff --git a/src/gripd.h b/src/gripd.h
new file mode 100644
index 0000000..67ef16b
--- /dev/null
+++ b/src/gripd.h
@@ -0,0 +1,227 @@
+/* GrIPD v0.1.1 - Graphical Interface for Pure Data
+** Copyright (C) 2003 Joseph A. Sarlo
+**
+** This program is free software; you can redistribute it and/orsig
+** modify it under the terms of the GNU General Public License
+** as published by the Free Software Foundation; either version 2
+** of the License, or (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** jsarlo@ucsd.edu
+*/
+
+#include "m_pd.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <math.h>
+#ifdef NT
+#include <windows.h>
+#include <winsock.h>
+#else
+#include <signal.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sched.h>
+#include <sys/mman.h>
+#endif
+
+#define VERSION "0.1.1"
+#define DEFPORT 0
+/* maxiumum connections */
+#define BACKLOG 1
+/* max size of send buffer */
+#define MAXDATASIZE 16384
+#define MAXPORTSTRLEN 16
+#define MAXSYMNAMELEN 128
+#define MAXSYMVALUELEN 128
+/* separates send/recv object names from value they send/recv */
+#define SYMMSGSEP 31
+/* separates send/recv value pairs */
+#define PAIRSEPCHAR 29
+#define BANGSTRING "bang"
+/* if 1st char, indicates send/recv name is actually a command */
+#define COMMANDCHAR '!'
+/* command to add value to recv list */
+#define SETRCVRSTRING "!setRcvr"
+/* command to close connection */
+#define CLOSECOMMAND "!disconnect"
+/* command to close python app */
+#define EXITCOMMAND "!exit"
+/* command to lock GUI */
+#define LOCKCOMMAND "!lock"
+/* command to unlock GUI */
+#define UNLOCKCOMMAND "!unlock"
+/* command to set title */
+#define SETTITLECOMMAND "!settitle"
+/* command to hide GUI window */
+#define HIDECOMMAND "!hide"
+/* command to show GUI window */
+#define SHOWCOMMAND "!show"
+/* command for connection status */
+#define PINGCOMMAND "!ping"
+// command to have GUI open a open file dialog
+#define OPENPANELCOMMAND "!openpanel"
+// command to have GUI open a save file dialog
+#define SAVEPANELCOMMAND "!savepanel"
+/* initial size of rcvr object list */
+#define DEFLISTSIZE 16
+/* poll time in ms to re-try accept() */
+#define CONNECTIONPOLLTIME 100
+/* blocking time us for accept() */
+#define WAITTIME 1
+/* poll time in ms to re-try bind after "address already in use" */
+#define REBINDTIME 1000
+/* default receive poll time in ms */
+#define DEFRDELTIME 5
+#define DEFSDELTIME 1
+/* default send poll time in ms */
+#define DEFSTRSIZE 256
+#define MAXALISTLEN 64
+
+#ifdef NT
+#define MSG_DONTWAIT 0
+#define MSG_NOSIGNAL 0
+#define MSG_WAITALL 0
+#else
+#define SOCKET_ERROR -1
+#endif
+
+/* Individual "receive" class */
+typedef struct _gripdRcvr
+{
+ t_object r_obj;
+ t_symbol *r_sym;
+ /* gripd object, needed so recevied symbol functions can access
+ gripd data (socket)*/
+ void *r_x;
+}t_gripdRcvr;
+
+/* Main object class */
+typedef struct _gripd
+{
+ t_object t_ob;
+ t_outlet *x_outlet2;
+ unsigned short int x_port;
+#ifdef NT
+ SOCKET x_sock;
+ SOCKET x_newSock;
+ /* for Windows, 1 if WSAStartup is called */
+ int x_wsockInitByMe;
+ PROCESS_INFORMATION x_childProcessInfo;
+#else
+ int x_sock;
+ int x_newSock;
+ int x_childPID;
+#endif
+ /* 1 if socket has been bound, 0 otherwise */
+ int x_bound;
+ /* 1 if currently connected, 0 otherwise */
+ int x_connected;
+ /* 1 if PD opened python app, otherwise (shared mem for linux)*/
+ int *x_localOpened;
+ /* timer for receiveing/sending */
+ t_clock *x_rclock;
+ t_clock *x_sclock;
+ /* timer for polling accept() */
+ t_clock *x_connectionClock;
+ /* timer for re-binding after "address already in use" error */
+ t_clock *x_bindClock;
+ /* path to python.exe for Windows */
+ char x_pythExec[DEFSTRSIZE];
+ /* path to gripd.py (or gripd.exe and gripd.py in Windows) */
+ char x_pythFile[DEFSTRSIZE];
+ /* send/receive poll times */
+ double x_sdeltime;
+ double x_rdeltime;
+ /* current number of receive "objects" being used */
+ int x_rcvrListSize;
+ /* size currently allocated for receiver objects */
+ int x_rcvrListMaxSize;
+ /* pointer to list of receiver objects */
+ t_gripdRcvr **x_rcvrs;
+ /* buffer to be sent */
+ char x_sendBuffer[MAXDATASIZE];
+ /* path to application */
+ char x_appPath[MAXDATASIZE];
+}t_gripd;
+
+t_class *gripd_class;
+t_class *gripdRcvr_class;
+
+void gripd_setup(void);
+void *gripd_new(t_floatarg port);
+void gripd_connect(t_gripd *x);
+/* initialize "server" */
+void gripd_openSocket(t_gripd *x);
+/* shutdown server */
+void gripd_disconnect(t_gripd *x);
+/* poll accept() */
+void gripd_trySocket(t_gripd *x);
+void gripd_closeSocket(t_gripd *x);
+void gripd_recv(t_gripd *x);
+void gripd_send(t_gripd *x);
+/* add name:value pair to send string */
+void gripd_appendSendBuffer(t_gripd *x, char *aString);
+/* open gripd.py (or gripd.exe inWindows) unlocked mode*/
+void gripd_open(t_gripd *x, t_symbol *sym, int argc, t_atom *argv);
+/* open gripd.py (or gripd.exe inWindows) locked mode*/
+void gripd_openLocked(t_gripd *x, t_symbol *sym, int argc, t_atom *argv);
+/* actually open gripd.py (or gripd.exe inWindows)*/
+void gripd_openPyth(t_gripd *x, t_symbol *sym, int argc,
+ t_atom *argv, int locked);
+/* tell python app to close itself */
+void gripd_closePyth(t_gripd *x);
+/* lock GUI */
+void gripd_lock(t_gripd *x);
+/* unlock GUI */
+void gripd_unlock(t_gripd *x);
+/* hide GUI */
+void gripd_hide(t_gripd *x);
+/* show GUI */
+void gripd_show(t_gripd *x);
+/* set GUI window title */
+void gripd_setTitle(t_gripd *x, t_symbol *sym, int argc, t_atom *argv);
+/* set path to gripd.py (or gripd.exe in Windows) */
+void gripd_setPath(t_gripd *x, t_symbol *sym, int argc, t_atom *argv);
+/* set path to python.exe for Windows */
+void gripd_setPythonPath(t_gripd *x, t_symbol *sym, int argc,
+ t_atom *argv);
+void gripd_setSTime(t_gripd *x, t_floatarg val);
+void gripd_setRTime(t_gripd *x, t_floatarg val);
+void gripd_openpanel(t_gripd *x);
+void gripd_savepanel(t_gripd *x);
+void gripdR_bang(t_gripdRcvr *r);
+void gripdR_float(t_gripdRcvr *r, t_float floatValue);
+void gripdR_symbol(t_gripdRcvr *r, t_symbol *sym);
+void gripdR_anything(t_gripdRcvr *r, t_symbol *sym, int argc,
+ t_atom *argv);
+void gripdR_list(t_gripdRcvr *r, t_symbol *sym, int argc, t_atom *argv);
+/* instantiate new rcv object */
+void gripd_makeGripdRcvr(t_gripd *x, t_symbol *s);
+/* check is rcv object has already been created */
+int gripd_checkExistance(t_gripd *x, char *name);
+/* allocate more mem for recv objects */
+void gripd_expandRcvrList(t_gripd *x);
+void gripd_free(t_gripd *x);
+int gripd_isNumeric(char *string);
+#ifndef NT
+void gripd_sigChild(int signum);
+#endif
+void gripd_getApplicationPath(t_gripd *x);
diff --git a/src/joystick.c b/src/joystick.c
new file mode 100644
index 0000000..02fddb7
--- /dev/null
+++ b/src/joystick.c
@@ -0,0 +1,296 @@
+/* GrIPD v0.1.1 - Graphical Interface for Pure Data
+** Copyright (C) 2002 Joseph A. Sarlo
+**
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License
+** as published by the Free Software Foundation; either version 2
+** of the License, or (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** jsarlo@ucsd.edu
+*/
+
+#include <stdio.h>
+#define MAXEVENTS 4096
+#define MAXDEVS 16
+#ifdef NT
+#include <STRING.H>
+#include <WINDOWS.H>
+#include <MMSYSTEM.H>
+#include <stdlib.h>
+#define MAX_AXIS_OUTS 10
+#define MAX_BUTTON_OUTS 32
+#else
+#include <strings.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#define JOYSTICK_DEVICE "/dev/js0"
+#define JS_EVENT_BUTTON 0x01
+#define JS_EVENT_AXIS 0x02
+#define JS_EVENT_INTI 0x80
+#define DEFSCALE 1
+#define DEFTRANSLATION 0
+#define JSIOCGAXES _IOR('j', 0x11, unsigned char)
+#define JSIOCGBUTTONS _IOR('j', 0x12, unsigned char)
+#define MAXAXES 4
+#endif
+
+static int eventValue[MAXEVENTS][MAXDEVS];
+static int eventNumber[MAXEVENTS][MAXDEVS];
+static int eventType[MAXEVENTS][MAXDEVS];
+static int eventCount[MAXDEVS];
+static int devCount = 0;
+static int devList[MAXDEVS];
+#ifdef NT
+static JOYINFOEX joyInfoEx[MAXDEVS];
+static int joyDevNum[MAXDEVS];
+static int joy_buttons[MAXDEVS];
+static int joy_axes[MAXDEVS];
+static int button_val[MAX_BUTTON_OUTS][MAXDEVS];
+static int axis_val[MAX_AXIS_OUTS][MAXDEVS];
+/* FIXME */
+static DWORD *axes_ptr[MAX_AXIS_OUTS][MAXDEVS];
+#else
+static int joy_fd[MAXDEVS];
+struct js_event
+{
+ unsigned int time;
+ signed short value;
+ unsigned char type;
+ unsigned char number;
+};
+static struct js_event joy_e[MAXDEVS];
+#endif
+
+#ifdef NT
+extern "C" {
+#endif
+
+int closeDevice(int devno)
+{
+ if (devList[devno])
+ {
+ devCount--;
+ devList[devno] = 0;
+#ifdef NT
+ return (1);
+#else
+ if (close(joy_fd[devno]) < 0)
+ return (0);
+ else
+ {
+ joy_fd[devno] = -1;
+ return(1);
+ }
+#endif
+ }
+}
+
+int openDevice(char *dev)
+{
+#ifdef NT
+ int i, num_axes, num_buttons, devId;
+ JOYCAPS jscaps;
+ MMRESULT errCode;
+ if (devCount == 0)
+ {
+ for (i = 0; i < MAXDEVS; i++)
+ {
+ devList[i] = 0;
+ }
+ }
+ for (i = 0; i < MAXDEVS; i++)
+ {
+ if (devList[i] == 0)
+ {
+ devId = i;
+ i = MAXDEVS;
+ }
+ }
+ joyInfoEx[devId].dwSize = sizeof(joyInfoEx);
+ joyInfoEx[devId].dwFlags = JOY_RETURNALL;
+ joyDevNum[devId] = (JOYSTICKID1 - 1) + atoi(dev);
+ errCode = joyGetPosEx(joyDevNum[devId], &joyInfoEx[devId]);
+ if ((errCode == MMSYSERR_NOERROR) && (devCount < MAXDEVS))
+ {
+ joyGetDevCaps(joyDevNum[devId], &jscaps, sizeof(jscaps));
+ if (jscaps.wNumAxes > MAX_AXIS_OUTS)
+ joy_axes[devId] = MAX_AXIS_OUTS;
+ else
+ joy_axes[devId] = jscaps.wNumAxes;
+ if (jscaps.wNumButtons > MAX_BUTTON_OUTS)
+ joy_buttons[devId] = MAX_BUTTON_OUTS;
+ else
+ joy_buttons[devId] = jscaps.wNumButtons;
+ for (i = 0; i < joy_axes[devId]; i++)
+ axis_val[i][devId] = 0;
+ for (i = 0; i < joy_buttons[devId]; i++)
+ button_val[i][devId] = 0;
+ axes_ptr[0][devId] = &(joyInfoEx[devId].dwXpos);
+ axes_ptr[1][devId] = &(joyInfoEx[devId].dwYpos);
+ axes_ptr[2][devId] = &(joyInfoEx[devId].dwZpos);
+ axes_ptr[3][devId] = &(joyInfoEx[devId].dwRpos);
+ axes_ptr[4][devId] = &(joyInfoEx[devId].dwUpos);
+ axes_ptr[5][devId] = &(joyInfoEx[devId].dwVpos);
+ eventCount[devId] = 0;
+ devCount++;
+ devList[devId] = 1;
+ return (devId);
+ }
+ else
+ return (-1);
+#else
+ int i, devId;
+ char joy_dev[256];
+
+ if (devCount == 0)
+ {
+ for (i = 0; i < MAXDEVS; i++)
+ {
+ devList[i] = 0;
+ }
+ }
+ for (i = 0; i < MAXDEVS; i++)
+ {
+ if (devList[i] == 0)
+ {
+ devId = i;
+ i = MAXDEVS;
+ }
+ }
+ if (strcmp(dev, "") == 0)
+ strcpy(joy_dev, JOYSTICK_DEVICE);
+ else
+ strcpy(joy_dev, dev);
+ joy_fd[devId] = open (joy_dev, O_RDONLY | O_NONBLOCK);
+ if ((joy_fd[devId] == -1) || (devCount >= MAXDEVS))
+ {
+ return (-1);
+ }
+ else
+ {
+ devCount++;
+ eventCount[devId] = 0;
+ devList[devId] = 1;
+ return (devId);
+ }
+#endif
+}
+
+int readEvents(int devno)
+{
+#ifdef NT
+ int i;
+
+ eventCount[devno] = 0;
+ joyGetPosEx(joyDevNum[devno], &(joyInfoEx[devno]));
+ for (i = 0; i < joy_axes[devno]; i++)
+ if (((int)(*(axes_ptr[i][devno])) != axis_val[i][devno]) &&
+ (eventCount[devno] < MAXEVENTS))
+ {
+ eventType[eventCount[devno]][devno] = 0;
+ eventNumber[eventCount[devno]][devno] = i;
+ eventValue[eventCount[devno]][devno] = (int)(*(axes_ptr[i][devno]));
+ eventCount[devno]++;
+ axis_val[i][devno] = (int)(*(axes_ptr[i][devno]));
+ }
+ for (i = 0; i < joy_buttons[devno]; i ++)
+ {
+ if (joyInfoEx[devno].dwButtons & (1 << i))
+ {
+ if ((button_val[i][devno] == 0) && (eventCount[devno] < MAXEVENTS))
+ {
+ eventType[eventCount[devno]][devno] = 1;
+ eventNumber[eventCount[devno]][devno] = i;
+ eventValue[eventCount[devno]][devno] = 1;
+ eventCount[devno]++;
+ button_val[i][devno] = 1;
+ }
+ }
+ else
+ if ((button_val[i][devno] == 1) && (eventCount[devno] < MAXEVENTS))
+ {
+ eventType[eventCount[devno]][devno] = 1;
+ eventNumber[eventCount[devno]][devno] = i;
+ eventValue[eventCount[devno]][devno] = 0;
+ eventCount[devno]++;
+ button_val[i][devno] = 0;
+ }
+ }
+ return (eventCount[devno]);
+#else
+ int i;
+
+ eventCount[devno] = 0;
+ if (joy_fd[devno] > -1)
+ {
+ while (read (joy_fd[devno], &(joy_e[devno]), sizeof(struct js_event)) > -1)
+ {
+ if (eventCount[devno] < MAXEVENTS)
+ {
+ if (joy_e[devno].type == JS_EVENT_AXIS)
+ eventType[eventCount[devno]][devno] = 0;
+ if (joy_e[devno].type == JS_EVENT_BUTTON)
+ eventType[eventCount[devno]][devno] = 1;
+ eventNumber[eventCount[devno]][devno] = joy_e[devno].number;
+ eventValue[eventCount[devno]][devno] = joy_e[devno].value;
+ eventCount[devno]++;
+ }
+ }
+ }
+ return eventCount[devno];
+#endif
+}
+
+int getEventCount(int devno)
+{
+ return (eventCount[devno]);
+}
+
+int getEventType(int devno, int eNum)
+{
+ int returnVal = 0;
+
+ if (eNum >= 0 && eNum < eventCount[devno])
+ {
+ returnVal = eventType[eNum][devno];
+ }
+ return (returnVal);
+}
+
+int getEventNumber(int devno, int eNum)
+{
+ int returnVal = 0;
+
+ if (eNum >= 0 && eNum < eventCount[devno])
+ {
+ returnVal = eventNumber[eNum][devno];
+ }
+ return (returnVal);
+}
+
+int getEventValue(int devno, int eNum)
+{
+ int returnVal = 0;
+
+ if (eNum >= 0 && eNum < eventCount[devno])
+ {
+ returnVal = eventValue[eNum][devno];
+ }
+ return (returnVal);
+}
+#ifdef NT
+}
+#endif
+
diff --git a/src/joystick_wrap.c b/src/joystick_wrap.c
new file mode 100644
index 0000000..b2e2087
--- /dev/null
+++ b/src/joystick_wrap.c
@@ -0,0 +1,692 @@
+/*
+ * FILE : joystick_wrap.c
+ *
+ * This file was automatically generated by :
+ * Simplified Wrapper and Interface Generator (SWIG)
+ * Version 1.1 (Patch 5)
+ *
+ * Portions Copyright (c) 1995-1998
+ * The University of Utah and The Regents of the University of California.
+ * Permission is granted to distribute this file in any manner provided
+ * this notice remains intact.
+ *
+ * Do not make changes to this file--changes will be lost!
+ *
+ */
+
+
+#define SWIGCODE
+/* Implementation : PYTHON */
+
+#define SWIGPYTHON
+#include <string.h>
+#include <stdlib.h>
+/***********************************************************************
+ * $Header: /home/zmoelnig/cvs2svn/pure-data/puredata_cvsbackup/extensions/gripd/src/joystick_wrap.c,v 1.1.1.1 2005-11-10 05:52:09 eighthave Exp $
+ * swig_lib/python/python.cfg
+ *
+ * This file contains coded needed to add variable linking to the
+ * Python interpreter. C variables are added as a new kind of Python
+ * datatype.
+ *
+ * Also contains supporting code for building python under Windows
+ * and things like that.
+ *
+ * $Log: not supported by cvs2svn $
+ ************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "Python.h"
+#ifdef __cplusplus
+}
+#endif
+
+/* Definitions for Windows/Unix exporting */
+#if defined(__WIN32__)
+# if defined(_MSC_VER)
+# define SWIGEXPORT(a,b) __declspec(dllexport) a b
+# else
+# if defined(__BORLANDC__)
+# define SWIGEXPORT(a,b) a _export b
+# else
+# define SWIGEXPORT(a,b) a b
+# endif
+# endif
+#else
+# define SWIGEXPORT(a,b) a b
+#endif
+
+#ifdef SWIG_GLOBAL
+#ifdef __cplusplus
+#define SWIGSTATIC extern "C"
+#else
+#define SWIGSTATIC
+#endif
+#endif
+
+#ifndef SWIGSTATIC
+#define SWIGSTATIC static
+#endif
+
+typedef struct {
+ char *name;
+ PyObject *(*get_attr)(void);
+ int (*set_attr)(PyObject *);
+} swig_globalvar;
+
+typedef struct swig_varlinkobject {
+ PyObject_HEAD
+ swig_globalvar **vars;
+ int nvars;
+ int maxvars;
+} swig_varlinkobject;
+
+/* ----------------------------------------------------------------------
+ swig_varlink_repr()
+
+ Function for python repr method
+ ---------------------------------------------------------------------- */
+
+static PyObject *
+swig_varlink_repr(swig_varlinkobject *v)
+{
+ v = v;
+ return PyString_FromString("<Global variables>");
+}
+
+/* ---------------------------------------------------------------------
+ swig_varlink_print()
+
+ Print out all of the global variable names
+ --------------------------------------------------------------------- */
+
+static int
+swig_varlink_print(swig_varlinkobject *v, FILE *fp, int flags)
+{
+
+ int i = 0;
+ flags = flags;
+ fprintf(fp,"Global variables { ");
+ while (v->vars[i]) {
+ fprintf(fp,"%s", v->vars[i]->name);
+ i++;
+ if (v->vars[i]) fprintf(fp,", ");
+ }
+ fprintf(fp," }\n");
+ return 0;
+}
+
+/* --------------------------------------------------------------------
+ swig_varlink_getattr
+
+ This function gets the value of a variable and returns it as a
+ PyObject. In our case, we'll be looking at the datatype and
+ converting into a number or string
+ -------------------------------------------------------------------- */
+
+static PyObject *
+swig_varlink_getattr(swig_varlinkobject *v, char *n)
+{
+ int i = 0;
+ char temp[128];
+
+ while (v->vars[i]) {
+ if (strcmp(v->vars[i]->name,n) == 0) {
+ return (*v->vars[i]->get_attr)();
+ }
+ i++;
+ }
+ sprintf(temp,"C global variable %s not found.", n);
+ PyErr_SetString(PyExc_NameError,temp);
+ return NULL;
+}
+
+/* -------------------------------------------------------------------
+ swig_varlink_setattr()
+
+ This function sets the value of a variable.
+ ------------------------------------------------------------------- */
+
+static int
+swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p)
+{
+ char temp[128];
+ int i = 0;
+ while (v->vars[i]) {
+ if (strcmp(v->vars[i]->name,n) == 0) {
+ return (*v->vars[i]->set_attr)(p);
+ }
+ i++;
+ }
+ sprintf(temp,"C global variable %s not found.", n);
+ PyErr_SetString(PyExc_NameError,temp);
+ return 1;
+}
+
+statichere PyTypeObject varlinktype = {
+/* PyObject_HEAD_INIT(&PyType_Type) Note : This doesn't work on some machines */
+ PyObject_HEAD_INIT(0)
+ 0,
+ "varlink", /* Type name */
+ sizeof(swig_varlinkobject), /* Basic size */
+ 0, /* Itemsize */
+ 0, /* Deallocator */
+ (printfunc) swig_varlink_print, /* Print */
+ (getattrfunc) swig_varlink_getattr, /* get attr */
+ (setattrfunc) swig_varlink_setattr, /* Set attr */
+ 0, /* tp_compare */
+ (reprfunc) swig_varlink_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_mapping*/
+ 0, /* tp_hash */
+};
+
+/* Create a variable linking object for use later */
+
+SWIGSTATIC PyObject *
+SWIG_newvarlink(void)
+{
+ swig_varlinkobject *result = 0;
+ result = PyMem_NEW(swig_varlinkobject,1);
+ varlinktype.ob_type = &PyType_Type; /* Patch varlinktype into a PyType */
+ result->ob_type = &varlinktype;
+ /* _Py_NewReference(result); Does not seem to be necessary */
+ result->nvars = 0;
+ result->maxvars = 64;
+ result->vars = (swig_globalvar **) malloc(64*sizeof(swig_globalvar *));
+ result->vars[0] = 0;
+ result->ob_refcnt = 0;
+ Py_XINCREF((PyObject *) result);
+ return ((PyObject*) result);
+}
+
+SWIGSTATIC void
+SWIG_addvarlink(PyObject *p, char *name,
+ PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p))
+{
+ swig_varlinkobject *v;
+ v= (swig_varlinkobject *) p;
+
+ if (v->nvars >= v->maxvars -1) {
+ v->maxvars = 2*v->maxvars;
+ v->vars = (swig_globalvar **) realloc(v->vars,v->maxvars*sizeof(swig_globalvar *));
+ if (v->vars == NULL) {
+ fprintf(stderr,"SWIG : Fatal error in initializing Python module.\n");
+ exit(1);
+ }
+ }
+ v->vars[v->nvars] = (swig_globalvar *) malloc(sizeof(swig_globalvar));
+ v->vars[v->nvars]->name = (char *) malloc(strlen(name)+1);
+ strcpy(v->vars[v->nvars]->name,name);
+ v->vars[v->nvars]->get_attr = get_attr;
+ v->vars[v->nvars]->set_attr = set_attr;
+ v->nvars++;
+ v->vars[v->nvars] = 0;
+}
+
+
+
+/*****************************************************************************
+ * $Header: /home/zmoelnig/cvs2svn/pure-data/puredata_cvsbackup/extensions/gripd/src/joystick_wrap.c,v 1.1.1.1 2005-11-10 05:52:09 eighthave Exp $
+ *
+ * swigptr.swg
+ *
+ * This file contains supporting code for the SWIG run-time type checking
+ * mechanism. The following functions are available :
+ *
+ * SWIG_RegisterMapping(char *origtype, char *newtype, void *(*cast)(void *));
+ *
+ * Registers a new type-mapping with the type-checker. origtype is the
+ * original datatype and newtype is an equivalent type. cast is optional
+ * pointer to a function to cast pointer values between types (this
+ * is typically used to cast pointers from derived classes to base classes in C++)
+ *
+ * SWIG_MakePtr(char *buffer, void *ptr, char *typestring);
+ *
+ * Makes a pointer string from a pointer and typestring. The result is returned
+ * in buffer which is assumed to hold enough space for the result.
+ *
+ * char * SWIG_GetPtr(char *buffer, void **ptr, char *type)
+ *
+ * Gets a pointer value from a string. If there is a type-mismatch, returns
+ * a character string to the received type. On success, returns NULL.
+ *
+ *
+ * You can remap these functions by making a file called "swigptr.swg" in
+ * your the same directory as the interface file you are wrapping.
+ *
+ * These functions are normally declared static, but this file can be
+ * can be used in a multi-module environment by redefining the symbol
+ * SWIGSTATIC.
+ *****************************************************************************/
+
+#include <stdlib.h>
+
+#ifdef SWIG_GLOBAL
+#ifdef __cplusplus
+#define SWIGSTATIC extern "C"
+#else
+#define SWIGSTATIC
+#endif
+#endif
+
+#ifndef SWIGSTATIC
+#define SWIGSTATIC static
+#endif
+
+
+/* SWIG pointer structure */
+
+typedef struct SwigPtrType {
+ char *name; /* Datatype name */
+ int len; /* Length (used for optimization) */
+ void *(*cast)(void *); /* Pointer casting function */
+ struct SwigPtrType *next; /* Linked list pointer */
+} SwigPtrType;
+
+/* Pointer cache structure */
+
+typedef struct {
+ int stat; /* Status (valid) bit */
+ SwigPtrType *tp; /* Pointer to type structure */
+ char name[256]; /* Given datatype name */
+ char mapped[256]; /* Equivalent name */
+} SwigCacheType;
+
+/* Some variables */
+
+static int SwigPtrMax = 64; /* Max entries that can be currently held */
+ /* This value may be adjusted dynamically */
+static int SwigPtrN = 0; /* Current number of entries */
+static int SwigPtrSort = 0; /* Status flag indicating sort */
+static int SwigStart[256]; /* Starting positions of types */
+
+/* Pointer table */
+static SwigPtrType *SwigPtrTable = 0; /* Table containing pointer equivalences */
+
+/* Cached values */
+
+#define SWIG_CACHESIZE 8
+#define SWIG_CACHEMASK 0x7
+static SwigCacheType SwigCache[SWIG_CACHESIZE];
+static int SwigCacheIndex = 0;
+static int SwigLastCache = 0;
+
+/* Sort comparison function */
+static int swigsort(const void *data1, const void *data2) {
+ SwigPtrType *d1 = (SwigPtrType *) data1;
+ SwigPtrType *d2 = (SwigPtrType *) data2;
+ return strcmp(d1->name,d2->name);
+}
+
+/* Binary Search function */
+static int swigcmp(const void *key, const void *data) {
+ char *k = (char *) key;
+ SwigPtrType *d = (SwigPtrType *) data;
+ return strncmp(k,d->name,d->len);
+}
+
+/* Register a new datatype with the type-checker */
+
+SWIGSTATIC
+void SWIG_RegisterMapping(char *origtype, char *newtype, void *(*cast)(void *)) {
+
+ int i;
+ SwigPtrType *t = 0,*t1;
+
+ /* Allocate the pointer table if necessary */
+
+ if (!SwigPtrTable) {
+ SwigPtrTable = (SwigPtrType *) malloc(SwigPtrMax*sizeof(SwigPtrType));
+ SwigPtrN = 0;
+ }
+ /* Grow the table */
+ if (SwigPtrN >= SwigPtrMax) {
+ SwigPtrMax = 2*SwigPtrMax;
+ SwigPtrTable = (SwigPtrType *) realloc((char *) SwigPtrTable,SwigPtrMax*sizeof(SwigPtrType));
+ }
+ for (i = 0; i < SwigPtrN; i++)
+ if (strcmp(SwigPtrTable[i].name,origtype) == 0) {
+ t = &SwigPtrTable[i];
+ break;
+ }
+ if (!t) {
+ t = &SwigPtrTable[SwigPtrN];
+ t->name = origtype;
+ t->len = strlen(t->name);
+ t->cast = 0;
+ t->next = 0;
+ SwigPtrN++;
+ }
+
+ /* Check for existing entry */
+
+ while (t->next) {
+ if ((strcmp(t->name,newtype) == 0)) {
+ if (cast) t->cast = cast;
+ return;
+ }
+ t = t->next;
+ }
+
+ /* Now place entry (in sorted order) */
+
+ t1 = (SwigPtrType *) malloc(sizeof(SwigPtrType));
+ t1->name = newtype;
+ t1->len = strlen(t1->name);
+ t1->cast = cast;
+ t1->next = 0;
+ t->next = t1;
+ SwigPtrSort = 0;
+}
+
+/* Make a pointer value string */
+
+SWIGSTATIC
+void SWIG_MakePtr(char *_c, const void *_ptr, char *type) {
+ static char _hex[16] =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'};
+ unsigned long _p, _s;
+ char _result[20], *_r; /* Note : a 64-bit hex number = 16 digits */
+ _r = _result;
+ _p = (unsigned long) _ptr;
+ if (_p > 0) {
+ while (_p > 0) {
+ _s = _p & 0xf;
+ *(_r++) = _hex[_s];
+ _p = _p >> 4;
+ }
+ *_r = '_';
+ while (_r >= _result)
+ *(_c++) = *(_r--);
+ } else {
+ strcpy (_c, "NULL");
+ }
+ if (_ptr)
+ strcpy (_c, type);
+}
+
+/* Define for backwards compatibility */
+
+#define _swig_make_hex SWIG_MakePtr
+
+/* Function for getting a pointer value */
+
+SWIGSTATIC
+char *SWIG_GetPtr(char *_c, void **ptr, char *_t)
+{
+ unsigned long _p;
+ char temp_type[256];
+ char *name;
+ int i, len;
+ SwigPtrType *sp,*tp;
+ SwigCacheType *cache;
+ int start, end;
+ _p = 0;
+
+ /* Pointer values must start with leading underscore */
+ if (*_c == '_') {
+ _c++;
+ /* Extract hex value from pointer */
+ while (*_c) {
+ if ((*_c >= '0') && (*_c <= '9'))
+ _p = (_p << 4) + (*_c - '0');
+ else if ((*_c >= 'a') && (*_c <= 'f'))
+ _p = (_p << 4) + ((*_c - 'a') + 10);
+ else
+ break;
+ _c++;
+ }
+
+ if (_t) {
+ if (strcmp(_t,_c)) {
+ if (!SwigPtrSort) {
+ qsort((void *) SwigPtrTable, SwigPtrN, sizeof(SwigPtrType), swigsort);
+ for (i = 0; i < 256; i++) {
+ SwigStart[i] = SwigPtrN;
+ }
+ for (i = SwigPtrN-1; i >= 0; i--) {
+ SwigStart[(int) (SwigPtrTable[i].name[1])] = i;
+ }
+ for (i = 255; i >= 1; i--) {
+ if (SwigStart[i-1] > SwigStart[i])
+ SwigStart[i-1] = SwigStart[i];
+ }
+ SwigPtrSort = 1;
+ for (i = 0; i < SWIG_CACHESIZE; i++)
+ SwigCache[i].stat = 0;
+ }
+
+ /* First check cache for matches. Uses last cache value as starting point */
+ cache = &SwigCache[SwigLastCache];
+ for (i = 0; i < SWIG_CACHESIZE; i++) {
+ if (cache->stat) {
+ if (strcmp(_t,cache->name) == 0) {
+ if (strcmp(_c,cache->mapped) == 0) {
+ cache->stat++;
+ *ptr = (void *) _p;
+ if (cache->tp->cast) *ptr = (*(cache->tp->cast))(*ptr);
+ return (char *) 0;
+ }
+ }
+ }
+ SwigLastCache = (SwigLastCache+1) & SWIG_CACHEMASK;
+ if (!SwigLastCache) cache = SwigCache;
+ else cache++;
+ }
+ /* We have a type mismatch. Will have to look through our type
+ mapping table to figure out whether or not we can accept this datatype */
+
+ start = SwigStart[(int) _t[1]];
+ end = SwigStart[(int) _t[1]+1];
+ sp = &SwigPtrTable[start];
+ while (start < end) {
+ if (swigcmp(_t,sp) == 0) break;
+ sp++;
+ start++;
+ }
+ if (start >= end) sp = 0;
+ /* Try to find a match for this */
+ if (sp) {
+ while (swigcmp(_t,sp) == 0) {
+ name = sp->name;
+ len = sp->len;
+ tp = sp->next;
+ /* Try to find entry for our given datatype */
+ while(tp) {
+ if (tp->len >= 255) {
+ return _c;
+ }
+ strcpy(temp_type,tp->name);
+ strncat(temp_type,_t+len,255-tp->len);
+ if (strcmp(_c,temp_type) == 0) {
+
+ strcpy(SwigCache[SwigCacheIndex].mapped,_c);
+ strcpy(SwigCache[SwigCacheIndex].name,_t);
+ SwigCache[SwigCacheIndex].stat = 1;
+ SwigCache[SwigCacheIndex].tp = tp;
+ SwigCacheIndex = SwigCacheIndex & SWIG_CACHEMASK;
+
+ /* Get pointer value */
+ *ptr = (void *) _p;
+ if (tp->cast) *ptr = (*(tp->cast))(*ptr);
+ return (char *) 0;
+ }
+ tp = tp->next;
+ }
+ sp++;
+ /* Hmmm. Didn't find it this time */
+ }
+ }
+ /* Didn't find any sort of match for this data.
+ Get the pointer value and return the received type */
+ *ptr = (void *) _p;
+ return _c;
+ } else {
+ /* Found a match on the first try. Return pointer value */
+ *ptr = (void *) _p;
+ return (char *) 0;
+ }
+ } else {
+ /* No type specified. Good luck */
+ *ptr = (void *) _p;
+ return (char *) 0;
+ }
+ } else {
+ if (strcmp (_c, "NULL") == 0) {
+ *ptr = (void *) 0;
+ return (char *) 0;
+ }
+ *ptr = (void *) 0;
+ return _c;
+ }
+}
+
+/* Compatibility mode */
+
+#define _swig_get_hex SWIG_GetPtr
+
+#define SWIG_init initjoystick
+
+#define SWIG_name "joystick"
+
+extern int closeDevice(int);
+extern int openDevice(char *);
+extern int readEvents(int);
+extern int getEventCount(int);
+extern int getEventType(int, int);
+extern int getEventNumber(int, int);
+extern int getEventValue(int, int);
+static PyObject *_wrap_closeDevice(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"i:closeDevice",&_arg0))
+ return NULL;
+ _result = (int )closeDevice(_arg0);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_openDevice(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ char * _arg0;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"s:openDevice",&_arg0))
+ return NULL;
+ _result = (int )openDevice(_arg0);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_readEvents(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"i:readEvents",&_arg0))
+ return NULL;
+ _result = (int )readEvents(_arg0);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_getEventCount(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"i:getEventCount",&_arg0))
+ return NULL;
+ _result = (int )getEventCount(_arg0);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_getEventType(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+ int _arg1;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"ii:getEventType",&_arg0,&_arg1))
+ return NULL;
+ _result = (int )getEventType(_arg0,_arg1);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_getEventNumber(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+ int _arg1;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"ii:getEventNumber",&_arg0,&_arg1))
+ return NULL;
+ _result = (int )getEventNumber(_arg0,_arg1);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_getEventValue(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+ int _arg1;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"ii:getEventValue",&_arg0,&_arg1))
+ return NULL;
+ _result = (int )getEventValue(_arg0,_arg1);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyMethodDef joystickMethods[] = {
+ { "getEventValue", _wrap_getEventValue, 1 },
+ { "getEventNumber", _wrap_getEventNumber, 1 },
+ { "getEventType", _wrap_getEventType, 1 },
+ { "getEventCount", _wrap_getEventCount, 1 },
+ { "readEvents", _wrap_readEvents, 1 },
+ { "openDevice", _wrap_openDevice, 1 },
+ { "closeDevice", _wrap_closeDevice, 1 },
+ { NULL, NULL }
+};
+static PyObject *SWIG_globals;
+#ifdef __cplusplus
+extern "C"
+#endif
+SWIGEXPORT(void,initjoystick)() {
+ PyObject *m, *d;
+ SWIG_globals = SWIG_newvarlink();
+ m = Py_InitModule("joystick", joystickMethods);
+ d = PyModule_GetDict(m);
+/*
+ * These are the pointer type-equivalency mappings.
+ * (Used by the SWIG pointer type-checker).
+ */
+ SWIG_RegisterMapping("_signed_long","_long",0);
+ SWIG_RegisterMapping("_long","_unsigned_long",0);
+ SWIG_RegisterMapping("_long","_signed_long",0);
+ SWIG_RegisterMapping("_unsigned_long","_long",0);
+ SWIG_RegisterMapping("_signed_int","_int",0);
+ SWIG_RegisterMapping("_unsigned_short","_short",0);
+ SWIG_RegisterMapping("_signed_short","_short",0);
+ SWIG_RegisterMapping("_unsigned_int","_int",0);
+ SWIG_RegisterMapping("_short","_unsigned_short",0);
+ SWIG_RegisterMapping("_short","_signed_short",0);
+ SWIG_RegisterMapping("_int","_unsigned_int",0);
+ SWIG_RegisterMapping("_int","_signed_int",0);
+}
diff --git a/src/makefile b/src/makefile
new file mode 100644
index 0000000..8930736
--- /dev/null
+++ b/src/makefile
@@ -0,0 +1,44 @@
+#--------------------------------------------------------------
+
+current: gripd_linux
+clean: clean_linux
+
+#----------- Options (all OS) --------------------------------
+
+MIDI = TRUE
+#MIDI = FALSE
+JOYSTICK = TRUE
+#JOYSTICK = FALSE
+
+#----------- Settings (Linux) --------------------------------
+
+MIDIOSSUBTYPE = ALSA
+#MIDIOSSUBTYPE = OSS
+PDINCLUDE = -I../../src
+LINUXPYTHONINCLUDE = -I/usr/include/python2.2
+SYSTEMLIBDIR = /usr/lib
+
+#----------- Settings (Windows) -------------------------------
+
+VC = "C:\Program Files\Microsoft Visual Studio\VC98"
+PYTHONHOME = C:\python22
+PYTHONVER = 22
+PDNTSRCDIR = C:\pd-37\src
+PDNTLDIR = C:\pd-37\bin
+
+#----------- Linux --------------------------------------------
+
+gripd_linux:
+ make -f Makefile.Linux all
+clean_linux:
+ make -f Makefile.Linux linux_clean
+
+#----------- Win32---------------------------------------------
+
+gripd_nt:
+ nmake -f Makefile.NT all
+clean_nt:
+ nmake -f Makefile.NT nt_clean
+
+
+
diff --git a/src/midi.cpp b/src/midi.cpp
new file mode 100644
index 0000000..1d63446
--- /dev/null
+++ b/src/midi.cpp
@@ -0,0 +1,146 @@
+/* GrIPD v0.1.1 - Graphical Interface for Pure Data
+** Copyright (C) 2003 Joseph A. Sarlo
+**
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License
+** as published by the Free Software Foundation; either version 2
+** of the License, or (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** jsarlo@ucsd.edu
+*/
+
+#include "midiiolib.h"
+#include <stdio.h>
+#ifndef NT
+#include <unistd.h>
+#endif
+#define MAXDEVS 16
+#define MAXEVENTS 4096
+
+#ifndef VISUAL
+using namespace std;
+#endif
+
+static int eventCount[MAXDEVS];
+static int eventCommand[MAXEVENTS][MAXDEVS];
+static int eventP0[MAXEVENTS][MAXDEVS];
+static int eventP1[MAXEVENTS][MAXDEVS];
+static int eventP2[MAXEVENTS][MAXDEVS];
+static int eventP3[MAXEVENTS][MAXDEVS];
+static MidiInput mInput[MAXDEVS];
+static int devCount = 0;
+static int devList[MAXDEVS];
+
+int openDevice(int dev) {
+ int i, devId, numPorts;
+
+ numPorts = MidiInPort::getNumPorts();
+ if (dev >= numPorts || dev < 0) {
+ return (-1);
+ }
+ else {
+ if (devCount == 0) {
+ for (i = 0; i < MAXDEVS; i++) {
+ devList[i] = 0;
+ }
+ }
+ for (i = 0; i < MAXDEVS; i++) {
+ if (devList[i] == 0) {
+ devId = i;
+ i = MAXDEVS;
+ }
+ }
+ devCount++;
+ eventCount[devId] = 0;
+ devList[devId] = 1;
+ mInput[devId].setPort(dev);
+ mInput[devId].open();
+ return (devId);
+ }
+}
+
+int closeDevice(int devno) {
+ if (devList[devno]) {
+ devCount--;
+ devList[devno] = 0;
+#ifndef LINUX
+ mInput[devno].close();
+#endif
+ return (1);
+ }
+ else
+ return (-1);
+}
+
+int readEvents(int devno) {
+ int i;
+ MidiMessage message;
+
+ if (devno < 0 || devno >= MAXDEVS)
+ return (-1);
+ eventCount[devno] = mInput[devno].getCount();
+ if (eventCount[devno] > MAXEVENTS) {
+ eventCount[devno] = MAXEVENTS;
+ }
+ for (i = 0; i < eventCount[devno]; i++) {
+ message = mInput[devno].extract();
+ eventCommand[i][devno] = message.getCommand();
+ eventP0[i][devno] = message.getP0();
+ eventP1[i][devno] = message.getP1();
+ eventP2[i][devno] = message.getP2();
+ eventP3[i][devno] = message.getP3();
+ }
+ return (eventCount[devno]);
+}
+
+int getEventCount(int devno) {
+ if (devno < 0 || devno >= MAXDEVS)
+ return (-1);
+ else
+ return (eventCount[devno]);
+}
+
+int getEventCommand(int devno, int eNum) {
+ if (eNum < 0 || eNum >= eventCount[devno] || devno < 0 || devno >= MAXDEVS)
+ return (-1);
+ else
+ return eventCommand[eNum][devno];
+}
+
+int getEventP0(int devno, int eNum) {
+ if (eNum < 0 || eNum >= eventCount[devno] || devno < 0 || devno >= MAXDEVS)
+ return (-1);
+ else
+ return eventP0[eNum][devno];
+}
+
+int getEventP1(int devno, int eNum) {
+ if (eNum < 0 || eNum >= eventCount[devno] || devno < 0 || devno >= MAXDEVS)
+ return (-1);
+ else
+ return eventP1[eNum][devno];
+}
+
+int getEventP2(int devno, int eNum) {
+ if (eNum < 0 || eNum >= eventCount[devno] || devno < 0 || devno >= MAXDEVS)
+ return (-1);
+ else
+ return eventP2[eNum][devno];
+}
+
+int getEventP3(int devno, int eNum) {
+ if (eNum < 0 || eNum >= eventCount[devno] || devno < 0 || devno >= MAXDEVS)
+ return (-1);
+ else
+ return eventP3[eNum][devno];
+}
+
diff --git a/src/midi_wrap.c b/src/midi_wrap.c
new file mode 100644
index 0000000..7b4ad15
--- /dev/null
+++ b/src/midi_wrap.c
@@ -0,0 +1,723 @@
+/*
+ * FILE : midi_wrap.c
+ *
+ * This file was automatically generated by :
+ * Simplified Wrapper and Interface Generator (SWIG)
+ * Version 1.1 (Patch 5)
+ *
+ * Portions Copyright (c) 1995-1998
+ * The University of Utah and The Regents of the University of California.
+ * Permission is granted to distribute this file in any manner provided
+ * this notice remains intact.
+ *
+ * Do not make changes to this file--changes will be lost!
+ *
+ */
+
+
+#define SWIGCODE
+/* Implementation : PYTHON */
+
+#define SWIGPYTHON
+#include <string.h>
+#include <stdlib.h>
+/***********************************************************************
+ * $Header: /home/zmoelnig/cvs2svn/pure-data/puredata_cvsbackup/extensions/gripd/src/midi_wrap.c,v 1.1.1.1 2005-11-10 05:52:09 eighthave Exp $
+ * swig_lib/python/python.cfg
+ *
+ * This file contains coded needed to add variable linking to the
+ * Python interpreter. C variables are added as a new kind of Python
+ * datatype.
+ *
+ * Also contains supporting code for building python under Windows
+ * and things like that.
+ *
+ * $Log: not supported by cvs2svn $
+ ************************************************************************/
+
+#ifdef __cplusplus
+#include "Python.h"
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* Definitions for Windows/Unix exporting */
+#if defined(__WIN32__)
+# if defined(_MSC_VER)
+# define SWIGEXPORT(a,b) __declspec(dllexport) a b
+# else
+# if defined(__BORLANDC__)
+# define SWIGEXPORT(a,b) a _export b
+# else
+# define SWIGEXPORT(a,b) a b
+# endif
+# endif
+#else
+# define SWIGEXPORT(a,b) a b
+#endif
+
+#ifdef SWIG_GLOBAL
+#ifdef __cplusplus
+#define SWIGSTATIC extern "C"
+#else
+#define SWIGSTATIC
+#endif
+#endif
+
+#ifndef SWIGSTATIC
+#define SWIGSTATIC static
+#endif
+
+typedef struct {
+ char *name;
+ PyObject *(*get_attr)(void);
+ int (*set_attr)(PyObject *);
+} swig_globalvar;
+
+typedef struct swig_varlinkobject {
+ PyObject_HEAD
+ swig_globalvar **vars;
+ int nvars;
+ int maxvars;
+} swig_varlinkobject;
+
+/* ----------------------------------------------------------------------
+ swig_varlink_repr()
+
+ Function for python repr method
+ ---------------------------------------------------------------------- */
+
+static PyObject *
+swig_varlink_repr(swig_varlinkobject *v)
+{
+ v = v;
+ return PyString_FromString("<Global variables>");
+}
+
+/* ---------------------------------------------------------------------
+ swig_varlink_print()
+
+ Print out all of the global variable names
+ --------------------------------------------------------------------- */
+
+static int
+swig_varlink_print(swig_varlinkobject *v, FILE *fp, int flags)
+{
+
+ int i = 0;
+ flags = flags;
+ fprintf(fp,"Global variables { ");
+ while (v->vars[i]) {
+ fprintf(fp,"%s", v->vars[i]->name);
+ i++;
+ if (v->vars[i]) fprintf(fp,", ");
+ }
+ fprintf(fp," }\n");
+ return 0;
+}
+
+/* --------------------------------------------------------------------
+ swig_varlink_getattr
+
+ This function gets the value of a variable and returns it as a
+ PyObject. In our case, we'll be looking at the datatype and
+ converting into a number or string
+ -------------------------------------------------------------------- */
+
+static PyObject *
+swig_varlink_getattr(swig_varlinkobject *v, char *n)
+{
+ int i = 0;
+ char temp[128];
+
+ while (v->vars[i]) {
+ if (strcmp(v->vars[i]->name,n) == 0) {
+ return (*v->vars[i]->get_attr)();
+ }
+ i++;
+ }
+ sprintf(temp,"C global variable %s not found.", n);
+ PyErr_SetString(PyExc_NameError,temp);
+ return NULL;
+}
+
+/* -------------------------------------------------------------------
+ swig_varlink_setattr()
+
+ This function sets the value of a variable.
+ ------------------------------------------------------------------- */
+
+static int
+swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p)
+{
+ char temp[128];
+ int i = 0;
+ while (v->vars[i]) {
+ if (strcmp(v->vars[i]->name,n) == 0) {
+ return (*v->vars[i]->set_attr)(p);
+ }
+ i++;
+ }
+ sprintf(temp,"C global variable %s not found.", n);
+ PyErr_SetString(PyExc_NameError,temp);
+ return 1;
+}
+
+statichere PyTypeObject varlinktype = {
+/* PyObject_HEAD_INIT(&PyType_Type) Note : This doesn't work on some machines */
+ PyObject_HEAD_INIT(0)
+ 0,
+ "varlink", /* Type name */
+ sizeof(swig_varlinkobject), /* Basic size */
+ 0, /* Itemsize */
+ 0, /* Deallocator */
+ (printfunc) swig_varlink_print, /* Print */
+ (getattrfunc) swig_varlink_getattr, /* get attr */
+ (setattrfunc) swig_varlink_setattr, /* Set attr */
+ 0, /* tp_compare */
+ (reprfunc) swig_varlink_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_mapping*/
+ 0, /* tp_hash */
+};
+
+/* Create a variable linking object for use later */
+
+SWIGSTATIC PyObject *
+SWIG_newvarlink(void)
+{
+ swig_varlinkobject *result = 0;
+ result = PyMem_NEW(swig_varlinkobject,1);
+ varlinktype.ob_type = &PyType_Type; /* Patch varlinktype into a PyType */
+ result->ob_type = &varlinktype;
+ /* _Py_NewReference(result); Does not seem to be necessary */
+ result->nvars = 0;
+ result->maxvars = 64;
+ result->vars = (swig_globalvar **) malloc(64*sizeof(swig_globalvar *));
+ result->vars[0] = 0;
+ result->ob_refcnt = 0;
+ Py_XINCREF((PyObject *) result);
+ return ((PyObject*) result);
+}
+
+SWIGSTATIC void
+SWIG_addvarlink(PyObject *p, char *name,
+ PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p))
+{
+ swig_varlinkobject *v;
+ v= (swig_varlinkobject *) p;
+
+ if (v->nvars >= v->maxvars -1) {
+ v->maxvars = 2*v->maxvars;
+ v->vars = (swig_globalvar **) realloc(v->vars,v->maxvars*sizeof(swig_globalvar *));
+ if (v->vars == NULL) {
+ fprintf(stderr,"SWIG : Fatal error in initializing Python module.\n");
+ exit(1);
+ }
+ }
+ v->vars[v->nvars] = (swig_globalvar *) malloc(sizeof(swig_globalvar));
+ v->vars[v->nvars]->name = (char *) malloc(strlen(name)+1);
+ strcpy(v->vars[v->nvars]->name,name);
+ v->vars[v->nvars]->get_attr = get_attr;
+ v->vars[v->nvars]->set_attr = set_attr;
+ v->nvars++;
+ v->vars[v->nvars] = 0;
+}
+
+
+
+/*****************************************************************************
+ * $Header: /home/zmoelnig/cvs2svn/pure-data/puredata_cvsbackup/extensions/gripd/src/midi_wrap.c,v 1.1.1.1 2005-11-10 05:52:09 eighthave Exp $
+ *
+ * swigptr.swg
+ *
+ * This file contains supporting code for the SWIG run-time type checking
+ * mechanism. The following functions are available :
+ *
+ * SWIG_RegisterMapping(char *origtype, char *newtype, void *(*cast)(void *));
+ *
+ * Registers a new type-mapping with the type-checker. origtype is the
+ * original datatype and newtype is an equivalent type. cast is optional
+ * pointer to a function to cast pointer values between types (this
+ * is typically used to cast pointers from derived classes to base classes in C++)
+ *
+ * SWIG_MakePtr(char *buffer, void *ptr, char *typestring);
+ *
+ * Makes a pointer string from a pointer and typestring. The result is returned
+ * in buffer which is assumed to hold enough space for the result.
+ *
+ * char * SWIG_GetPtr(char *buffer, void **ptr, char *type)
+ *
+ * Gets a pointer value from a string. If there is a type-mismatch, returns
+ * a character string to the received type. On success, returns NULL.
+ *
+ *
+ * You can remap these functions by making a file called "swigptr.swg" in
+ * your the same directory as the interface file you are wrapping.
+ *
+ * These functions are normally declared static, but this file can be
+ * can be used in a multi-module environment by redefining the symbol
+ * SWIGSTATIC.
+ *****************************************************************************/
+
+#include <stdlib.h>
+
+#ifdef SWIG_GLOBAL
+#ifdef __cplusplus
+#define SWIGSTATIC extern "C"
+#else
+#define SWIGSTATIC
+#endif
+#endif
+
+#ifndef SWIGSTATIC
+#define SWIGSTATIC static
+#endif
+
+
+/* SWIG pointer structure */
+
+typedef struct SwigPtrType {
+ char *name; /* Datatype name */
+ int len; /* Length (used for optimization) */
+ void *(*cast)(void *); /* Pointer casting function */
+ struct SwigPtrType *next; /* Linked list pointer */
+} SwigPtrType;
+
+/* Pointer cache structure */
+
+typedef struct {
+ int stat; /* Status (valid) bit */
+ SwigPtrType *tp; /* Pointer to type structure */
+ char name[256]; /* Given datatype name */
+ char mapped[256]; /* Equivalent name */
+} SwigCacheType;
+
+/* Some variables */
+
+static int SwigPtrMax = 64; /* Max entries that can be currently held */
+ /* This value may be adjusted dynamically */
+static int SwigPtrN = 0; /* Current number of entries */
+static int SwigPtrSort = 0; /* Status flag indicating sort */
+static int SwigStart[256]; /* Starting positions of types */
+
+/* Pointer table */
+static SwigPtrType *SwigPtrTable = 0; /* Table containing pointer equivalences */
+
+/* Cached values */
+
+#define SWIG_CACHESIZE 8
+#define SWIG_CACHEMASK 0x7
+static SwigCacheType SwigCache[SWIG_CACHESIZE];
+static int SwigCacheIndex = 0;
+static int SwigLastCache = 0;
+
+/* Sort comparison function */
+static int swigsort(const void *data1, const void *data2) {
+ SwigPtrType *d1 = (SwigPtrType *) data1;
+ SwigPtrType *d2 = (SwigPtrType *) data2;
+ return strcmp(d1->name,d2->name);
+}
+
+/* Binary Search function */
+static int swigcmp(const void *key, const void *data) {
+ char *k = (char *) key;
+ SwigPtrType *d = (SwigPtrType *) data;
+ return strncmp(k,d->name,d->len);
+}
+
+/* Register a new datatype with the type-checker */
+
+SWIGSTATIC
+void SWIG_RegisterMapping(char *origtype, char *newtype, void *(*cast)(void *)) {
+
+ int i;
+ SwigPtrType *t = 0,*t1;
+
+ /* Allocate the pointer table if necessary */
+
+ if (!SwigPtrTable) {
+ SwigPtrTable = (SwigPtrType *) malloc(SwigPtrMax*sizeof(SwigPtrType));
+ SwigPtrN = 0;
+ }
+ /* Grow the table */
+ if (SwigPtrN >= SwigPtrMax) {
+ SwigPtrMax = 2*SwigPtrMax;
+ SwigPtrTable = (SwigPtrType *) realloc((char *) SwigPtrTable,SwigPtrMax*sizeof(SwigPtrType));
+ }
+ for (i = 0; i < SwigPtrN; i++)
+ if (strcmp(SwigPtrTable[i].name,origtype) == 0) {
+ t = &SwigPtrTable[i];
+ break;
+ }
+ if (!t) {
+ t = &SwigPtrTable[SwigPtrN];
+ t->name = origtype;
+ t->len = strlen(t->name);
+ t->cast = 0;
+ t->next = 0;
+ SwigPtrN++;
+ }
+
+ /* Check for existing entry */
+
+ while (t->next) {
+ if ((strcmp(t->name,newtype) == 0)) {
+ if (cast) t->cast = cast;
+ return;
+ }
+ t = t->next;
+ }
+
+ /* Now place entry (in sorted order) */
+
+ t1 = (SwigPtrType *) malloc(sizeof(SwigPtrType));
+ t1->name = newtype;
+ t1->len = strlen(t1->name);
+ t1->cast = cast;
+ t1->next = 0;
+ t->next = t1;
+ SwigPtrSort = 0;
+}
+
+/* Make a pointer value string */
+
+SWIGSTATIC
+void SWIG_MakePtr(char *_c, const void *_ptr, char *type) {
+ static char _hex[16] =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'};
+ unsigned long _p, _s;
+ char _result[20], *_r; /* Note : a 64-bit hex number = 16 digits */
+ _r = _result;
+ _p = (unsigned long) _ptr;
+ if (_p > 0) {
+ while (_p > 0) {
+ _s = _p & 0xf;
+ *(_r++) = _hex[_s];
+ _p = _p >> 4;
+ }
+ *_r = '_';
+ while (_r >= _result)
+ *(_c++) = *(_r--);
+ } else {
+ strcpy (_c, "NULL");
+ }
+ if (_ptr)
+ strcpy (_c, type);
+}
+
+/* Define for backwards compatibility */
+
+#define _swig_make_hex SWIG_MakePtr
+
+/* Function for getting a pointer value */
+
+SWIGSTATIC
+char *SWIG_GetPtr(char *_c, void **ptr, char *_t)
+{
+ unsigned long _p;
+ char temp_type[256];
+ char *name;
+ int i, len;
+ SwigPtrType *sp,*tp;
+ SwigCacheType *cache;
+ int start, end;
+ _p = 0;
+
+ /* Pointer values must start with leading underscore */
+ if (*_c == '_') {
+ _c++;
+ /* Extract hex value from pointer */
+ while (*_c) {
+ if ((*_c >= '0') && (*_c <= '9'))
+ _p = (_p << 4) + (*_c - '0');
+ else if ((*_c >= 'a') && (*_c <= 'f'))
+ _p = (_p << 4) + ((*_c - 'a') + 10);
+ else
+ break;
+ _c++;
+ }
+
+ if (_t) {
+ if (strcmp(_t,_c)) {
+ if (!SwigPtrSort) {
+ qsort((void *) SwigPtrTable, SwigPtrN, sizeof(SwigPtrType), swigsort);
+ for (i = 0; i < 256; i++) {
+ SwigStart[i] = SwigPtrN;
+ }
+ for (i = SwigPtrN-1; i >= 0; i--) {
+ SwigStart[(int) (SwigPtrTable[i].name[1])] = i;
+ }
+ for (i = 255; i >= 1; i--) {
+ if (SwigStart[i-1] > SwigStart[i])
+ SwigStart[i-1] = SwigStart[i];
+ }
+ SwigPtrSort = 1;
+ for (i = 0; i < SWIG_CACHESIZE; i++)
+ SwigCache[i].stat = 0;
+ }
+
+ /* First check cache for matches. Uses last cache value as starting point */
+ cache = &SwigCache[SwigLastCache];
+ for (i = 0; i < SWIG_CACHESIZE; i++) {
+ if (cache->stat) {
+ if (strcmp(_t,cache->name) == 0) {
+ if (strcmp(_c,cache->mapped) == 0) {
+ cache->stat++;
+ *ptr = (void *) _p;
+ if (cache->tp->cast) *ptr = (*(cache->tp->cast))(*ptr);
+ return (char *) 0;
+ }
+ }
+ }
+ SwigLastCache = (SwigLastCache+1) & SWIG_CACHEMASK;
+ if (!SwigLastCache) cache = SwigCache;
+ else cache++;
+ }
+ /* We have a type mismatch. Will have to look through our type
+ mapping table to figure out whether or not we can accept this datatype */
+
+ start = SwigStart[(int) _t[1]];
+ end = SwigStart[(int) _t[1]+1];
+ sp = &SwigPtrTable[start];
+ while (start < end) {
+ if (swigcmp(_t,sp) == 0) break;
+ sp++;
+ start++;
+ }
+ if (start >= end) sp = 0;
+ /* Try to find a match for this */
+ if (sp) {
+ while (swigcmp(_t,sp) == 0) {
+ name = sp->name;
+ len = sp->len;
+ tp = sp->next;
+ /* Try to find entry for our given datatype */
+ while(tp) {
+ if (tp->len >= 255) {
+ return _c;
+ }
+ strcpy(temp_type,tp->name);
+ strncat(temp_type,_t+len,255-tp->len);
+ if (strcmp(_c,temp_type) == 0) {
+
+ strcpy(SwigCache[SwigCacheIndex].mapped,_c);
+ strcpy(SwigCache[SwigCacheIndex].name,_t);
+ SwigCache[SwigCacheIndex].stat = 1;
+ SwigCache[SwigCacheIndex].tp = tp;
+ SwigCacheIndex = SwigCacheIndex & SWIG_CACHEMASK;
+
+ /* Get pointer value */
+ *ptr = (void *) _p;
+ if (tp->cast) *ptr = (*(tp->cast))(*ptr);
+ return (char *) 0;
+ }
+ tp = tp->next;
+ }
+ sp++;
+ /* Hmmm. Didn't find it this time */
+ }
+ }
+ /* Didn't find any sort of match for this data.
+ Get the pointer value and return the received type */
+ *ptr = (void *) _p;
+ return _c;
+ } else {
+ /* Found a match on the first try. Return pointer value */
+ *ptr = (void *) _p;
+ return (char *) 0;
+ }
+ } else {
+ /* No type specified. Good luck */
+ *ptr = (void *) _p;
+ return (char *) 0;
+ }
+ } else {
+ if (strcmp (_c, "NULL") == 0) {
+ *ptr = (void *) 0;
+ return (char *) 0;
+ }
+ *ptr = (void *) 0;
+ return _c;
+ }
+}
+
+/* Compatibility mode */
+
+#define _swig_get_hex SWIG_GetPtr
+
+#define SWIG_init initmidi
+
+#define SWIG_name "midi"
+extern int openDevice(int );
+extern int closeDevice(int );
+extern int readEvents(int );
+extern int getEventCount(int );
+extern int getEventCommand(int ,int );
+extern int getEventP0(int ,int );
+extern int getEventP1(int ,int );
+extern int getEventP2(int ,int );
+extern int getEventP3(int ,int );
+static PyObject *_wrap_openDevice(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"i:openDevice",&_arg0))
+ return NULL;
+ _result = (int )openDevice(_arg0);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_closeDevice(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"i:closeDevice",&_arg0))
+ return NULL;
+ _result = (int )closeDevice(_arg0);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_readEvents(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"i:readEvents",&_arg0))
+ return NULL;
+ _result = (int )readEvents(_arg0);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_getEventCount(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"i:getEventCount",&_arg0))
+ return NULL;
+ _result = (int )getEventCount(_arg0);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_getEventCommand(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+ int _arg1;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"ii:getEventCommand",&_arg0,&_arg1))
+ return NULL;
+ _result = (int )getEventCommand(_arg0,_arg1);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_getEventP0(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+ int _arg1;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"ii:getEventP0",&_arg0,&_arg1))
+ return NULL;
+ _result = (int )getEventP0(_arg0,_arg1);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_getEventP1(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+ int _arg1;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"ii:getEventP1",&_arg0,&_arg1))
+ return NULL;
+ _result = (int )getEventP1(_arg0,_arg1);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_getEventP2(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+ int _arg1;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"ii:getEventP2",&_arg0,&_arg1))
+ return NULL;
+ _result = (int )getEventP2(_arg0,_arg1);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyObject *_wrap_getEventP3(PyObject *self, PyObject *args) {
+ PyObject * _resultobj;
+ int _result;
+ int _arg0;
+ int _arg1;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"ii:getEventP3",&_arg0,&_arg1))
+ return NULL;
+ _result = (int )getEventP3(_arg0,_arg1);
+ _resultobj = Py_BuildValue("i",_result);
+ return _resultobj;
+}
+
+static PyMethodDef midiMethods[] = {
+ { "getEventP3", _wrap_getEventP3, 1 },
+ { "getEventP2", _wrap_getEventP2, 1 },
+ { "getEventP1", _wrap_getEventP1, 1 },
+ { "getEventP0", _wrap_getEventP0, 1 },
+ { "getEventCommand", _wrap_getEventCommand, 1 },
+ { "getEventCount", _wrap_getEventCount, 1 },
+ { "readEvents", _wrap_readEvents, 1 },
+ { "closeDevice", _wrap_closeDevice, 1 },
+ { "openDevice", _wrap_openDevice, 1 },
+ { NULL, NULL }
+};
+static PyObject *SWIG_globals;
+#ifdef __cplusplus
+extern "C"
+#endif
+SWIGEXPORT(void,initmidi)() {
+ PyObject *m, *d;
+ SWIG_globals = SWIG_newvarlink();
+ m = Py_InitModule("midi", midiMethods);
+ d = PyModule_GetDict(m);
+/*
+ * These are the pointer type-equivalency mappings.
+ * (Used by the SWIG pointer type-checker).
+ */
+ SWIG_RegisterMapping("_signed_long","_long",0);
+ SWIG_RegisterMapping("_long","_unsigned_long",0);
+ SWIG_RegisterMapping("_long","_signed_long",0);
+ SWIG_RegisterMapping("_unsigned_long","_long",0);
+ SWIG_RegisterMapping("_signed_int","_int",0);
+ SWIG_RegisterMapping("_unsigned_short","_short",0);
+ SWIG_RegisterMapping("_signed_short","_short",0);
+ SWIG_RegisterMapping("_unsigned_int","_int",0);
+ SWIG_RegisterMapping("_short","_unsigned_short",0);
+ SWIG_RegisterMapping("_short","_signed_short",0);
+ SWIG_RegisterMapping("_int","_unsigned_int",0);
+ SWIG_RegisterMapping("_int","_signed_int",0);
+}
diff --git a/src/midiio/include/Array.cpp b/src/midiio/include/Array.cpp
new file mode 100644
index 0000000..044ed2d
--- /dev/null
+++ b/src/midiio/include/Array.cpp
@@ -0,0 +1,378 @@
+//
+// Copyright 1997-1999 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Feb 5 19:42:53 PST 1997
+// Last Modified: Sun May 11 20:41:28 GMT-0800 1997
+// Last Modified: Wed Jul 7 11:44:50 PDT 1999 (added setAll() function)
+// Filename: ...sig/maint/code/base/Array/Array.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/Array.cpp
+// Syntax: C++
+//
+// Description: An array which can grow dynamically. Array is derived from
+// the Collection class and adds various mathematical operators
+// to the Collection class. The Array template class is used for
+// storing numbers of any type which can be added, multiplied
+// and divided into one another.
+//
+
+#ifndef _ARRAY_CPP_INCLUDED
+#define _ARRAY_CPP_INCLUDED
+
+#include "Array.h"
+#include <iostream>
+#include <stdlib.h>
+
+
+//////////////////////////////
+//
+// Array::Array
+//
+
+template<class type>
+Array<type>::Array(void) : Collection<type>(4) { }
+
+template<class type>
+Array<type>::Array(int arraySize) : Collection<type>(arraySize) { }
+
+template<class type>
+Array<type>::Array(Array<type>& anArray) : Collection<type>(anArray) { }
+
+template<class type>
+Array<type>::Array(int arraySize, type *anArray) :
+ Collection<type>(arraySize, anArray) { }
+
+
+
+
+//////////////////////////////
+//
+// Array::~Array
+//
+
+template<class type>
+Array<type>::~Array() { }
+
+
+
+//////////////////////////////
+//
+// Array::setAll -- sets the contents of each element to the
+// specified value
+//
+
+template<class type>
+void Array<type>::setAll(type aValue) {
+ for (int i=0; i<getSize(); i++) {
+ array[i] = aValue;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Array::sum
+//
+
+template<class type>
+type Array<type>::sum(void) {
+ type theSum = 0;
+ for (int i=0; i<getSize(); i++) {
+ theSum += array[i];
+ }
+ return theSum;
+}
+
+template<class type>
+type Array<type>::sum(int loIndex, int hiIndex) {
+ type theSum = 0;
+ for (int i=loIndex; i<=hiIndex; i++) {
+ theSum += array[i];
+ }
+ return theSum;
+}
+
+
+
+//////////////////////////////
+//
+// Array::zero(-1, -1)
+//
+
+template<class type>
+void Array<type>::zero(int minIndex, int maxIndex) {
+ if (size == 0) return;
+ if (minIndex == -1) minIndex = 0;
+ if (maxIndex == -1) maxIndex = size-1;
+
+ if (minIndex < 0 || maxIndex < 0 || minIndex > maxIndex ||
+ maxIndex >= size) {
+ cerr << "Error in zero function: min = " << minIndex
+ << " max = " << maxIndex << " size = " << size << endl;
+ exit(1);
+ }
+
+ for (int i=minIndex; i<=maxIndex; i++) {
+ array[i] = 0;
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+//
+// operators
+//
+
+
+template<class type>
+int Array<type>::operator==(const Array<type>& aArray) {
+ if (getSize() != aArray.getSize()) {
+ return 0;
+ }
+ Array<type>& t = *this;
+ int i;
+ for (i=0; i<getSize(); i++) {
+ if (t[i] != aArray[i]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator=
+//
+
+template<class type>
+Array<type>& Array<type>::operator=(const Array<type>& anArray) {
+ if (allocSize < anArray.size) {
+ if (allocSize != 0) {
+ delete [] array;
+ }
+ allocSize = anArray.size;
+ size = anArray.size;
+ array = new type[size];
+ allowGrowthQ = anArray.allowGrowthQ;
+ growthAmount = anArray.growthAmount;
+ maxSize = anArray.maxSize;
+ }
+ size = anArray.size;
+ for (int i=0; i<size; i++) {
+ array[i] = anArray.array[i];
+ }
+
+ return *this;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator+=
+//
+
+template<class type>
+Array<type>& Array<type>::operator+=(const Array<type>& anArray) {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ for (int i=0; i<size; i++) {
+ array[i] += anArray.array[i];
+ }
+
+ return *this;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator+
+//
+
+template<class type>
+Array<type> Array<type>::operator+(const Array<type>& anArray) const {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ Array<type> bArray(*this);
+ bArray += anArray;
+ return bArray;
+}
+
+
+template<class type>
+Array<type> Array<type>::operator+(type aNumber) const {
+ Array<type> anArray(*this);
+ for (int i=0; i<size; i++) {
+ anArray[i] += aNumber;
+ }
+ return anArray;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator-=
+//
+
+template<class type>
+Array<type>& Array<type>::operator-=(const Array<type>& anArray) {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ for (int i=0; i<size; i++) {
+ array[i] -= anArray.array[i];
+ }
+
+ return *this;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator-
+//
+
+template<class type>
+Array<type> Array<type>::operator-(const Array<type>& anArray) const {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ Array<type> bArray(*this);
+ bArray -= anArray;
+ return bArray;
+}
+
+
+template<class type>
+Array<type> Array<type>::operator-(void) const {
+ Array<type> anArray(*this);
+ for (int i=0; i<size; i++) {
+ anArray[i] = -anArray[i];
+ }
+ return anArray;
+}
+
+template<class type>
+Array<type> Array<type>::operator-(type aNumber) const {
+ Array<type> anArray(*this);
+ for (int i=0; i<size; i++) {
+ anArray[i] -= aNumber;
+ }
+ return anArray;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator*=
+//
+
+template<class type>
+Array<type>& Array<type>::operator*=(const Array<type>& anArray) {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ for (int i=0; i<size; i++) {
+ array[i] *= anArray.array[i];
+ }
+
+ return *this;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator*
+//
+
+template<class type>
+Array<type> Array<type>::operator*(const Array<type>& anArray) const {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ Array<type> bArray(*this);
+ bArray *= anArray;
+ return bArray;
+}
+
+
+template<class type>
+Array<type> Array<type>::operator*(type aNumber) const {
+ Array<type> anArray(*this);
+ for (int i=0; i<size; i++) {
+ anArray[i] *= aNumber;
+ }
+ return anArray;
+}
+
+//////////////////////////////
+//
+// Array::operator/=
+//
+
+template<class type>
+Array<type>& Array<type>::operator/=(const Array<type>& anArray) {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ for (int i=0; i<size; i++) {
+ array[i] /= anArray.array[i];
+ }
+
+ return *this;
+}
+
+//////////////////////////////
+//
+// Array::operator/
+//
+
+template<class type>
+Array<type> Array<type>::operator/(const Array<type>& anArray) const {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ Array<type> bArray(*this);
+ bArray /= anArray;
+ return bArray;
+}
+
+
+#endif /* _ARRAY_CPP_INCLUDED */
+
+
+
+// md5sum: 8f52a167c93f51702ce316204fd6e722 - Array.cpp =css= 20030102
diff --git a/src/midiio/include/Array.h b/src/midiio/include/Array.h
new file mode 100644
index 0000000..75e08eb
--- /dev/null
+++ b/src/midiio/include/Array.h
@@ -0,0 +1,67 @@
+//
+// Copyright 1997-1999 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Feb 5 19:42:53 PST 1997
+// Last Modified: Sun May 11 20:33:13 GMT-0800 1997
+// Last Modified: Wed Jul 7 11:44:50 PDT 1999 (added setAll() function)
+// Last Modified: Mon Jul 29 22:08:32 PDT 2002 (added operator==)
+// Filename: ...sig/maint/code/base/Array/Array.h
+// Web Address: http://sig.sapp.org/include/sigBase/Array.h
+// Documentation: http://sig.sapp.org/doc/classes/Array
+// Syntax: C++
+//
+// Description: An array which can grow dynamically. Array is derived from
+// the Collection class and adds various mathematical operators
+// to the Collection class. The Array template class is used for
+// storing numbers of any type which can be added, multiplied
+// and divided into one another.
+//
+
+#ifndef _ARRAY_H_INCLUDED
+#define _ARRAY_H_INCLUDED
+
+#include "Collection.h"
+
+
+template<class type>
+class Array : public Collection<type> {
+ public:
+ Array (void);
+ Array (int arraySize);
+ Array (Array<type>& aArray);
+ Array (int arraySize, type *anArray);
+ ~Array ();
+
+ void setAll (type aValue);
+ type sum (void);
+ type sum (int lowIndex, int hiIndex);
+ void zero (int minIndex = -1, int maxIndex = -1);
+
+ int operator== (const Array<type>& aArray);
+ Array<type>& operator= (const Array<type>& aArray);
+ Array<type>& operator+= (const Array<type>& aArray);
+ Array<type>& operator-= (const Array<type>& aArray);
+ Array<type>& operator*= (const Array<type>& aArray);
+ Array<type>& operator/= (const Array<type>& aArray);
+
+ Array<type> operator+ (const Array<type>& aArray) const;
+ Array<type> operator+ (type aNumber) const;
+ Array<type> operator- (const Array<type>& aArray) const;
+ Array<type> operator- (void) const;
+
+ Array<type> operator- (type aNumber) const;
+ Array<type> operator* (const Array<type>& aArray) const;
+ Array<type> operator* (type aNumber) const;
+ Array<type> operator/ (const Array<type>& aArray) const;
+};
+
+
+#include "Array.cpp" /* necessary for templates */
+
+
+
+#endif /* _ARRAY_H_INCLUDED */
+
+
+
+// md5sum: 09d1b1f8e70ecde53f484548e48f33c3 - Array.h =css= 20030102
diff --git a/src/midiio/include/CircularBuffer.cpp b/src/midiio/include/CircularBuffer.cpp
new file mode 100644
index 0000000..9f4aca6
--- /dev/null
+++ b/src/midiio/include/CircularBuffer.cpp
@@ -0,0 +1,291 @@
+//
+// Copyright 1997-1998 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 19 December 1997
+// Last Modified: Wed Jan 21 23:16:54 GMT-0800 1998
+// Filename: ...sig/maint/code/base/CircularBuffer/CircularBuffer.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/CircularBuffer.cpp
+// Syntax: C++
+//
+// Description: A Circular buffer designed to handle MIDI input,
+// but able to store any type of object. Elements
+// can be read out of the buffer in two ways.
+// (1) from a read pointer which extracts the
+// elements in order by following the write pointer,
+// and (2) from an index operator related to the
+// write pointer's location, for example,
+// object[0] is the last value written into the
+// buffer and object[-1] (or object[1]) is the
+// item written just before that.
+//
+//
+
+#ifndef _CIRCULARBUFFER_CPP_INCLUDED
+#define _CIRCULARBUFFER_CPP_INCLUDED
+
+#include "CircularBuffer.h"
+#include <stdlib.h>
+#include <iostream>
+
+
+//////////////////////////////
+//
+// CircularBuffer::CircularBuffer -- Constructor.
+//
+
+template<class type>
+CircularBuffer<type>::CircularBuffer(void) {
+ size = 0;
+ buffer = NULL;
+ reset();
+}
+
+
+template<class type>
+CircularBuffer<type>::CircularBuffer(int maxElements) {
+ if (maxElements < 0) {
+ std::cerr << "Error: cannot have a negative number of elements: "
+ << maxElements << std::endl;
+ exit(1);
+ }
+ if (maxElements == 0) {
+ size = 0;
+ buffer = NULL;
+ reset();
+ } else {
+ size = maxElements;
+ buffer = new type[maxElements];
+ reset();
+ }
+}
+
+
+template<class type>
+CircularBuffer<type>::CircularBuffer(const CircularBuffer<type>& anotherBuffer) {
+ size = anotherBuffer.size;
+ if (getSize() == 0) {
+ buffer = NULL;
+ reset();
+ } else {
+ buffer = new type[getSize()];
+ writeIndex = anotherBuffer.writeIndex;
+ readIndex = anotherBuffer.readIndex;
+ itemCount = anotherBuffer.itemCount;
+ for (int i=0; i<getSize(); i++) {
+ buffer[i] = anotherBuffer.buffer[i];
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::~CircularBuffer -- Destructor.
+// deallocates buffer memory.
+//
+
+template<class type>
+CircularBuffer<type>::~CircularBuffer() {
+ if (buffer != NULL) {
+ delete [] buffer;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::capacity -- returns the number of items which
+// can be added to the buffer. Returns a positive number
+// if the buffer has empty locations available. Returns 0 if the
+// buffer is 100% full. Returns a negative number if the
+// buffer has overflowed.
+
+template<class type>
+int CircularBuffer<type>::capacity(void) const {
+ return getSize() - getCount();
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::extract -- reads the next value from the buffer.
+//
+
+template<class type>
+type CircularBuffer<type>::extract(void) {
+ itemCount--;
+ if (itemCount < 0) {
+ std::cerr << "Error: no elements in buffer to extract." << std::endl;
+ exit(1);
+ }
+ increment(readIndex);
+ return buffer[readIndex];
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::getCount -- returns the number of elements
+// between the write index and the read index.
+//
+
+template<class type>
+int CircularBuffer<type>::getCount(void) const {
+ return itemCount;
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::getSize -- returns the allocated size of the buffer.
+//
+
+template<class type>
+int CircularBuffer<type>::getSize(void) const {
+ return size;
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::insert -- add an element to the circular buffer
+//
+
+template<class type>
+void CircularBuffer<type>::insert(const type& anItem) {
+ itemCount++;
+ increment(writeIndex);
+ buffer[writeIndex] = anItem;
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::operator[] -- access an element relative to the
+// currently written element
+//
+
+template<class type>
+type& CircularBuffer<type>::operator[](int index) {
+ if (buffer == NULL) {
+ std::cerr << "Error: buffer has no allocated space" << std::endl;
+ exit(1);
+ }
+ int realIndex = (index < 0) ? -index : index;
+ if (realIndex >= getSize()) {
+ std::cerr << "Error: Invalid access: " << realIndex << ", maximum is "
+ << getSize()-1 << std::endl;
+ exit(1);
+ }
+ realIndex = writeIndex - realIndex;
+
+ // should need to go through this loop a max of one time:
+ while (realIndex < 0) {
+ realIndex += getSize();
+ }
+
+ return buffer[realIndex];
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::read -- an alias for the extract function.
+//
+
+template<class type>
+type CircularBuffer<type>::read(void) {
+ return extract();
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::reset -- throws out all previous data and
+// sets the read/write/count to initial values. The size
+// data variable must be valid before this function is
+// called.
+//
+
+template<class type>
+void CircularBuffer<type>::reset(void) {
+ readIndex = writeIndex = getSize() - 1;
+ itemCount = 0;
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::setSize -- warning: will throw out all previous data
+// stored in buffer.
+//
+
+template<class type>
+void CircularBuffer<type>::setSize(int aSize) {
+ if (aSize < 0) {
+ std::cerr << "Error: cannot have a negative buffer size: " << aSize << std::endl;
+ exit(1);
+ }
+ if (buffer != NULL) {
+ delete [] buffer;
+ }
+
+ if (aSize == 0) {
+ size = aSize;
+ buffer = NULL;
+ reset();
+ } else {
+ size = aSize;
+ buffer = new type[aSize];
+ reset();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::write -- an alias for the insert function.
+//
+
+template<class type>
+void CircularBuffer<type>::write(const type& anElement) {
+ write(anElement);
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+//////////////////////////////
+//
+// CircularBuffer::increment -- adds one to specified index and
+// will automatically wrap the index when it gets too large.
+//
+
+template<class type>
+void CircularBuffer<type>::increment(int& index) {
+ index++;
+ if (index >= getSize()) {
+ index = 0;
+ }
+}
+
+
+#endif /* _CIRCULARBUFFER_CPP_INCLUDED */
+
+
+
+// md5sum: 31b2e8d6efe7398a12ddb0a1b5680ca2 - CircularBuffer.cpp =css= 20030102
diff --git a/src/midiio/include/CircularBuffer.h b/src/midiio/include/CircularBuffer.h
new file mode 100644
index 0000000..6bb3071
--- /dev/null
+++ b/src/midiio/include/CircularBuffer.h
@@ -0,0 +1,66 @@
+//
+// Copyright 1997-1998 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 19 December 1997
+// Last Modified: Wed Jan 21 23:08:13 GMT-0800 1998
+// Filename: ...sig/maint/code/base/CircularBuffer/CircularBuffer.h
+// Web Address: http://sig.sapp.org/include/sigBase/CircularBuffer.cpp
+// Documentation: http://sig.sapp.org/doc/classes/CircularBuffer
+// Syntax: C++
+//
+// Description: A Circular buffer designed to handle MIDI input,
+// but able to store any type of object. Elements
+// can be read out of the buffer in two ways.
+// (1) from a read pointer which extracts the
+// elements in order by following the write pointer,
+// and (2) from an index operator related to the
+// write pointer's location, for example,
+// object[0] is the last value written into the
+// buffer and object[-1] (or object[1]) is the
+// item written just before that.
+//
+
+#ifndef _CIRCULARBUFFER_H_INCLUDED
+#define _CIRCULARBUFFER_H_INCLUDED
+
+
+template<class type>
+class CircularBuffer {
+ public:
+ CircularBuffer (void);
+ CircularBuffer (int maxElements);
+ CircularBuffer (const CircularBuffer<type>&
+ anotherBuffer);
+ ~CircularBuffer ();
+
+ int capacity (void) const;
+ type extract (void);
+ int getCount (void) const;
+ int getSize (void) const;
+ void insert (const type& aMessage);
+ type& operator[] (int index);
+ type read (void);
+ void reset (void);
+ void setSize (int aSize);
+ void write (const type& aMessage);
+
+ protected:
+ type* buffer;
+ int size;
+ int writeIndex;
+ int readIndex;
+ int itemCount;
+
+ void increment (int& index);
+};
+
+
+#include "CircularBuffer.cpp"
+
+
+
+#endif /* _CIRCULARBUFFER_H_INCLUDED */
+
+
+
+// md5sum: 2857693ec37fdcb6df09db479faf110b - CircularBuffer.h =css= 20030102
diff --git a/src/midiio/include/Collection.cpp b/src/midiio/include/Collection.cpp
new file mode 100644
index 0000000..74eef16
--- /dev/null
+++ b/src/midiio/include/Collection.cpp
@@ -0,0 +1,355 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Feb 5 19:42:53 PST 1997
+// Last Modified: Wed Apr 23 22:08:34 GMT-0800 1997
+// Last Modified: Fri Sep 14 15:50:52 PDT 2001 (added last() function)
+// Filename: ...sig/maint/code/base/Collection/Collection.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/Collection.cpp
+// Syntax: C++
+//
+// Description: A dynamic array which can grow as necessary.
+// This class can hold any type of item, but the
+// derived Array class is specifically for collections
+// of numbers.
+//
+
+#ifndef _COLLECTION_CPP_INCLUDED
+#define _COLLECTION_CPP_INCLUDED
+
+#include "Collection.h"
+#include <iostream>
+#include <stdlib.h>
+
+
+//////////////////////////////
+//
+// Collection::Collection
+//
+
+template<class type>
+Collection<type>::Collection(void) {
+ allocSize = 0;
+ size = 0;
+ array = NULL;
+ allowGrowthQ = 0;
+ growthAmount = 8;
+ maxSize = 0;
+}
+
+template<class type>
+Collection<type>::Collection(int arraySize) {
+ array = new type[arraySize];
+ size = arraySize;
+ allocSize = arraySize;
+ allowGrowthQ = 0;
+ growthAmount = arraySize;
+ maxSize = 0;
+}
+
+
+template<class type>
+Collection<type>::Collection(int arraySize, type *aCollection) {
+ size = arraySize;
+ allocSize = arraySize;
+ array = new type[size];
+ for (int i=0; i<size; i++) {
+ array[i] = aCollection[i];
+ }
+ growthAmount = arraySize;
+ allowGrowthQ = 0;
+ maxSize = 0;
+}
+
+
+template<class type>
+Collection<type>::Collection(Collection<type>& aCollection) {
+ size = aCollection.size;
+ allocSize = size;
+ array = new type[size];
+ for (int i=0; i<size; i++) {
+ array[i] = aCollection.array[i];
+ }
+ allowGrowthQ = aCollection.allowGrowthQ;
+ growthAmount = aCollection.growthAmount;
+ maxSize = aCollection.maxSize;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::~Collection
+//
+
+template<class type>
+Collection<type>::~Collection() {
+ if (getAllocSize() != 0) {
+ delete [] array;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Collection::allowGrowth
+// default value: status = 1
+//
+
+template<class type>
+void Collection<type>::allowGrowth(int status) {
+ if (status == 0) {
+ allowGrowthQ = 0;
+ } else {
+ allowGrowthQ = 1;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Collection::append
+//
+
+template<class type>
+void Collection<type>::append(type& element) {
+ if (size == getAllocSize()) {
+ grow();
+ }
+ array[size] = element;
+ size++;
+}
+
+template<class type>
+void Collection<type>::appendcopy(type element) {
+ if (size == getAllocSize()) {
+ grow();
+ }
+ array[size] = element;
+ size++;
+}
+
+template<class type>
+void Collection<type>::append(type *element) {
+ if (size == getAllocSize()) {
+ grow();
+ }
+ array[size] = *element;
+ size++;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::grow
+// default parameter: growamt = -1
+//
+
+template<class type>
+void Collection<type>::grow(long growamt) {
+ allocSize += growamt > 0 ? growamt : growthAmount;
+ if (maxSize != 0 && getAllocSize() > maxSize) {
+ std::cerr << "Error: Maximum size allowed for array exceeded." << std::endl;
+ exit(1);
+ }
+
+ type *temp = new type[getAllocSize()];
+ for (int i=0; i<size; i++) {
+ temp[i] = array[i];
+ }
+ array = temp;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::pointer
+//
+
+template<class type>
+type* Collection<type>::pointer(void) {
+ return array;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::getBase
+//
+
+template<class type>
+type* Collection<type>::getBase(void) {
+ return array;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::getAllocSize
+//
+
+template<class type>
+long Collection<type>::getAllocSize(void) const {
+ return allocSize;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::getSize --
+//
+
+template<class type>
+long Collection<type>::getSize(void) const {
+ return size;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::last --
+//
+
+template<class type>
+type& Collection<type>::last(void) {
+ return array[getSize()-1];
+}
+
+
+
+//////////////////////////////
+//
+// Collection::setAllocSize
+//
+
+template<class type>
+void Collection<type>::setAllocSize(long aSize) {
+ if (aSize < getSize()) {
+ std::cerr << "Error: cannot set allocated size smaller than actual size."
+ << std::endl;
+ exit(1);
+ }
+
+ if (aSize <= getAllocSize()) {
+ shrinkTo(aSize);
+ } else {
+ grow(aSize-getAllocSize());
+ size = aSize;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Collection::setGrowth
+// default parameter: growth = -1
+//
+
+template<class type>
+void Collection<type>::setGrowth(long growth) {
+ if (growth > 0) {
+ growthAmount = growth;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Collection::setSize
+//
+
+template<class type>
+void Collection<type>::setSize(long newSize) {
+ if (newSize <= getAllocSize()) {
+ size = newSize;
+ } else {
+ grow(newSize-getAllocSize());
+ size = newSize;
+ }
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Collection operators
+//
+
+//////////////////////////////
+//
+// Collection::operator[]
+//
+
+template<class type>
+type& Collection<type>::operator[](int elementIndex) {
+ if (allowGrowthQ && elementIndex == size) {
+ if (size == getAllocSize()) {
+ grow();
+ }
+ size++;
+ } else if (elementIndex >= size) {
+ std::cerr << "Error: accessing invalid array location "
+ << elementIndex
+ << " Maximum is " << size-1 << std::endl;
+ exit(1);
+ }
+ return array[elementIndex];
+}
+
+
+//////////////////////////////
+//
+// Collection::operator[] const
+//
+
+template<class type>
+type Collection<type>::operator[](int elementIndex) const {
+ if (elementIndex >= size) {
+ std::cerr << "Error: accessing invalid array location "
+ << elementIndex
+ << " Maximum is " << size-1 << std::endl;
+ exit(1);
+ }
+ return array[elementIndex];
+}
+
+//////////////////////////////
+//
+// shrinkTo
+//
+
+template<class type>
+void Collection<type>::shrinkTo(long aSize) {
+ if (aSize < getSize()) {
+ exit(1);
+ }
+
+ type *temp = new type[aSize];
+ for (int i=0; i<size; i++) {
+ temp[i] = array[i];
+ }
+ delete [] array;
+ array = temp;
+
+ allocSize = aSize;
+ if (size > allocSize) {
+ size = allocSize;
+ }
+}
+
+
+#endif /* _COLLECTION_CPP_INCLUDED */
+
+
+
+// md5sum: 9929fee30b1bede4305e1fb46303ddc1 - Collection.cpp =css= 20030102
diff --git a/src/midiio/include/Collection.h b/src/midiio/include/Collection.h
new file mode 100644
index 0000000..6775366
--- /dev/null
+++ b/src/midiio/include/Collection.h
@@ -0,0 +1,70 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Feb 5 19:42:53 PST 1997
+// Last Modified: Tue Apr 22 20:28:16 GMT-0800 1997
+// Last Modified: Fri Sep 14 15:50:52 PDT 2001 (added last() function)
+// Filename: ...sig/maint/code/base/Collection/Collection.h
+// Web Address: http://sig.sapp.org/include/sigBase/Collection.h
+// Documentation: http://sig.sapp.org/doc/classes/Collection
+// Syntax: C++
+//
+// Description: A dynamic array which can grow as necessary.
+// This class can hold any type of item, but the
+// derived Array class is specifically for collections
+// of numbers.
+//
+
+#ifndef _COLLECTION_H_INCLUDED
+#define _COLLECTION_H_INCLUDED
+
+
+template<class type>
+class Collection {
+ public:
+ Collection (void);
+ Collection (int arraySize);
+ Collection (int arraySize, type *aCollection);
+ Collection (Collection<type>& aCollection);
+ ~Collection ();
+
+ void allowGrowth (int status = 1);
+ void append (type& element);
+ void appendcopy (type element);
+ void append (type* element);
+ type *getBase (void);
+ long getAllocSize (void) const;
+ long getSize (void) const;
+ type *pointer (void);
+ void setAllocSize (long aSize);
+ void setGrowth (long growth);
+ void setSize (long newSize);
+ type& operator[] (int arrayIndex);
+ type operator[] (int arrayIndex) const;
+ void grow (long growamt = -1);
+ type& last (void);
+
+
+ protected:
+ long size; // actual array size
+ long allocSize; // maximum allowable array size
+ type *array; // where the array data is stored
+ char allowGrowthQ; // allow/disallow growth
+ long growthAmount; // number of elements to grow by if index
+ // element one beyond max size is accessed
+ long maxSize; // the largest size the array is allowed
+ // to grow to, if 0, then ignore max
+
+ void shrinkTo (long aSize);
+};
+
+
+#include "Collection.cpp"
+
+
+
+#endif /* _COLLECTION_H_INCLUDED */
+
+
+
+// md5sum: 01bec04835c0bd117f40c2bfe51c4abd - Collection.h =css= 20030102
diff --git a/src/midiio/include/FileIO.h b/src/midiio/include/FileIO.h
new file mode 100644
index 0000000..fdec5de
--- /dev/null
+++ b/src/midiio/include/FileIO.h
@@ -0,0 +1,148 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri May 9 22:30:32 PDT 1997
+// Last Modified: Sun Dec 14 05:26:16 GMT-0800 1997
+// Filename: ...sig/maint/code/base/FileIO/FileIO.h
+// Web Address: http://sig.sapp.org/include/sigBase/FileIO.h
+// Documentation: http://sig.sapp.org/doc/classes/FileIO
+// Syntax: C++
+//
+// Description: Derived from the fstream class, this class has
+// functions which allow writing binary files in
+// both little and big endian formats. Useful for
+// writing files such as soundfiles and MIDI files
+// which require numbers to be stored in a particular
+// endian format.
+//
+
+#ifndef _FILEIO_H_INCLUDED
+#define _FILEIO_H_INCLUDED
+
+
+#include <fstream>
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+typedef unsigned int uint;
+
+// templates would be nice to use here, but they don't seem
+// to work intuitively...
+
+class FileIO : public std::fstream {
+ public:
+ FileIO (void);
+ FileIO (const char* filename, std::ios::openmode state);
+ ~FileIO ();
+
+ void readBigEndian (char& aNumber);
+ void readBigEndian (uchar& aNumber);
+ void readBigEndian (short& aNumber);
+ void readBigEndian (ushort& aNumber);
+ void readBigEndian (long& aNumber);
+ void readBigEndian (ulong& aNumber);
+ void readBigEndian (int& aNumber);
+ void readBigEndian (uint& aNumber);
+ void readBigEndian (float& aNumber);
+ void readBigEndian (double& aNumber);
+
+ void readLittleEndian (char& aNumber);
+ void readLittleEndian (uchar& aNumber);
+ void readLittleEndian (short& aNumber);
+ void readLittleEndian (ushort& aNumber);
+ void readLittleEndian (long& aNumber);
+ void readLittleEndian (ulong& aNumber);
+ void readLittleEndian (int& aNumber);
+ void readLittleEndian (uint& aNumber);
+ void readLittleEndian (float& aNumber);
+ void readLittleEndian (double& aNumber);
+
+ void readMachineEndian (char& aNumber);
+ void readMachineEndian (uchar& aNumber);
+ void readMachineEndian (short& aNumber);
+ void readMachineEndian (ushort& aNumber);
+ void readMachineEndian (long& aNumber);
+ void readMachineEndian (ulong& aNumber);
+ void readMachineEndian (int& aNumber);
+ void readMachineEndian (uint& aNumber);
+ void readMachineEndian (float& aNumber);
+ void readMachineEndian (double& aNumber);
+
+ void readNotMachineEndian (char& aNumber);
+ void readNotMachineEndian (uchar& aNumber);
+ void readNotMachineEndian (short& aNumber);
+ void readNotMachineEndian (ushort& aNumber);
+ void readNotMachineEndian (long& aNumber);
+ void readNotMachineEndian (ulong& aNumber);
+ void readNotMachineEndian (int& aNumber);
+ void readNotMachineEndian (uint& aNumber);
+ void readNotMachineEndian (float& aNumber);
+ void readNotMachineEndian (double& aNumber);
+
+ void writeBigEndian (char aNumber);
+ void writeBigEndian (uchar aNumber);
+ void writeBigEndian (short aNumber);
+ void writeBigEndian (ushort aNumber);
+ void writeBigEndian (long aNumber);
+ void writeBigEndian (ulong aNumber);
+ void writeBigEndian (int aNumber);
+ void writeBigEndian (uint aNumber);
+ void writeBigEndian (float aNumber);
+ void writeBigEndian (double aNumber);
+
+ void writeLittleEndian (char aNumber);
+ void writeLittleEndian (uchar aNumber);
+ void writeLittleEndian (short aNumber);
+ void writeLittleEndian (ushort aNumber);
+ void writeLittleEndian (long aNumber);
+ void writeLittleEndian (ulong aNumber);
+ void writeLittleEndian (int aNumber);
+ void writeLittleEndian (uint aNumber);
+ void writeLittleEndian (float aNumber);
+ void writeLittleEndian (double aNumber);
+
+ void writeMachineEndian (char aNumber);
+ void writeMachineEndian (uchar aNumber);
+ void writeMachineEndian (short aNumber);
+ void writeMachineEndian (ushort aNumber);
+ void writeMachineEndian (long aNumber);
+ void writeMachineEndian (ulong aNumber);
+ void writeMachineEndian (int aNumber);
+ void writeMachineEndian (uint aNumber);
+ void writeMachineEndian (float aNumber);
+ void writeMachineEndian (double aNumber);
+
+ void writeNotMachineEndian (char aNumber);
+ void writeNotMachineEndian (uchar aNumber);
+ void writeNotMachineEndian (short aNumber);
+ void writeNotMachineEndian (ushort aNumber);
+ void writeNotMachineEndian (long aNumber);
+ void writeNotMachineEndian (ulong aNumber);
+ void writeNotMachineEndian (int aNumber);
+ void writeNotMachineEndian (uint aNumber);
+ void writeNotMachineEndian (float aNumber);
+ void writeNotMachineEndian (double aNumber);
+
+ protected:
+
+ char flipBytes (char aNumber);
+ uchar flipBytes (uchar aNumber);
+ short flipBytes (short aNumber);
+ ushort flipBytes (ushort aNumber);
+ long flipBytes (long aNumber);
+ ulong flipBytes (ulong aNumber);
+ int flipBytes (int aNumber);
+ uint flipBytes (uint aNumber);
+ float flipBytes (float aNumber);
+ double flipBytes (double aNumber);
+
+};
+
+
+
+#endif /* _FILEIO_H_INCLUDED */
+
+
+
+// md5sum: 0a146ebe5c6bd0850be973f612827d20 - FileIO.h =css= 20030102
diff --git a/src/midiio/include/MidiFile.h b/src/midiio/include/MidiFile.h
new file mode 100644
index 0000000..10794d5
--- /dev/null
+++ b/src/midiio/include/MidiFile.h
@@ -0,0 +1,108 @@
+//
+// Copyright 1999-2000 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Nov 26 14:12:01 PST 1999
+// Last Modified: Fri Dec 2 13:26:44 PST 1999
+// Last Modified: Fri Nov 10 12:13:15 PST 2000 (added some more editing cap.)
+// Last Modified: Thu Jan 10 10:03:39 PST 2002 (added allocateEvents())
+// Last Modified: Mon Jun 10 22:43:10 PDT 2002 (added clear())
+// Filename: ...sig/include/sigInfo/MidiFile.h
+// Web Address: http://sig.sapp.org/include/sigInfo/MidiFile.h
+// Syntax: C++
+//
+// Description: A class which can read/write Standard MIDI files.
+// MIDI data is stored by track in an array. This
+// class is used for example in the MidiPerform class.
+//
+
+#ifndef _MIDIfILE_H_INCLUDED
+#define _MIDIfILE_H_INCLUDED
+
+#include "FileIO.h"
+#include "Array.h"
+#include "Collection.h"
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+
+#define TIME_STATE_DELTA 0
+#define TIME_STATE_ABSOLUTE 1
+
+#define TRACK_STATE_SPLIT 0
+#define TRACK_STATE_JOINED 1
+
+
+class _MFEvent {
+ public:
+ _MFEvent (void);
+ _MFEvent (int command);
+ _MFEvent (int command, int param1);
+ _MFEvent (int command, int param1, int param2);
+ _MFEvent (int track, int command, int param1, int param2);
+ _MFEvent (int aTime, int aTrack, int command, int param1, int param2);
+ ~_MFEvent ();
+ int time;
+ int track;
+ Array<uchar> data;
+};
+
+
+
+class MidiFile {
+ public:
+ MidiFile (void);
+ MidiFile (char* aFile);
+ ~MidiFile ();
+
+ void absoluteTime (void);
+ int addEvent (int aTrack, int aTime,
+ Array<uchar>& midiData);
+ int addTrack (void);
+ int addTrack (int count);
+ void allocateEvents (int track, int aSize);
+ void deltaTime (void);
+ void deleteTrack (int aTrack);
+ void erase (void);
+ void clear (void);
+ _MFEvent& getEvent (int aTrack, int anIndex);
+ int getTimeState (void);
+ int getTrackState (void);
+ int getTicksPerQuarterNote (void);
+ int getTrackCount (void);
+ int getNumTracks (void);
+ int getNumEvents (int aTrack);
+ void joinTracks (void);
+ void mergeTracks (int aTrack1, int aTrack2);
+ int read (char* aFile);
+ void setTicksPerQuarterNote (int ticks);
+ void sortTrack (Collection<_MFEvent>& trackData);
+ void sortTracks (void);
+ void splitTracks (void);
+ int write (const char* aFile);
+
+ protected:
+ Collection<Collection<_MFEvent>*> events; // midi file events
+ int ticksPerQuarterNote; // time base of file
+ int trackCount; // # of tracks in file
+ int theTrackState; // joined or split
+ int theTimeState; // absolute or delta
+ char* readFileName; // read file name
+
+ private:
+ void extractMidiData (FileIO& inputfile, Array<uchar>& array,
+ uchar& runningCommand);
+ ulong extractVlvTime (FileIO& inputfile);
+ ulong unpackVLV (uchar a, uchar b, uchar c, uchar d, uchar e);
+ void writeVLValue (long aValue, Array<uchar>& data);
+};
+
+
+int eventcompare(const void* a, const void* b);
+std::ostream& operator<<(std::ostream& out, MidiFile& aMidiFile);
+
+#endif /* _MIDIfILE_H_INCLUDED */
+
+
+
+// md5sum: ff46e64698e2d9e88ebeef3efa9927d0 - MidiFile.h =css= 20030102
diff --git a/src/midiio/include/MidiFileWrite.h b/src/midiio/include/MidiFileWrite.h
new file mode 100644
index 0000000..a213fdf
--- /dev/null
+++ b/src/midiio/include/MidiFileWrite.h
@@ -0,0 +1,61 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Mar 15 10:55:56 GMT-0800 1998
+// Last Modified: Sun Mar 15 10:55:56 GMT-0800 1998
+// Filename: ...sig/code/control/MidiFileWrite/MidiFileWrite.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiFileWrite.h
+// Syntax: C++
+//
+// Description: The MidiFileWrite class will write out a Type 0 MidiFile.
+// Used for recording MIDI data streams into Standard
+// MIDI files.
+//
+
+#ifndef _MIDIFILEWRITE_INCLUDED
+#define _MIDIFILEWRITE_INCLUDED
+
+
+#include "FileIO.h"
+
+
+class MidiFileWrite {
+ public:
+ MidiFileWrite (void);
+ MidiFileWrite (const char* aFilename, int startTime = -1);
+ ~MidiFileWrite ();
+
+ void close (void);
+ void setup (const char* aFilename, int startTime = -1);
+ void start (int startTime = -1);
+ void writeAbsolute (int aTime, int command, int p1, int p2);
+ void writeAbsolute (int aTime, int command, int p1);
+ void writeAbsolute (int aTime, int command);
+ void writeRaw (uchar aByte);
+ void writeRaw (uchar aByte, uchar Byte);
+ void writeRaw (uchar aByte, uchar Byte, uchar cByte);
+ void writeRaw (uchar aByte, uchar Byte, uchar cByte,
+ uchar dByte);
+ void writeRaw (uchar aByte, uchar Byte, uchar cByte,
+ uchar dByte, uchar eByte);
+ void writeRaw (uchar* anArray, int arraySize);
+ void writeRelative (int aTime, int command, int p1, int p2);
+ void writeRelative (int aTime, int command, int p1);
+ void writeRelative (int aTime, int command);
+ void writeVLValue (long aValue);
+
+
+ protected:
+ FileIO *midifile; // file stream for MIDI file
+ long trackSize; // size count for MIDI track
+ int lastPlayTime; // for calculating delta times
+ int openQ; // for checking file status
+
+};
+
+
+
+#endif /* _MIDIFILEWRITE_INCLUDED */
+
+
+
+// md5sum: 44ac572078bff648d096c7e7867d1b3c - MidiFileWrite.h =css= 20030102
diff --git a/src/midiio/include/MidiIO.h b/src/midiio/include/MidiIO.h
new file mode 100644
index 0000000..80c9168
--- /dev/null
+++ b/src/midiio/include/MidiIO.h
@@ -0,0 +1,58 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Sun Jan 25 15:44:35 GMT-0800 1998
+// Filename: ...sig/code/control/MidiIO/MidiIO.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiIO.h
+// Syntax: C++
+//
+// Description: A unified class for MidiInput and MidiOutput that handles
+// MIDI input and output connections. The Synthesizer
+// and RadioBaton classes are derived from this class.
+//
+
+#ifndef _MIDIIO_H_INCLUDED
+#define _MIDIIO_H_INCLUDED
+
+
+#include "MidiInput.h"
+#include "MidiOutput.h"
+
+
+class MidiIO : public MidiOutput, public MidiInput {
+ public:
+ MidiIO (void);
+ MidiIO (int outPort, int inPort);
+ ~MidiIO ();
+
+ void close (void);
+ void closeInput (void);
+ void closeOutput (void);
+ int getChannelInOffset (void) const;
+ int getChannelOutOffset (void) const;
+ int getInputPort (void);
+ int getInputTrace (void);
+ int getNumInputPorts (void);
+ int getNumOutputPorts (void);
+ int getOutputPort (void);
+ int getOutputTrace (void);
+ int open (void);
+ int openInput (void);
+ int openOutput (void);
+ void setChannelOffset (int anOffset);
+ void setInputPort (int aPort);
+ void setInputTrace (int aState);
+ void setOutputPort (int aPort);
+ void setOutputTrace (int aState);
+ void toggleInputTrace (void);
+ void toggleOutputTrace (void);
+
+};
+
+
+
+#endif /* _MIDIIO_H_INCLUDED */
+
+
+
+// md5sum: 9f6122405c4d9e83994457210217ff22 - MidiIO.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort.h b/src/midiio/include/MidiInPort.h
new file mode 100644
index 0000000..ac225c4
--- /dev/null
+++ b/src/midiio/include/MidiInPort.h
@@ -0,0 +1,98 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Jan 21 22:35:31 GMT-0800 1998
+// Last Modified: Thu Jan 22 23:13:54 GMT-0800 1998
+// Last Modified: Sat Nov 7 16:09:18 PST 1998
+// Last Modified: Tue Jun 29 16:14:50 PDT 1999 (added Sysex input)
+// Last Modified: Tue May 23 23:08:44 PDT 2000 (oss/alsa selection added)
+// Filename: ...sig/maint/code/control/MidiInPort/MidiInPort.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of an
+// operating-system specific MIDI input method.
+// Provides control of all low-level MIDI input
+// functionality such that it will work on all
+// computers in the same manner.
+//
+
+#ifndef _MIDIINPORT_H_INCLUDED
+#define _MIDIINPORT_H_INCLUDED
+
+
+#include "MidiMessage.h"
+
+#ifdef VISUAL
+ #define MIDIINPORT MidiInPort_visual
+ #include "MidiInPort_visual.h"
+#elif defined(LINUX) && defined(ALSA) && defined(OSS)
+ #define MIDIINPORT MidiInPort_linux
+ #include "MidiInPort_linux.h"
+#elif defined(LINUX) && defined(ALSA) && !defined(OSS)
+ #define MIDIINPORT MidiInPort_alsa
+ #include "MidiInPort_alsa.h"
+#elif defined (LINUX) && defined(OSS) && !defined(ALSA)
+ #define MIDIINPORT MidiInPort_oss
+ #include "MidiInPort_oss.h"
+#elif defined(LINUX)
+ #define MIDIINPORT MidiInPort_oss
+ #include "MidiInPort_oss.h"
+#else
+ #define MIDIINPORT MidiInPort_unsupported
+ #include "MidiInPort_unsupported.h"
+#endif
+
+
+class MidiInPort : protected MIDIINPORT {
+ public:
+ MidiInPort (void) : MIDIINPORT() {}
+ MidiInPort (int aPort, int autoOpen = 1) :
+ MIDIINPORT(aPort, autoOpen) {}
+ ~MidiInPort() { }
+
+ void clearSysex(void) { MIDIINPORT::clearSysex(); }
+ void clearSysex(int buffer) { MIDIINPORT::clearSysex(buffer); }
+ void close(void) { MIDIINPORT::close(); }
+ void closeAll(void) { MIDIINPORT::closeAll(); }
+ MidiMessage extract(void) { return MIDIINPORT::extract(); }
+ int getBufferSize(void) { return MIDIINPORT::getBufferSize(); }
+ int getChannelOffset(void) const {
+ return MIDIINPORT::getChannelOffset(); }
+ int getCount(void) { return MIDIINPORT::getCount(); }
+ const char* getName(void) { return MIDIINPORT::getName(); }
+ static const char* getName(int i) { return MIDIINPORT::getName(i); }
+ static int getNumPorts(void) {
+ return MIDIINPORT::getNumPorts(); }
+ int getPort(void) { return MIDIINPORT::getPort(); }
+ int getPortStatus(void){
+ return MIDIINPORT::getPortStatus(); }
+ uchar* getSysex(int buffer) { return MIDIINPORT::getSysex(buffer); }
+ int getSysexSize(int buffer) { return MIDIINPORT::getSysexSize(buffer); }
+ int getTrace(void) { return MIDIINPORT::getTrace(); }
+ void insert(const MidiMessage& aMessage) {
+ MIDIINPORT::insert(aMessage); }
+ int installSysex(uchar* anArray, int aSize) {
+ return MIDIINPORT::installSysex(anArray, aSize); }
+ int open(void) { return MIDIINPORT::open(); }
+ MidiMessage& operator[](int index) {
+ return MIDIINPORT::message(index); }
+ void pause(void) { MIDIINPORT::pause(); }
+ void setBufferSize(int aSize) {
+ MIDIINPORT::setBufferSize(aSize); }
+ void setChannelOffset(int anOffset) {
+ MIDIINPORT::setChannelOffset(anOffset); }
+ void setAndOpenPort(int aPort) { setPort(aPort); open(); }
+ void setPort(int aPort) { MIDIINPORT::setPort(aPort); }
+ int setTrace(int aState) {
+ return MIDIINPORT::setTrace(aState); }
+ void toggleTrace(void) { MIDIINPORT::toggleTrace(); }
+ void unpause(void) { MIDIINPORT::unpause(); }
+};
+
+
+
+#endif /* _MIDIINPORT_H_INCLUDED */
+
+
+
+// md5sum: 96f8a2b4411a356d1b73cd96421b8931 - MidiInPort.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_alsa.h b/src/midiio/include/MidiInPort_alsa.h
new file mode 100644
index 0000000..b321600
--- /dev/null
+++ b/src/midiio/include/MidiInPort_alsa.h
@@ -0,0 +1,107 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:05:27 PDT 2000
+// Last Modified: Sat Oct 13 16:11:24 PDT 2001 (updated for ALSA 0.9)
+// Last Modified: Sat Nov 2 20:35:50 PST 2002 (added #ifdef ALSA)
+// Filename: ...sig/maint/code/control/MidiInPort/linux/MidiInPort_alsa.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort_alsa.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux ALSA sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#ifndef _MIDIINPORT_ALSA_H_INCLUDED
+#define _MIDIINPORT_ALSA_H_INCLUDED
+
+#ifdef LINUX
+#ifdef ALSA
+
+#include "MidiMessage.h"
+#include "CircularBuffer.h"
+#include "Array.h"
+#include "Sequencer_alsa.h"
+#include "SigTimer.h"
+#include <pthread.h>
+
+typedef unsigned char uchar;
+typedef void (*MIDI_Callback_function)(int arrivalPort);
+
+
+class MidiInPort_alsa : public Sequencer_alsa {
+ public:
+ MidiInPort_alsa (void);
+ MidiInPort_alsa (int aPort, int autoOpen = 1);
+ ~MidiInPort_alsa ();
+
+ void clearSysex (int buffer);
+ void clearSysex (void);
+ void close (void);
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getBufferSize (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ uchar* getSysex (int buffer);
+ int getSysexSize (int buffer);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ int installSysex (uchar* anArray, int aSize);
+ MidiMessage& message (int index);
+ int open (void);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ static Array<int> threadinitport;
+
+ protected:
+ int port; // the port to which this object belongs
+
+ static MIDI_Callback_function callbackFunction;
+
+ static int installSysexPrivate (int port,
+ uchar* anArray, int aSize);
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* trace; // for verifying input
+ static std::ostream* tracedisplay; // stream for displaying trace
+ static int numDevices; // number of input ports
+ static CircularBuffer<MidiMessage>** midiBuffer; // MIDI storage frm ports
+ static int channelOffset; // channel offset, either 0 or 1
+ // not being used right now.
+ static int* pauseQ; // for adding items to Buffer or not
+ static SigTimer midiTimer; // for timing MIDI input
+ static Array<pthread_t> midiInThread; // for MIDI input thread function
+ static int* sysexWriteBuffer; // for MIDI sysex write location
+ static Array<uchar>** sysexBuffers; // for MIDI sysex storage
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+
+
+ friend void *interpretMidiInputStreamPrivateALSA(void * x);
+
+};
+
+
+#endif /* ALSA */
+#endif /* LINUX */
+
+#endif /* _MIDIINPORT_ALSA_H_INCLUDED */
+
+
+
+// md5sum: 260a0accd6b08b638a00904c382293bc - MidiInPort_alsa.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_alsa05.h b/src/midiio/include/MidiInPort_alsa05.h
new file mode 100644
index 0000000..27af569
--- /dev/null
+++ b/src/midiio/include/MidiInPort_alsa05.h
@@ -0,0 +1,107 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:05:27 PDT 2000
+// Last Modified: Wed Oct 3 22:28:20 PDT 2001 (frozen for ALSA 0.5)
+// Last Modified: Thu Jan 2 18:55:12 PST 2003 (added #ifdef ALSA05)
+// Filename: ...sig/maint/code/control/MidiInPort/linux/MidiInPort_alsa05.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort_alsa05.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux ALSA sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#ifndef _MIDIINPORT_ALSA05_H_INCLUDED
+#define _MIDIINPORT_ALSA05_H_INCLUDED
+
+#ifdef LINUX
+#ifdef ALSA05
+
+#include "MidiMessage.h"
+#include "CircularBuffer.h"
+#include "Array.h"
+#include "Sequencer_alsa05.h"
+#include "SigTimer.h"
+#include <pthread.h>
+
+typedef unsigned char uchar;
+typedef void (*MIDI_Callback_function)(int arrivalPort);
+
+
+class MidiInPort_alsa05 : public Sequencer_alsa05 {
+ public:
+ MidiInPort_alsa05 (void);
+ MidiInPort_alsa05 (int aPort, int autoOpen = 1);
+ ~MidiInPort_alsa05 ();
+
+ void clearSysex (int buffer);
+ void clearSysex (void);
+ void close (void);
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getBufferSize (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ uchar* getSysex (int buffer);
+ int getSysexSize (int buffer);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ int installSysex (uchar* anArray, int aSize);
+ MidiMessage& message (int index);
+ int open (void);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ static Array<int> threadinitport;
+
+ protected:
+ int port; // the port to which this object belongs
+
+ static MIDI_Callback_function callbackFunction;
+
+ static int installSysexPrivate (int port,
+ uchar* anArray, int aSize);
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* trace; // for verifying input
+ static ostream* tracedisplay; // stream for displaying trace
+ static int numDevices; // number of input ports
+ static CircularBuffer<MidiMessage>** midiBuffer; // MIDI storage frm ports
+ static int channelOffset; // channel offset, either 0 or 1
+ // not being used right now.
+ static int* pauseQ; // for adding items to Buffer or not
+ static SigTimer midiTimer; // for timing MIDI input
+ static Array<pthread_t> midiInThread; // for MIDI input thread function
+ static int* sysexWriteBuffer; // for MIDI sysex write location
+ static Array<uchar>** sysexBuffers; // for MIDI sysex storage
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+
+
+ friend void *interpretMidiInputStreamPrivateALSA05(void * x);
+
+};
+
+
+#endif /* ALSA05 */
+#endif /* LINUX */
+
+#endif /* _MIDIINPORT_ALSA05_H_INCLUDED */
+
+
+
+// md5sum: 7b85b4a658c6f1d45dc1da7752f25cae - MidiInPort_alsa05.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_linux.h b/src/midiio/include/MidiInPort_linux.h
new file mode 100644
index 0000000..589d27a
--- /dev/null
+++ b/src/midiio/include/MidiInPort_linux.h
@@ -0,0 +1,94 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:30:04 PDT 2000
+// Last Modified: Thu May 18 23:36:07 PDT 2000 (added ifdef LINUX lines)
+// Last Modified: Sat Nov 2 20:37:49 PST 2002 (added ifdef ALSA OSS)
+// Filename: ...sig/maint/code/control/MidiInPort/MidiInPort_linux.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort_linux.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of an
+// operating-system specific MIDI input method.
+// Provides control of all low-level MIDI input
+// functionality such that it will work on all
+// computers in the same manner.
+//
+
+#ifndef _MIDIINPORT_LINUX_H_INCLUDED
+#define _MIDIINPORT_LINUX_H_INCLUDED
+
+#ifdef LINUX
+#if defined(ALSA) && defined(OSS)
+
+#define MIDI_IN_UNKNOWN_SELECT 0
+#define MIDI_IN_OSS_SELECT 1
+#define MIDI_IN_ALSA_SELECT 2
+
+#include "MidiInPort_oss.h"
+#include "MidiInPort_alsa.h"
+#include "MidiInPort_unsupported.h"
+#include "MidiMessage.h"
+
+
+class MidiInPort_linux {
+ public:
+ MidiInPort_linux(void);
+ MidiInPort_linux(int aPort, int autoOpen = 1);
+ ~MidiInPort_linux();
+
+ void clearSysex (void);
+ void clearSysex (int buffer);
+ void close (void);
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getBufferSize (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ uchar* getSysex (int buffer);
+ int getSysexSize (int buffer);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ int installSysex (uchar* anArray, int aSize);
+ MidiMessage& message (int index);
+ int open (void);
+ MidiMessage& operator[] (int index);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setAndOpenPort (int aPort);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ static int getSelect (void);
+ static int selectOSS (void);
+ static int selectALSA (void);
+ static int selectUnknown (void);
+
+ private:
+
+ static int current; // the type of MIDI out selected
+ static int alsaQ; // boolean for if ALSA is present
+ static int ossQ; // boolean for if OSS is present
+ static int objectCount; // keeps track of static variables
+
+ static MidiInPort_oss *oss_input;
+ static MidiInPort_alsa *alsa_input;
+ static MidiInPort_unsupported *unknown_input;
+
+ void determineDrivers (void);
+};
+
+#endif /* ALSA and OSS def */
+#endif /* LINUX def */
+
+#endif /* _MIDIINPORT_LINUX_H_INCLUDED */
+
+
+// md5sum: cc3608fb63ccf222f018efc89a4275f0 - MidiInPort_linux.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_oss.h b/src/midiio/include/MidiInPort_oss.h
new file mode 100644
index 0000000..ffa5666
--- /dev/null
+++ b/src/midiio/include/MidiInPort_oss.h
@@ -0,0 +1,105 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Jan 8 08:33:57 PST 1999
+// Last Modified: Fri Jan 8 08:34:01 PST 1999
+// Last Modified: Tue Jun 29 16:18:02 PDT 1999 (added sysex capability)
+// Last Modified: Wed May 10 17:10:05 PDT 2000 (name change from _linux to _oss)
+// Filename: ...sig/maint/code/control/MidiInPort/linux/MidiInPort_oss.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort_oss.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux OSS sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#ifndef _MIDIINPORT_OSS_H_INCLUDED
+#define _MIDIINPORT_OSS_H_INCLUDED
+
+#ifdef LINUX
+
+#include "MidiMessage.h"
+#include "CircularBuffer.h"
+#include "Array.h"
+#include "Sequencer_oss.h"
+#include "SigTimer.h"
+#include <pthread.h>
+
+typedef unsigned char uchar;
+typedef void (*MIDI_Callback_function)(int arrivalPort);
+
+
+class MidiInPort_oss : public Sequencer_oss {
+ public:
+ MidiInPort_oss (void);
+ MidiInPort_oss (int aPort, int autoOpen = 1);
+ ~MidiInPort_oss ();
+
+ void clearSysex (int buffer);
+ void clearSysex (void);
+ void close (void);
+ void close (int i) { close(); }
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getBufferSize (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ uchar* getSysex (int buffer);
+ int getSysexSize (int buffer);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ int installSysex (uchar* anArray, int aSize);
+ MidiMessage& message (int index);
+ int open (void);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ protected:
+ int port; // the port to which this object belongs
+
+ static MIDI_Callback_function callbackFunction;
+
+ static int installSysexPrivate (int port,
+ uchar* anArray, int aSize);
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* trace; // for verifying input
+ static std::ostream* tracedisplay; // stream for displaying trace
+ static int numDevices; // number of input ports
+ static CircularBuffer<MidiMessage>** midiBuffer; // MIDI storage frm ports
+ static int channelOffset; // channel offset, either 0 or 1
+ // not being used right now.
+ static int* pauseQ; // for adding items to Buffer or not
+ static SigTimer midiTimer; // for timing MIDI input
+ static pthread_t midiInThread; // for MIDI input thread function
+ static int* sysexWriteBuffer; // for MIDI sysex write location
+ static Array<uchar>** sysexBuffers; // for MIDI sysex storage
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+
+
+ friend void *interpretMidiInputStreamPrivate(void * x);
+
+};
+
+
+#endif /* LINUX */
+
+#endif /* _MIDIINPORT_OSS_H_INCLUDED */
+
+
+
+// md5sum: 05331ff5c3806fc753ebebaeffa3c377 - MidiInPort_oss.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_unsupported.h b/src/midiio/include/MidiInPort_unsupported.h
new file mode 100644
index 0000000..1f3bcf0
--- /dev/null
+++ b/src/midiio/include/MidiInPort_unsupported.h
@@ -0,0 +1,89 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Jan 23 00:04:51 GMT-0800 1998
+// Last Modified: Fri Jan 23 00:04:58 GMT-0800 1998
+// Last Modified: Wed Jun 30 11:42:59 PDT 1999 (added sysex capability)
+// Filename: ...sig/code/control/MidiInPort/unsupported/MidiInPort_unsupported.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiInPort_unsupported.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// an unknown sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+// This class is used when there is no MIDI input, so
+// that MIDI programs can otherwise be compiled and run.
+// This file can also serve as a template for creating
+// an OS specific class for MIDI input.
+//
+
+#ifndef _MIDIINPUT_UNSUPPORTED_H_INCLUDED
+#define _MIDIINPUT_UNSUPPORTED_H_INCLUDED
+
+#include "MidiMessage.h"
+#include "CircularBuffer.h"
+#include "Array.h"
+
+class MidiInPort_unsupported {
+ public:
+ MidiInPort_unsupported (void);
+ MidiInPort_unsupported (int aPort, int autoOpen = 1);
+ ~MidiInPort_unsupported ();
+
+ void clearSysex (int index) { }
+ void clearSysex (void) { }
+ int getSysexSize (int index) { return 0; }
+ uchar* getSysex (int buffer) { return NULL; }
+ int installSysex (unsigned char *&, int &) { return 0; }
+ int getBufferSize (void) { return 0; }
+ void close (void);
+ void close (int i) { close(); }
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ MidiMessage& message (int index);
+ int open (void);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ protected:
+ int port; // the port to which this object belongs
+ int trace;
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* openQ; // for open/close status of port
+ static int numDevices; // number of input ports
+ static CircularBuffer<MidiMessage>* midiBuffer; // MIDI storage from ports
+ static int channelOffset; // channel offset, either 0 or 1
+ // not being used right now.
+ static int* sysexWriteBuffer; // for MIDI sysex write location
+ static Array<uchar>** sysexBuffers; // for MIDI sysex storage
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void setPortStatus (int aStatus);
+
+
+};
+
+
+
+#endif /* _MIDIINPUT_UNSUPPORTED_H_INCLUDED */
+
+
+
+// md5sum: ff5492fbd59a47e48e2c0ce06705add1 - MidiInPort_unsupported.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_visual.h b/src/midiio/include/MidiInPort_visual.h
new file mode 100644
index 0000000..398a187
--- /dev/null
+++ b/src/midiio/include/MidiInPort_visual.h
@@ -0,0 +1,114 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Dec 28 15:18:46 GMT-0800 1997
+// Last Modified: Mon Jan 12 20:05:27 GMT-0800 1998
+// Last Modified: Wed Jun 30 11:29:51 PDT 1999 (added sysex capability)
+// Filename: ...sig/code/control/MidiInPort/visual/MidiInPort_visual.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiInPort_visual.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// Windows 95/NT/98 specific MIDI input methods.
+// as defined in winmm.lib. This class is inherited
+// privately by the MidiInPort class.
+//
+
+#ifndef _MIDIINPUT_VISUAL_H_INCLUDED
+#define _MIDIINPUT_VISUAL_H_INCLUDED
+
+
+#ifdef VISUAL
+
+#define DEFAULT_INPUT_BUFFER_SIZE (1024)
+
+#include <windows.h>
+#include <mmsystem.h>
+
+#include "MidiMessage.h"
+#include "CircularBuffer.h"
+#include "Array.h"
+
+class MidiInPort_visual {
+ public:
+ MidiInPort_visual (void);
+ MidiInPort_visual (int aPort, int autoOpen = 1);
+ ~MidiInPort_visual ();
+
+ void clearSysex (void);
+ void clearSysex (int buffer);
+ void close (void);
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getBufferSize (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ uchar* getSysex (int buffer);
+ int getSysexSize (int buffer);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ int installSysex (uchar* anArray, int aSize);
+ MidiMessage& message (int index);
+ int open (void);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ protected:
+ int port; // the port to which this object belongs
+ int trace;
+
+ int installSysexPrivate (int port, uchar* anArray, int aSize);
+ void installSysexStuff (HMIDIIN dev, int port);
+ void uninstallSysexStuff (HMIDIIN dev, int port);
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* openQ; // for open/close status of port
+ static int* inrunningQ; // for running open input port
+ static int numDevices; // number of input ports
+ static HMIDIIN* device; // Windoze MIDI-in device structure
+ static MIDIHDR** sysexDriverBuffer1; // for Windoze driver sysex buffers
+ static MIDIHDR** sysexDriverBuffer2; // for Windoze driver sysex buffers
+ static int* sysexDBnumber; // for Windoze driver sysex buffers
+ static HANDLE* hMutex; // mutual exclusive
+ static CircularBuffer<MidiMessage>* midiBuffer; // MIDI storage from ports
+ static int channelOffset; // channel offset from either 0 or 1.
+ // not being used right now.
+ static int* sysexWriteBuffer; // for MIDI sysex write location
+ static Array<uchar>** sysexBuffers;// for MIDI sysex storage
+ static int* sysexStatus; // tracing multiple MIM_LONGDATA messgs
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void releaseMutex (void);
+ void setPortStatus (int aStatus);
+ void waitForMutex (void);
+
+
+ friend void CALLBACK midiInputCallback(HMIDIIN hMidiIn, UINT inputStatus,
+ DWORD instancePtr, DWORD midiMessage, DWORD timestamp);
+};
+
+
+// This is the command which is called by the driver when there is
+// MIDI data being received from the MIDI input port:
+ void CALLBACK midiInputCallback(HMIDIIN hMidiIn, UINT inputStatus,
+ DWORD instancePtr, DWORD midiMessage, DWORD timestamp);
+
+
+#endif /* VISUAL */
+#endif /* _MIDIINPUT_VISUAL_H_INCLUDED */
+
+
+
+// md5sum: d5aee7a88c4a054b3e2d4d40622fdc42 - MidiInPort_visual.h =css= 20030102
diff --git a/src/midiio/include/MidiInput.h b/src/midiio/include/MidiInput.h
new file mode 100644
index 0000000..4425f75
--- /dev/null
+++ b/src/midiio/include/MidiInput.h
@@ -0,0 +1,53 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 18 December 1997
+// Last Modified: Sun Jan 25 15:27:02 GMT-0800 1998
+// Last Modified: Thu Apr 20 16:23:24 PDT 2000 (added scale function)
+// Filename: ...sig/code/control/MidiInput/MidiInput.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInput.h
+// Syntax: C++
+//
+// Description: A higher-level MIDI input interface than the
+// MidiInPort class. Can be used to allow multiple
+// objects to share a single MIDI input stream, or
+// to fake a MIDI input connection.
+//
+
+#ifndef _MIDIINPUT_H_INCLUDED
+#define _MIDIINPUT_H_INCLUDED
+
+
+#include "MidiInPort.h"
+
+
+class MidiInput : public MidiInPort {
+ public:
+ MidiInput (void);
+ MidiInput (int aPort, int autoOpen = 1);
+ ~MidiInput ();
+
+ int getBufferSize (void);
+ int getCount (void);
+ MidiMessage extract (void);
+ void insert (const MidiMessage& aMessage);
+ int isOrphan (void) const;
+ void makeOrphanBuffer (int aSize = 1024);
+ void removeOrphanBuffer(void);
+ void setBufferSize (int aSize);
+
+ int scale (int value, int min, int max);
+ double fscale (int value, double min, double max);
+ int scale14 (int value, int min, int max);
+ double fscale14 (int value, double min, double max);
+
+ protected:
+ CircularBuffer<MidiMessage>* orphanBuffer;
+
+};
+
+
+#endif /* _MIDIINPUT_H_INCLUDED */
+
+
+
+// md5sum: 73972cc29d7bcf0fba136b098c0419a0 - MidiInput.h =css= 20030102
diff --git a/src/midiio/include/MidiMessage.h b/src/midiio/include/MidiMessage.h
new file mode 100644
index 0000000..e4b59ba
--- /dev/null
+++ b/src/midiio/include/MidiMessage.h
@@ -0,0 +1,78 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 19 December 1997
+// Last Modified: Fri Jan 23 00:21:24 GMT-0800 1998
+// Last Modified: Sun Sep 20 20:30:53 PDT 1998
+// Last Modified: Mon Oct 15 14:29:12 PDT 2001 (added is_note functions)
+// Filename: ...sig/include/sigInfo/MidiMessage.h
+// Web Address: http://sig.sapp.org/include/sigInfo/MidiMessage.h
+// Syntax: C++
+//
+// Description: A structure for handling MIDI input messages.
+// This class stores a time stamp plus up to
+// four MIDI message bytes. System Exclusive messages
+// are stored in a separate array in the MidiInPort
+// class, and their storage index is passed to the
+// user through a MIDI message for later extraction
+// of the full sysex message.
+//
+
+#ifndef _MIDIMESSAGE_H_INCLUDED
+#define _MIDIMESSAGE_H_INCLUDED
+
+#include <iostream>
+
+typedef unsigned char uchar;
+typedef unsigned long ulong;
+
+class MidiMessage {
+ public:
+ ulong time; // timestamp
+ ulong data; // MIDI command and parameters
+
+ MidiMessage (void);
+ MidiMessage (int aCommand, int aP1, int aP2,
+ int aTime = 0);
+ MidiMessage (const MidiMessage& aMessage);
+ ~MidiMessage ();
+
+ uchar& command (void);
+ MidiMessage& operator= (const MidiMessage& aMessage);
+ uchar& operator[] (int index);
+ uchar& p0 (void);
+ uchar& p1 (void);
+ uchar& p2 (void);
+ uchar& p3 (void);
+ int getArgCount (void) const;
+ int getParameterCount (void) const;
+
+ uchar getCommand (void) const;
+ uchar getP0 (void) const;
+ uchar getP1 (void) const;
+ uchar getP2 (void) const;
+ uchar getP3 (void) const;
+
+ void setCommand (uchar aCommand);
+ void setData (uchar aCommand, uchar aP1 = 0,
+ uchar aP2 = 0, uchar aP3 = 0);
+ void setP0 (uchar aP0);
+ void setP1 (uchar aP1);
+ void setP2 (uchar aP2);
+ void setP3 (uchar aP3);
+
+ int is_note (void);
+ int is_note_on (void);
+ int is_note_off (void);
+
+};
+
+
+std::ostream& operator<<(std::ostream& out, MidiMessage& aMessage);
+
+
+#endif /* _MIDIMESSAGE_H_INCLUDED */
+
+
+
+// md5sum: 4738e957fb8a233f6dbaeebda490e6a4 - MidiMessage.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort.h b/src/midiio/include/MidiOutPort.h
new file mode 100644
index 0000000..0287dfd
--- /dev/null
+++ b/src/midiio/include/MidiOutPort.h
@@ -0,0 +1,92 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Dec 28 15:04:24 GMT-0800 1997
+// Last Modified: Fri Jan 23 10:56:18 GMT-0800 1998
+// Last Modified: Sat Nov 7 16:15:54 PST 1998
+// Last Modified: Tue May 23 23:08:44 PDT 2000 (oss/alsa selection added)
+// Last Modified: Mon Jun 19 10:32:11 PDT 2000 (oss/alsa define fix)
+// Filename: ...sig/code/control/MidiOutPort/MidiOutPort.h
+// Web Address: http://sig.sapp.org/include/sig/MidiOutPort.h
+// Syntax: C++
+//
+// Description: Operating-System independent interface for
+// basic MIDI output capabilities. Privately
+// inherits the operating-system specific class
+// for MIDI output.
+//
+
+#ifndef _MIDIOUTPORT_H_INCLUDED
+#define _MIDIOUTPORT_H_INCLUDED
+
+
+#ifdef VISUAL
+ #define MIDIOUTPORT MidiOutPort_visual
+ #include "MidiOutPort_visual.h"
+#elif defined(LINUX) && defined(ALSA) && defined(OSS)
+ #define MIDIOUTPORT MidiOutPort_linux
+ #include "MidiOutPort_linux.h"
+#elif defined(LINUX) && defined(ALSA) && !defined(OSS)
+ #define MIDIOUTPORT MidiOutPort_alsa
+ #include "MidiOutPort_alsa.h"
+#elif defined (LINUX) && defined(OSS) && !defined(ALSA)
+ #define MIDIOUTPORT MidiOutPort_oss
+ #include "MidiOutPort_oss.h"
+#elif defined(LINUX)
+ #define MIDIOUTPORT MidiOutPort_oss
+ #include "MidiOutPort_oss.h"
+#else
+ #define MIDIOUTPORT MidiOutPort_unsupported
+ #include "MidiOutPort_unsupported.h"
+#endif
+
+
+class MidiOutPort : protected MIDIOUTPORT {
+ public:
+ MidiOutPort (void) : MIDIOUTPORT() {}
+ MidiOutPort (int aPort, int autoOpen = 1) :
+ MIDIOUTPORT(aPort, autoOpen) {}
+ ~MidiOutPort() { }
+
+ void close(void) { MIDIOUTPORT::close(); }
+ void closeAll(void) { MIDIOUTPORT::closeAll(); }
+ int getChannelOffset(void) const {
+ return MIDIOUTPORT::getChannelOffset(); }
+ const char* getName(void) { return MIDIOUTPORT::getName(); }
+ static const char* getName(int i) { return MIDIOUTPORT::getName(i); }
+ static int getNumPorts(void) { return MIDIOUTPORT::getNumPorts(); }
+ int getPort(void) { return MIDIOUTPORT::getPort(); }
+ int getPortStatus(void) {
+ return MIDIOUTPORT::getPortStatus(); }
+ int getTrace(void) {
+ return MIDIOUTPORT::getTrace(); }
+ int open(void) { return MIDIOUTPORT::open(); }
+ int rawsend(int command, int p1, int p2) {
+ return MIDIOUTPORT::rawsend(command, p1, p2); }
+ int rawsend(int command, int p1) {
+ return MIDIOUTPORT::rawsend(command, p1); }
+ int rawsend(int command) {
+ return MIDIOUTPORT::rawsend(command); }
+ int rawsend(uchar* array, int size) {
+ return MIDIOUTPORT::rawsend(array, size); }
+ void setAndOpenPort(int aPort) { setPort(aPort); open(); }
+// void setChannelOffset(int aChannel) {
+// MIDIOUTPORT::setChannelOffset(aChannel); }
+ void setPort(int aPort) { MIDIOUTPORT::setPort(aPort); }
+ int setTrace(int aState) {
+ return MIDIOUTPORT::setTrace(aState); }
+ int sysex(uchar* array, int size) {
+ return MIDIOUTPORT::sysex(array, size); }
+ void toggleTrace(void) { MIDIOUTPORT::toggleTrace(); }
+ MidiOutPort& operator=(MidiOutPort& other) {
+ setPort(other.getPort());
+ if (other.getPortStatus()) { open(); }
+ return *this; }
+};
+
+
+
+
+#endif /* _MIDIOUTPORT_H_INCLUDED */
+
+
+// md5sum: 2f7b8aa8ef705eab57179b626ce1d62d - MidiOutPort.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort_alsa.h b/src/midiio/include/MidiOutPort_alsa.h
new file mode 100644
index 0000000..34139a3
--- /dev/null
+++ b/src/midiio/include/MidiOutPort_alsa.h
@@ -0,0 +1,79 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed May 10 16:22:00 PDT 2000
+// Last Modified: Sun May 14 20:43:44 PDT 2000
+// Last Modified: Sat Nov 2 20:39:01 PST 2002 (added ALSA def)
+// Filename: ...sig/maint/code/control/MidiOutPort/linux/MidiOutPort_alsa.h
+// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_alsa.h
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Linux using
+// OSS sound drivers. Privately inherited by the
+// MidiOutPort class.
+//
+
+#ifndef _MIDIOUTPORT_ALSA_H_INCLUDED
+#define _MIDIOUTPORT_ALSA_H_INCLUDED
+
+#ifdef LINUX
+#ifdef ALSA
+
+#include "Sequencer_alsa.h"
+#include <iostream>
+
+typedef unsigned char uchar;
+
+
+class MidiOutPort_alsa : public Sequencer_alsa {
+ public:
+ MidiOutPort_alsa (void);
+ MidiOutPort_alsa (int aPort, int autoOpen = 1);
+ ~MidiOutPort_alsa ();
+
+ void close (void);
+ void closeAll (void);
+ int getChannelOffset (void) const;
+ const char* getName (void);
+ static const char* getName (int i);
+ int getPort (void);
+ static int getNumPorts (void);
+ int getPortStatus (void);
+ int getTrace (void);
+ int rawsend (int command, int p1, int p2);
+ int rawsend (int command, int p1);
+ int rawsend (int command);
+ int rawsend (uchar* array, int size);
+ int open (void);
+ void setChannelOffset (int aChannel);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ int sysex (uchar* array, int size);
+ void toggleTrace (void);
+
+ protected:
+ int port; // the port to which this object belongs
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int numDevices; // number of output ports
+ static int* trace; // for printing messages to output
+ static std::ostream* tracedisplay; // for printing trace messages
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void setPortStatus (int aStatus);
+
+ static int channelOffset; // channel offset, either 0 or 1.
+ // not being used right now.
+};
+
+
+
+#endif /* ALSA */
+#endif /* LINUX */
+#endif /* _MIDIOUTPUT_ALSA_H_INCLUDED */
+
+
+// md5sum: 5b7648c7b493df7cb0d1fae3bbb8be24 - MidiOutPort_alsa.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort_linux.h b/src/midiio/include/MidiOutPort_linux.h
new file mode 100644
index 0000000..a02dc22
--- /dev/null
+++ b/src/midiio/include/MidiOutPort_linux.h
@@ -0,0 +1,80 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed May 10 16:03:52 PDT 2000
+// Last Modified: Thu May 18 23:37:17 PDT 2000
+// Last Modified: Sat Nov 2 20:40:01 PST 2002 (added ALSA OSS def)
+// Filename: ...sig/code/control/MidiOutPort_linux/MidiOutPort_linux.h
+// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_linux.h
+// Syntax: C++
+//
+// Description: Linux MIDI output class which detects which
+// type of MIDI drivers are available: either
+// ALSA or OSS.
+//
+
+#ifndef _MIDIOUTPORT_LINUX_H_INCLUDED
+#define _MIDIOUTPORT_LINUX_H_INCLUDED
+
+#ifdef LINUX
+#if defined(ALSA) && defined(OSS)
+
+#include "MidiOutPort_oss.h"
+#include "MidiOutPort_alsa.h"
+#include "MidiOutPort_unsupported.h"
+
+#define UNKNOWN_MIDI_SELECT 0 /* use dummy MIDI output */
+#define OSS_MIDI_SELECT 1 /* use OSS MIDI output */
+#define ALSA_MIDI_SELECT 2 /* use ALSA MIDI output */
+
+class MidiOutPort_linux {
+ public:
+ MidiOutPort_linux (void);
+ MidiOutPort_linux (int aPort, int autoOpen = 1);
+ ~MidiOutPort_linux ();
+
+ void close (void);
+ void closeAll (void);
+ int getChannelOffset (void) const;
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ int getTrace (void);
+ int open (void);
+ int rawsend (int command, int p1, int p2);
+ int rawsend (int command, int p1);
+ int rawsend (int command);
+ int rawsend (uchar* array, int size);
+ void setAndOpenPort (int aPort);
+ void setChannelOffset (int aChannel);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ int sysex (uchar* array, int size);
+ void toggleTrace (void);
+
+ static int getSelect (void);
+ static int selectOSS (void);
+ static int selectALSA (void);
+ static int selectUnknown (void);
+
+ private:
+ static int current; // the type of MIDI out selected
+ static int alsaQ; // boolean for if ALSA is present
+ static int ossQ; // boolean for if OSS is present
+
+ static int objectCount;
+ static MidiOutPort_oss *oss_output;
+ static MidiOutPort_alsa *alsa_output;
+ static MidiOutPort_unsupported *unknown_output;
+
+ void determineDrivers (void);
+};
+
+#endif /* ALSA and OSS */
+#endif /* LINUX */
+
+#endif /* _MIDIOUTPORT_LINUX_H_INCLUDED */
+
+
+// md5sum: c80f9f47c45a6d4a20b6549743cae9fb - MidiOutPort_linux.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort_oss.h b/src/midiio/include/MidiOutPort_oss.h
new file mode 100644
index 0000000..22cf32d
--- /dev/null
+++ b/src/midiio/include/MidiOutPort_oss.h
@@ -0,0 +1,75 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Dec 18 19:15:00 PST 1998
+// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _linux to _oss)
+// Filename: ...sig/maint/code/control/MidiOutPort/linux/MidiOutPort_oss.h
+// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_oss.h
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Linux using
+// OSS sound drivers. Privately inherited by the
+// MidiOutPort class.
+//
+
+#ifndef _MIDIOUTPORT_OSS_H_INCLUDED
+#define _MIDIOUTPORT_OSS_H_INCLUDED
+
+#ifdef LINUX
+
+#include "Sequencer_oss.h"
+
+typedef unsigned char uchar;
+
+
+class MidiOutPort_oss : public Sequencer_oss {
+ public:
+ MidiOutPort_oss (void);
+ MidiOutPort_oss (int aPort, int autoOpen = 1);
+ ~MidiOutPort_oss ();
+
+ void close (void);
+ void closeAll (void);
+ int getChannelOffset (void) const;
+ const char* getName (void);
+ static const char* getName (int i);
+ int getPort (void);
+ static int getNumPorts (void);
+ int getPortStatus (void);
+ int getTrace (void);
+ int rawsend (int command, int p1, int p2);
+ int rawsend (int command, int p1);
+ int rawsend (int command);
+ int rawsend (uchar* array, int size);
+ int open (void);
+ void setChannelOffset (int aChannel);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ int sysex (uchar* array, int size);
+ void toggleTrace (void);
+
+ protected:
+ int port; // the port to which this object belongs
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int numDevices; // number of output ports
+ static int* trace; // for printing messages to output
+ static std::ostream* tracedisplay; // for printing trace messages
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void setPortStatus (int aStatus);
+
+ static int channelOffset; // channel offset, either 0 or 1.
+ // not being used right now.
+};
+
+
+
+#endif /* LINUX */
+#endif /* _MIDIOUTPUT_OSS_H_INCLUDED */
+
+
+// md5sum: f60183e23c49741e93d9b965bbe9a6d8 - MidiOutPort_oss.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort_unsupported.h b/src/midiio/include/MidiOutPort_unsupported.h
new file mode 100644
index 0000000..a5e8c35
--- /dev/null
+++ b/src/midiio/include/MidiOutPort_unsupported.h
@@ -0,0 +1,71 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Mon Jan 12 21:36:26 GMT-0800 1998
+// Last Modified: Mon Jan 12 21:36:31 GMT-0800 1998
+// Filename: ...sig/code/control/MidiOutPort/unsupported/MidiOutPort_unsupported.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiOutPort_unsupported.h
+// Syntax: C++
+//
+// Description: Operating-System specific interface for basic MIDI output
+// capabilities in an unknown operating system. Privately
+// inherited by the MidiOutPort class. Used for compiling
+// and running MIDI programs on a computer with no
+// MIDI output.
+//
+
+#ifndef _MIDIOUTPUT_UNSUPPORTED_H_INCLUDED
+#define _MIDIOUTPUT_UNSUPPORTED_H_INCLUDED
+
+typedef unsigned char uchar;
+
+class MidiOutPort_unsupported {
+ public:
+ MidiOutPort_unsupported (void);
+ MidiOutPort_unsupported (int aPort, int autoOpen = 1);
+ ~MidiOutPort_unsupported ();
+
+ void close (void);
+ void closeAll (void);
+ int getChannelOffset (void) const;
+ const char* getName (void) const;
+ const char* getName (int i) const;
+ int getPort (void) const;
+ int getNumPorts (void) const;
+ int getPortStatus (void) const;
+ int getTrace (void) const;
+ int rawsend (int command, int p1, int p2);
+ int rawsend (int command, int p1);
+ int rawsend (int command);
+ int rawsend (uchar* array, int size);
+ int open (void);
+ void setChannelOffset (int aChannel);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ int sysex (uchar* array, int size);
+ void toggleTrace (void);
+
+ protected:
+ int port; // the port to which this object belongs
+ int trace; // for printing out midi messages to standard output
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* openQ; // for open/close status of port
+ static int numDevices; // number of output ports
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void setPortStatus (int aStatus);
+
+ static int channelOffset; // channel offset, either 0 or 1
+ // not being used right now.
+};
+
+
+
+#endif /* _MIDIOUTPUT_UNSUPPORTED_H_INCLUDED */
+
+
+
+// md5sum: e244688a99d220addc7b1c6f6f6a8022 - MidiOutPort_unsupported.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort_visual.h b/src/midiio/include/MidiOutPort_visual.h
new file mode 100644
index 0000000..d6a3984
--- /dev/null
+++ b/src/midiio/include/MidiOutPort_visual.h
@@ -0,0 +1,75 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Dec 28 15:18:46 GMT-0800 1997
+// Last Modified: Mon Jan 12 20:05:27 GMT-0800 1998
+// Filename: ...sig/code/control/MidiOutPort/visual/MidiOutPort_visual.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiOutPort_visual.h
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Windows 95/NT/98
+// using winmm.lib. Privately inherited by the
+// MidiOutPort class.
+//
+
+#ifndef _MIDIOUTPUT_VISUAL_H_INCLUDED
+#define _MIDIOUTPUT_VISUAL_H_INCLUDED
+
+#ifdef VISUAL
+
+typedef unsigned char uchar;
+
+#include <windows.h>
+#include <mmsystem.h>
+
+class MidiOutPort_visual {
+ public:
+ MidiOutPort_visual (void);
+ MidiOutPort_visual (int aPort, int autoOpen = 1);
+ ~MidiOutPort_visual ();
+
+ void close (void);
+ void closeAll (void);
+ int getChannelOffset (void) const;
+ const char* getName (void);
+ static const char* getName (int i);
+ int getPort (void);
+ static int getNumPorts (void);
+ int getPortStatus (void);
+ int getTrace (void);
+ int rawsend (int command, int p1, int p2);
+ int rawsend (int command, int p1);
+ int rawsend (int command);
+ int rawsend (uchar* array, int size);
+ int open (void);
+ void setChannelOffset (int aChannel);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ int sysex (uchar* array, int size);
+ void toggleTrace (void);
+
+ protected:
+ int port; // the port to which this object belongs
+ int trace; // for printing out Midi messages to standard output
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* openQ; // for open/close status of port
+ static int numDevices; // number of output ports
+ static HMIDIOUT* device; // Windoze midi out device structure
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void setPortStatus (int aStatus);
+
+ static int channelOffset; // channel offset, either 0 or 1.
+ // not being used right now.
+};
+
+
+#endif /* VISUAL */
+#endif /* _MIDIOUTPUT_VISUAL_H_INCLUDED */
+
+
+// md5sum: 47799e340effa57676be8a3943cabb70 - MidiOutPort_visual.h =css= 20030102
diff --git a/src/midiio/include/MidiOutput.h b/src/midiio/include/MidiOutput.h
new file mode 100644
index 0000000..d424816
--- /dev/null
+++ b/src/midiio/include/MidiOutput.h
@@ -0,0 +1,140 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 18 December 1997
+// Last Modified: Mon Jan 26 23:53:05 GMT-0800 1998
+// Last Modified: Sat Jan 30 14:00:29 PST 1999
+// Last Modified: Sun Jul 18 18:52:42 PDT 1999 (added RPN functions)
+// Filename: ...sig/maint/code/control/MidiOutput/MidiOutput.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiOutput.h
+// Syntax: C++
+//
+// Description: The MIDI output interface for MIDI synthesizers/equipment
+// which has many convienience functions defined for
+// various types of MIDI output.
+//
+
+#ifndef _MIDIOUTPUT_H_INCLUDED
+#define _MIDIOUTPUT_H_INCLUDED
+
+#include "MidiOutPort.h"
+#include "FileIO.h"
+#include "SigTimer.h"
+#include "Array.h"
+
+
+class MidiOutput : public MidiOutPort {
+ public:
+ MidiOutput (void);
+ MidiOutput (int aPort, int autoOpen = 1);
+ ~MidiOutput ();
+
+ // Basic user MIDI output commands:
+ int cont (int channel, int controller, int data);
+ int off (int channel, int keynum, int releaseVelocity);
+ int pc (int channel, int timbre);
+ int play (int channel, int keynum, int velocity);
+ int pw (int channel, int mostByte, int leastByte);
+ int pw (int channel, int tuningData);
+ int pw (int channel, double tuningData);
+ void recordStart (char *filename, int format);
+ void recordStop (void);
+ void reset (void);
+ int send (int command, int p1, int p2);
+ int send (int command, int p1);
+ int send (int command);
+ void silence (int aChannel = -1);
+ void sustain (int channel, int status);
+ int sysex (char* data, int length);
+ int sysex (uchar* data, int length);
+
+ protected:
+ int outputRecordQ; // boolean for recording
+ int outputRecordType; // what form to record MIDI data in
+ int lastFlushTime; // for recording midi data
+ FileIO outputRecordFile; // file for recording midi data
+ static SigTimer timer; // for recording midi data
+ static Array<int>* rpn_lsb_status; // for RPN messages
+ static Array<int>* rpn_msb_status; // for RPN messages
+ static int objectCount; // for RPN messages
+
+ void deinitializeRPN (void);
+ void initializeRPN (void);
+ void writeOutputAscii (int channel, int p1, int p2);
+ void writeOutputBinary (int channel, int p1, int p2);
+ void writeOutputMidifile(int channel, int p1, int p2);
+
+ public: // RPN controller functions
+ int NRPN (int channel, int nrpn_msb, int nrpn_lsb,
+ int data_msb, int data_lsb);
+ int NRPN (int channel, int nrpn_msb, int nrpn_lsb,
+ int data_msb);
+ int NRPN (int channel, int nrpn_msb, int nrpn_lsb,
+ double data);
+ int NRPN_null (int channel);
+ int NRPN_attack (int channel, double value);
+ int NRPN_attack (int channel, int value);
+ int NRPN_decay (int channel, double value);
+ int NRPN_decay (int channel, int value);
+ int NRPN_drumAttack (int drum, double value);
+ int NRPN_drumAttack (int drum, int value);
+ int NRPN_drumChorus (int drum, double value);
+ int NRPN_drumChorus (int drum, int value);
+ int NRPN_drumDecay (int drum, double value);
+ int NRPN_drumDecay (int drum, int value);
+ int NRPN_drumLevel (int drum, double value);
+ int NRPN_drumLevel (int drum, int value);
+ int NRPN_drumPan (int drum, double value);
+ int NRPN_drumPan (int drum, int value);
+ int NRPN_drumPitch (int drum, double value);
+ int NRPN_drumPitch (int drum, int value);
+ int NRPN_drumFilterCutoff (int drum, double value);
+ int NRPN_drumFilterCutoff (int drum, int value);
+ int NRPN_drumFilterResonance(int drum, double value);
+ int NRPN_drumFilterResonance(int drum, int value);
+ int NRPN_drumReverb (int drum, double value);
+ int NRPN_drumReverb (int drum, int value);
+ int NRPN_drumVariation (int drum, double value);
+ int NRPN_drumVariation (int drum, int value);
+ int NRPN_filterCutoff (int channel, double value);
+ int NRPN_filterCutoff (int channel, int value);
+ int NRPN_release (int channel, double value);
+ int NRPN_release (int channel, int value);
+ int NRPN_vibratoDelay (int channel, double value);
+ int NRPN_vibratoDelay (int channel, int value);
+ int NRPN_vibratoDepth (int channel, double value);
+ int NRPN_vibratoDepth (int channel, int value);
+ int NRPN_vibratoRate (int channel, double value);
+ int NRPN_vibratoRate (int channel, int value);
+
+ int RPN (int channel, int rpn_msb, int rpn_lsb,
+ int data_msb, int data_lsb);
+ int RPN (int channel, int rpn_msb, int rpn_lsb,
+ int data_msb);
+ int RPN (int channel, int rpn_msb, int rpn_lsb,
+ double data);
+ int RPN_null (void);
+ int RPN_null (int channel);
+ int pbRange (int channel, int steps);
+ int tuneFine (int channel, int cents);
+ int fineTune (int channel, int cents);
+ int tuneCoarse (int channel, int steps);
+ int coarseTune (int channel, int steps);
+ int tuningProgram (int channel, int program);
+ int tuningBank (int channel, int bank);
+
+};
+
+
+#endif /* _MIDIOUTPUT_H_INCLUDED */
+
+// Brief description of MidiOutput public member functions:
+//
+// send: sends a MIDI command to the MIDI output with up to two parameters
+// play: sends a playnote command to the MIDI output
+// pc: Patch Change. changes the timbre (instrument) on the given channel
+// cont: sends a CONTinuous CONTroller MIDI command
+// sysex: sends a system exclusive command to the MIDI output
+//
+
+
+// md5sum: 12ee02c32563ae219aaa8c7599de55db - MidiOutput.h =css= 20030102
diff --git a/src/midiio/include/MidiPort.h b/src/midiio/include/MidiPort.h
new file mode 100644
index 0000000..834877e
--- /dev/null
+++ b/src/midiio/include/MidiPort.h
@@ -0,0 +1,49 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Fri Jan 23 10:21:25 GMT-0800 1998
+// Filename: .../sig/code/control/MidiPort/MidiPort.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiPort.h
+// Syntax: C++
+//
+// Description: A unified object that handles basic MIDI input and output.
+// Derived from the MidiInPort and MidiOutPort classes.
+//
+
+#ifndef _MIDIPORT_H_INCLUDED
+#define _MIDIPORT_H_INCLUDED
+
+
+#include "MidiInPort.h"
+#include "MidiOutPort.h"
+
+
+class MidiPort : public MidiOutPort, public MidiInPort {
+ public:
+ MidiPort (void);
+ MidiPort (int outputPort, int inputPort);
+ ~MidiPort ();
+
+ int getChannelInOffset (void) const;
+ int getChannelOutOffset (void) const;
+ int getInputPort (void);
+ int getInputTrace (void);
+ int getOutputPort (void);
+ int getOutputTrace (void);
+ void setChannelOffset (int anOffset);
+ void setInputPort (int aPort);
+ int setInputTrace (int aState);
+ void setOutputPort (int aPort);
+ int setOutputTrace (int aState);
+ void toggleInputTrace (void);
+ void toggleOutputTrace (void);
+
+};
+
+
+
+#endif /* _MIDIPORT_H_INCLUDED */
+
+
+
+// md5sum: 84d8155528b06c9aa902e8f06649385f - MidiPort.h =css= 20030102
diff --git a/src/midiio/include/Options.h b/src/midiio/include/Options.h
new file mode 100644
index 0000000..71754fb
--- /dev/null
+++ b/src/midiio/include/Options.h
@@ -0,0 +1,106 @@
+//
+// Copyright 1998-2000 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Apr 5 13:07:18 PDT 1998
+// Last Modified: Fri Jan 15 07:24:00 PST 1999
+// Last Modified: Sat Mar 27 18:17:59 PST 1999
+// Last Modified: Thu Apr 13 14:02:52 PDT 2000 (added 2nd define function)
+// Last Modified: Fri May 5 17:57:50 PDT 2000 (added --options suppression)
+// Filename: ...sig/maint/code/base/Options/Options.h
+// Web Address: http://sig.sapp.org/include/sigBase/Options.h
+// Documentation: http://sig.sapp.org/doc/classes/Options
+// Syntax: C++
+//
+// Description: Handles command-line options in a graceful manner.
+//
+
+#ifndef _OPTIONS_H_INCLUDED
+#define _OPTIONS_H_INCLUDED
+
+#include "Array.h"
+
+class option_list;
+class option_register;
+
+
+class Options {
+ public:
+ Options (void);
+ Options (int argc, char** argv);
+ ~Options ();
+
+ int argc (void) const;
+ char** argv (void) const;
+ void define (const char* aDefinition);
+ void define (const char* aDefinition,
+ const char* description);
+ char* getArg (int index);
+ char* getArgument (int index);
+ int getArgCount (void);
+ int getArgumentCount (void);
+ int getBoolean (const char* optionName);
+ const char* getCommand (void);
+ const char* getCommandLine (void);
+ const char* getString (void);
+ const char* getDefinition (const char* optionName);
+ double getDouble (const char* optionName);
+ char getFlag (void);
+ float getFloat (const char* optionName);
+ int getInt (const char* optionName);
+ int getInteger (const char* optionName);
+ const char* getString (const char* optionName);
+ char getType (const char* optionName);
+ int optionsArg (void);
+ void print (void);
+ void process (int error_check = 1, int suppress = 0);
+ void process (int argc, char** argv,
+ int error_check = 1,
+ int suppress = 0);
+ void reset (void);
+ void verify (int argc, char** argv,
+ int error_check = 1,
+ int suppress = 0);
+ void verify (int error_check = 1,
+ int suppress = 0);
+ void setFlag (char aFlag);
+ void setModified (const char* optionName,
+ const char* optionValue);
+ void setOptions (int argc, char** argv);
+
+ protected:
+ int options_error_check; // for verify command
+ int gargc;
+ char** gargv;
+ char* commandString;
+ char optionFlag;
+ Array<char*> argument;
+ Array<option_register*> optionRegister;
+ Array<option_list*> optionList;
+ int processedQ;
+ int sortedQ;
+ int suppressQ; // prevent the --options option
+ int optionsArgument; // indicates --options present
+
+ int getRegIndex (const char* optionName);
+ int optionQ (const char* aString, int& argp);
+ void sortOptionNames (void);
+ int storeOption (int gargp, int& position,
+ int& running);
+
+};
+
+#define OPTION_BOOLEAN_TYPE 'b'
+#define OPTION_CHAR_TYPE 'c'
+#define OPTION_DOUBLE_TYPE 'd'
+#define OPTION_FLOAT_TYPE 'f'
+#define OPTION_INT_TYPE 'i'
+#define OPTION_STRING_TYPE 's'
+#define OPTION_UNKNOWN_TYPE 'x'
+
+
+
+#endif /* _OPTIONS_H_INCLUDED */
+
+
+
+// md5sum: c59d297a8081cb48f61b534484819f48 - Options.h =css= 20030102
diff --git a/src/midiio/include/Options_private.h b/src/midiio/include/Options_private.h
new file mode 100644
index 0000000..8349d55
--- /dev/null
+++ b/src/midiio/include/Options_private.h
@@ -0,0 +1,73 @@
+//
+// Copyright 1998-1999 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Apr 5 13:07:18 PDT 1998
+// Last Modified: Sun Jan 10 05:44:48 PST 1999
+// Filename: ...sig/maint/code/base/Options/Options_private.h
+// Web Address: http://sig.sapp.org/include/sigBase/Options_private.h
+// Syntax: C++
+//
+// Description: A private function for use in the Options class.
+//
+
+#ifndef _OPTIONS_PRIVATE_H_INCLUDED
+#define _OPTIONS_PRIVATE_H_INCLUDED
+
+
+class option_register {
+ public:
+ option_register (void);
+ option_register (const char* aDefinition, char aType,
+ const char* aDefaultOption,
+ const char* aModifiedOption);
+ ~option_register ();
+ void clearModified (void);
+ const char* getDefinition (void);
+ const char* getDefault (void);
+ const char* getOption (void);
+ const char* getModified (void);
+ int getModifiedQ (void);
+ char getType (void);
+ void reset (void);
+ void setDefault (const char* aString);
+ void setDefinition (const char* aString);
+ void setModified (const char* aString);
+ void setType (char aType);
+
+ protected:
+ char* definition;
+ char* defaultOption;
+ char* modifiedOption;
+ char type;
+
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+
+class option_list {
+ public:
+ option_list (void);
+ option_list (const char* optionName, int anIndex);
+ ~option_list ();
+
+ int getIndex (void);
+ const char* getName (void);
+ void setName (const char* aString);
+ void setIndex (int anIndex);
+
+ protected:
+ char* name;
+ int index;
+
+};
+
+
+
+#endif /* _OPTIONS_PRIVATE_H_INCLUDED */
+
+
+
+// md5sum: b440ad2158e9921d0e31463a8c3e1ae0 - Options_private.h =css= 20030102
diff --git a/src/midiio/include/Sequencer_alsa.h b/src/midiio/include/Sequencer_alsa.h
new file mode 100644
index 0000000..3227f5e
--- /dev/null
+++ b/src/midiio/include/Sequencer_alsa.h
@@ -0,0 +1,139 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Thu May 11 21:06:21 PDT 2000
+// Last Modified: Sat Oct 13 14:50:04 PDT 2001 (updated for ALSA 0.9 interface)
+// Filename: ...sig/maint/code/control/MidiOutPort/Sequencer_alsa.h
+// Web Address: http://sig.sapp.org/include/sig/Sequencer_alsa.h
+// Syntax: C++
+//
+// Description: Basic MIDI input/output functionality for the
+// Linux ALSA midi device /dev/snd/midiXX. This class
+// is inherited by the classes MidiInPort_alsa and
+// MidiOutPort_alsa.
+//
+// to get information of status a alsa hardware & software
+// cat /proc/asound/version
+// cat /proc/asound/devices
+// cat /proc/asound/card0/midi0
+//
+
+#ifndef _SEQUENCER_ALSA_H_INCLUDED
+#define _SEQUENCER_ALSA_H_INCLUDED
+
+#include <iostream>
+
+#ifdef ALSA
+
+#include <alsa/asoundlib.h>
+#include "Collection.h"
+
+#define MIDI_EXTERNAL (1)
+#define MIDI_INTERNAL (2)
+
+typedef unsigned char uchar;
+
+
+class Sequencer_alsa {
+ public:
+ Sequencer_alsa (int autoOpen = 1);
+ ~Sequencer_alsa ();
+
+ void close (void);
+ void closeInput (int index);
+ void closeOutput (int index);
+ void displayInputs (std::ostream& out = std::cout,
+ char* initial = "\t");
+ void displayOutputs (std::ostream& out = std::cout,
+ char* initial = "\t");
+ static const char* getInputName (int aDevice);
+ static const char* getOutputName (int aDevice);
+ static int getNumInputs (void);
+ static int getNumOutputs (void);
+ int is_open (int mode, int index);
+ int is_open_in (int index);
+ int is_open_out (int index);
+ int open (int direction, int index);
+ int openInput (int index);
+ int openOutput (int index);
+ void read (int dev, uchar* buf, int count);
+ void rebuildInfoDatabase (void);
+ int write (int aDevice, int aByte);
+ int write (int aDevice, uchar* bytes, int count);
+ int write (int aDevice, char* bytes, int count);
+ int write (int aDevice, int* bytes, int count);
+
+ int getInCardValue (int aDevice) const;
+ int getOutCardValue (int aDevice) const;
+ protected:
+ static int class_count; // number of existing classes using
+ static int indevcount; // number of MIDI input devices
+ static int outdevcount; // number of MIDI output devices
+ static int initialized; // for starting buileinfodatabase
+
+ static Collection<snd_rawmidi_t*> Sequencer_alsa::rawmidi_in;
+ static Collection<snd_rawmidi_t*> Sequencer_alsa::rawmidi_out;
+ static Collection<int> Sequencer_alsa::midiincard;
+ static Collection<int> Sequencer_alsa::midioutcard;
+ static Collection<int> Sequencer_alsa::midiindevice;
+ static Collection<int> Sequencer_alsa::midioutdevice;
+ static Collection<char*> Sequencer_alsa::midiinname;
+ static Collection<char*> Sequencer_alsa::midioutname;
+
+ private:
+ static void buildInfoDatabase (void);
+ static void getPossibleMidiStreams(Collection<int>& cards,
+ Collection<int>& devices);
+ int getInDeviceValue (int aDevice) const;
+ int getInputType (int aDevice) const;
+ int getOutDeviceValue (int aDevice) const;
+ int getOutputType (int aDevice) const;
+ void removeInfoDatabase (void);
+
+
+ friend void *interpretMidiInputStreamPrivateALSA(void * x);
+
+};
+
+#else /* ALSA is not defined */
+
+typedef unsigned char uchar;
+
+class Sequencer_alsa {
+ public:
+ Sequencer_alsa (int autoOpen = 1) { }
+ ~Sequencer_alsa () { }
+
+ void close (void) { };
+ void displayInputs (std::ostream& out = std::cout,
+ char* initial = "\t")
+ { out << initial << "NONE\n"; }
+ void displayOutputs (std::ostream& out = std::cout,
+ char* initial = "\t")
+ { out << initial << "NONE\n"; }
+ static const char* getInputName (int aDevice) { return ""; }
+ static const char* getOutputName (int aDevice) { return ""; }
+ static int getNumInputs (void) { return 0; }
+ static int getNumOutputs (void) { return 0; }
+ int is_open (int mode, int index) { return 0; }
+ int is_open_in (int index) { return 0; }
+ int is_open_out (int index) { return 0; }
+ int open (void) { return 0; }
+ void read (int dev, uchar* buf, int count) { }
+ void rebuildInfoDatabase (void) { }
+ int write (int aDevice, int aByte) { return 0; }
+ int write (int aDevice, uchar* bytes, int count) { return 0; }
+ int write (int aDevice, char* bytes, int count) { return 0; }
+ int write (int aDevice, int* bytes, int count) { return 0; }
+ int getInCardValue (int aDevice) const { return 0; }
+ int getOutCardValue (int aDevice) const { return 0; }
+
+};
+
+
+#endif /* ALSA */
+
+
+#endif /* _SEQUENCER_ALSA_H_INCLUDED */
+
+
+// md5sum: 6147020b0646fca8245f653505308949 - Sequencer_alsa.h =css= 20030102
diff --git a/src/midiio/include/Sequencer_oss.h b/src/midiio/include/Sequencer_oss.h
new file mode 100644
index 0000000..5f269a7
--- /dev/null
+++ b/src/midiio/include/Sequencer_oss.h
@@ -0,0 +1,92 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Jan 3 21:02:02 PST 1999
+// Last Modified: Sat Jan 30 14:11:18 PST 1999
+// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _oss to _oss)
+// Filename: ...sig/maint/code/control/MidiOutPort/Sequencer_oss.h
+// Web Address: http://sig.sapp.org/include/sig/Sequencer_oss.h
+// Syntax: C++
+//
+// Description: Basic MIDI input/output functionality for the
+// Linux OSS midi device /dev/sequencer. This class
+// is inherited by the classes MidiInPort_oss and
+// MidiOutPort_oss.
+//
+
+#ifndef _SEQUENCER_OSS_H_INCLUDED
+#define _SEQUENCER_OSS_H_INCLUDED
+
+#include <iostream>
+
+#define MIDI_EXTERNAL (1)
+#define MIDI_INTERNAL (2)
+
+typedef unsigned char uchar;
+
+
+class Sequencer_oss {
+ public:
+ Sequencer_oss (int autoOpen = 1);
+ ~Sequencer_oss ();
+
+ void close (void);
+ void displayInputs (std::ostream& out = std::cout,
+ char* initial = "\t");
+ void displayOutputs (std::ostream& out = std::cout,
+ char* initial = "\t");
+ static int getNumInputs (void);
+ static int getNumOutputs (void);
+ static const char* getInputName (int aDevice);
+ static const char* getOutputName (int aDevice);
+ int is_open (void);
+ int open (void);
+ void read (uchar* buf, uchar* dev, int count);
+ void rawread (uchar* buf, int packetCount);
+ void rebuildInfoDatabase (void);
+ int write (int aDevice, int aByte);
+ int write (int aDevice, uchar* bytes, int count);
+ int write (int aDevice, char* bytes, int count);
+ int write (int aDevice, int* bytes, int count);
+
+ protected:
+ static const char* sequencer; // name of sequencer device
+ static int sequencer_fd; // sequencer file descriptor
+ static int class_count; // number of existing classes using
+ static uchar midi_write_packet[4]; // for writing MIDI bytes out
+ static uchar midi_read_packet[4]; // for reading MIDI bytes out
+ static uchar synth_write_message[8]; // for writing to internal seq
+ static int indevcount; // number of MIDI input devices
+ static int outdevcount; // number of MIDI output devices
+ static char** indevnames; // MIDI input device names
+ static char** outdevnames; // MIDI output device names
+ static int* indevnum; // total number of MIDI inputs
+ static int* outdevnum; // total number of MIDI outputs
+ static int* indevtype; // 1 = External, 2 = Internal
+ static int* outdevtype; // 1 = External, 2 = Internal
+ static uchar synth_message_buffer[1024]; // hold bytes for synth dev
+ static int synth_message_buffer_count; // count of synth buffer
+ static int synth_message_bytes_expected; // expected count of synth
+ static int synth_message_curr_device; // for keeping track of dev
+ static int initialized; // for starting buileinfodatabase
+
+ private:
+ static void buildInfoDatabase (void);
+ static int getFd (void);
+ int getInDeviceValue (int aDevice) const;
+ int getInputType (int aDevice) const;
+ int getOutDeviceValue (int aDevice) const;
+ int getOutputType (int aDevice) const;
+ void removeInfoDatabase (void);
+ void setFd (int anFd);
+
+ int writeInternal(int aDevice, int aByte);
+ int transmitMessageToInternalSynth(void);
+ int transmitVoiceMessage(void);
+ int transmitCommonMessage(void);
+};
+
+
+#endif /* _SEQUENCER_OSS_H_INCLUDED */
+
+
+// md5sum: 1df08cd946c609b9b42aadbc96b7a296 - Sequencer_oss.h =css= 20030102
diff --git a/src/midiio/include/SigTimer.h b/src/midiio/include/SigTimer.h
new file mode 100644
index 0000000..e93345c
--- /dev/null
+++ b/src/midiio/include/SigTimer.h
@@ -0,0 +1,104 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Thanks to: Erik Neuenschwander <erikn@leland.stanford.edu>
+// for Windows 95 assembly code for Pentium clock cycles.
+// Ozgur Izmirli <ozgur@ccrma.stanford.edu>
+// for concept of periodic timer.
+// Creation Date: Mon Oct 13 11:34:57 GMT-0800 1997
+// Last Modified: Tue Feb 10 21:05:19 GMT-0800 1998
+// Last Modified: Sat Sep 19 15:56:48 PDT 1998
+// Last Modified: Mon Feb 22 04:44:25 PST 1999
+// Last Modified: Sun Nov 28 12:39:39 PST 1999 (added adjustPeriod())
+// Filename: .../sig/code/control/SigTimer/SigTimer.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/SigTimer.h
+// Syntax: C++
+//
+// Description: This class can only be used on Motorola Pentinum 75 Mhz
+// chips or better because the timing information is
+// extracted from the clock cycle count from a register
+// on the CPU itself. This class will estimate the
+// speed of the computer, but it would be better if there
+// was a way of finding out the speed from some function.
+// This class is used primarily for timing of MIDI input
+// and output at a millisecond resolution.
+//
+// Interesting: http://www.datasilicon.nl/I786/timer_1.htm
+//
+
+#ifndef _SIGTIMER_H_INCLUDED
+#define _SIGTIMER_H_INCLUDED
+
+
+#ifdef VISUAL
+ #include <wtypes.h>
+ typedef LONGLONG int64bits;
+#else
+ typedef long long int int64bits;
+ #include <unistd.h> /* for millisleep function */
+#endif
+
+
+class SigTimer {
+ public:
+ SigTimer (void);
+ SigTimer (int aSpeed);
+ SigTimer (SigTimer& aTimer);
+ ~SigTimer ();
+
+ void adjustPeriod (double periodDelta);
+ int expired (void) const;
+ double getPeriod (void) const;
+ double getPeriodCount (void) const;
+ double getTempo (void) const;
+ int getTicksPerSecond (void) const;
+ int getTime (void) const;
+ double getTimeInSeconds (void) const;
+ int getTimeInTicks (void) const;
+ void reset (void);
+ void setPeriod (double aPeriod);
+ void setTempo (double beatsPerMinute);
+ void setPeriodCount (double aCount);
+ void setTicksPerSecond (int aTickRate);
+ void start (void);
+ void sync (SigTimer& aTimer);
+ void update (void);
+ void update (int periodCount);
+
+ // The following functions are semi-private. They do not have
+ // anything to do with timing themselves, but are a by-product
+ // of the timer implementation. They are useful, so they have
+ // been left public; however, they should be used judiciously.
+ static int getCpuSpeed (void);
+ static int measureCpuSpeed (int quantize = 0);
+ static void setCpuSpeed (int aSpeed);
+
+ // the following function is hardware specific to Intel Pentium
+ // computers with a processor speed of at least 75 MHz.
+ // This function is the only non-portable function in this
+ // class, but everything else is based on it.
+ static int64bits clockCycles (void);
+
+ protected:
+ static int64bits globalOffset;
+ static int cpuSpeed;
+
+ int64bits offset;
+ int ticksPerSecond;
+ double period;
+
+ // protected functions
+ double getFactor (void) const;
+
+};
+
+
+// The following function is mostly for Linux:
+void millisleep(int milliseconds);
+void millisleep(float milliseconds);
+
+
+#endif /* _SIGTIMER_H_INCLUDED */
+
+
+
+// md5sum: 601fa3caae4e3bacc4e6fb87f545c86b - SigTimer.h =css= 20030102
diff --git a/src/midiio/include/Voice.h b/src/midiio/include/Voice.h
new file mode 100644
index 0000000..3cddf9f
--- /dev/null
+++ b/src/midiio/include/Voice.h
@@ -0,0 +1,70 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Oct 11 18:21:46 PDT 1998
+// Last Modified: Sun Oct 11 18:33:04 PDT 1998
+// Filename: ...sig/maint/code/control/Voice/Voice.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/Voice.h
+// Syntax: C++
+//
+// Description: The Voice class is a MIDI output class which keeps
+// track of the last note played in to it. If the last
+// note was not turned off when a new note is played,
+// then the old note will be turned off before the
+// new note is played.
+//
+
+#ifndef _VOICE_H_INCLUDED
+#define _VOICE_H_INCLUDED
+
+#include "MidiOutput.h"
+
+class Voice : public MidiOutput {
+ public:
+ Voice (int aChannel);
+ Voice (const Voice& aVoice);
+ Voice (void);
+ ~Voice ();
+
+ void cont (int controler, int data);
+ int getChan (void) const;
+ int getChannel (void) const;
+ int getKey (void) const;
+ int getKeynum (void) const;
+ int getOffTime (void) const;
+ int getOnTime (void) const;
+ int getVel (void) const;
+ int getVelocity (void) const;
+ void off (void);
+ void pc (int aTimbre);
+ void play (int aChannel, int aKeyno, int aVelocity);
+ void play (int aKeyno, int aVelocity);
+ void play (void);
+ void setChan (int aChannel);
+ void setChannel (int aChannel);
+ void setKey (int aKeyno);
+ void setKeynum (int aKeyno);
+ void setVel (int aVelocity);
+ void setVelocity (int aVelocity);
+ int status (void) const;
+ void sustain (int aStatus);
+
+ protected:
+ int chan; // the current channel number
+ int key; // the current key number
+ int vel; // the current velocity value
+
+ int onTime; // last note on message sent
+ int offTime; // last note off message sent
+
+ int oldChan; // last channel played on
+ int oldKey; // last key to be played
+ int oldVel; // last velocity of last key
+
+ static SigTimer timer; // for recording on/off times
+};
+
+
+#endif /* _VOICE_H_INCLUDED */
+
+
+// md5sum: 8a5495ecc10d42be6b1832492e107723 - Voice.h =css= 20030102
diff --git a/src/midiio/include/gminstruments.h b/src/midiio/include/gminstruments.h
new file mode 100644
index 0000000..0e567da
--- /dev/null
+++ b/src/midiio/include/gminstruments.h
@@ -0,0 +1,251 @@
+//
+// Copyright 1997-2000 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> (from 18Dec1997)
+// Creation Date: 26 December 1997
+// Last Modified: Tue Apr 18 11:38:28 PDT 2000 (put CH_X defines here)
+// Filename: ...sig/include/sigInfo/gminstruments.h
+// Web Address: http://sig.sapp.org/include/sigInfo/gminstruments.h
+// Syntax: C
+//
+// Description: Defines names for instruments as arranged in General MIDI.
+//
+
+#ifndef _GMINSTRUMENTS_H_INCLUDED
+#define _GMINSTRUMENTS_H_INCLUDED
+
+#define CH_1 0
+#define CH_2 1
+#define CH_3 2
+#define CH_4 3
+#define CH_5 4
+#define CH_6 5
+#define CH_7 6
+#define CH_8 7
+#define CH_9 8
+#define CH_10 9
+#define CH_11 10
+#define CH_12 11
+#define CH_13 12
+#define CH_14 13
+#define CH_15 14
+#define CH_16 15
+
+#define GM_PIANO(X) (0+(X))
+#define GM_ACOUSTIC_GRAND_PIANO (0)
+#define GM_BRIGHT_ACOUSTIC_PIANO (1)
+#define GM_ELECTRIC_GRAND_PIANO (1)
+#define GM_HONKYTONK_PIANO (2)
+#define GM_HONKY_TONK_PIANO (3)
+#define GM_ELECTRIC_PIANO_1 (4)
+#define GM_ELECTRIC_PIANO_2 (5)
+#define GM_HARPSICHORD (6)
+#define GM_CLAVI (7)
+
+#define GM_CHROMATIC(X) (8+(X))
+#define GM_CELESTA (8)
+#define GM_GLOCKENSPIEL (9)
+#define GM_MUSIC_BOX (10)
+#define GM_VIBRAPHONE (11)
+#define GM_MARIMBA (12)
+#define GM_XYLOPHONE (13)
+#define GM_TUBULAR_BELLS (14)
+#define GM_DULCIMER (15)
+
+#define GM_ORGAN(X) (16+(X))
+#define GM_DRAWBAR_ORGAN (16)
+#define GM_PERCUSSIVE_ORGAN (17)
+#define GM_ROCK_ORGAN (18)
+#define GM_CHURCH_ORGAN (19)
+#define GM_REED_ORGAN (20)
+#define GM_ACCORDION (21)
+#define GM_HARMONICA (22)
+#define GM_TANGO_ACCORDION (23)
+
+#define GM_GUITAR(X) (24+(X))
+#define GM_ACOUSTIC_GUITAR_NYLON (24)
+#define GM_ACOUSTIC_GUITAR_STEEL (25)
+#define GM_ELECTRIC_GUITAR_JAZZ (26)
+#define GM_ELECTRIC_GUITAR_CLEAN (27)
+#define GM_ELECTRIC_GUITAR_MUTED (28)
+#define GM_OVERDRIVEN_GUITAR (29)
+#define GM_DISTORTION_GUITAR (30)
+#define GM_GUITAR_HARMONICS (31)
+
+#define GM_BASS(X) (32+(X))
+#define GM_ACOUSTIC_BASS (32)
+#define GM_ELECTRIC_BASS_FINGER (33)
+#define GM_ELECTRIC_BASS_PICK (34)
+#define GM_FRETLESS_BASS (35)
+#define GM_SLAP_BASS_1 (36)
+#define GM_SLAP_BASS_2 (37)
+#define GM_SYNTH_BASS_1 (38)
+#define GM_SYNTH_BASS_2 (39)
+
+#define GM_STRINGS(X) (40+(X))
+#define GM_VIOLIN (40)
+#define GM_VIOLA (41)
+#define GM_CELLO (42)
+#define GM_CONTRABASS (43)
+#define GM_TREMOLO_STRINGS (44)
+#define GM_PIZZACATO_STRINGS (45)
+#define GM_ORCHESTRAL_HARP (46)
+#define GM_TIMPANI (47)
+
+#define GM_ENSEMBLE(X) (48+(X))
+#define GM_STRING_ENSEMBLE_1 (48)
+#define GM_STRING_ENSEMBLE_2 (49)
+#define GM_SYNTHSTRINGS_1 (50)
+#define GM_SYNTHSTRINGS_2 (51)
+#define GM_CHOIR_AAHS (52)
+#define GM_VOICE_OOHS (53)
+#define GM_SYNTH_VOICE (54)
+#define GM_ORCHESTRA_HIT (55)
+
+#define GM_BRASS(X) (56+(X))
+#define GM_TRUMPET (56)
+#define GM_TROMBONE (57)
+#define GM_TUBA (58)
+#define GM_MUTED_TRUMPED (59)
+#define GM_FRENCH_HORN (60)
+#define GM_BRASS_SECTION (61)
+#define GM_SYNTHBRASS_1 (62)
+#define GM_SYNTHBRASS_2 (63)
+
+#define GM_REED(X) (64+(X))
+#define GM_SOPRANO_SAX (64)
+#define GM_ALTO_SAX (65)
+#define GM_TENOR_SAX (66)
+#define GM_BARITONE_SAX (67)
+#define GM_OBOE (68)
+#define GM_ENGLISH_HORN (69)
+#define GM_BASSOON (70)
+#define GM_CLARINET (71)
+
+#define GM_PIPE(X) (72+(X))
+#define GM_PICCOLO (72)
+#define GM_FLUTE (73)
+#define GM_RECORDER (74)
+#define GM_PAN_FLUTE (75)
+#define GM_BLOWN_BOTTLE (76)
+#define GM_SHAKUHACHI (77)
+#define GM_WHISTLE (78)
+#define GM_OCARINA (79)
+
+#define GM_LEAD(X) (80+(X))
+#define GM_LEAD_SQUARE (80)
+#define GM_LEAD_SAWTOOTH (81)
+#define GM_LEAD_CALLIOPE (82)
+#define GM_LEAD_CHIFF (83)
+#define GM_LEAD_CHARANG (84)
+#define GM_LEAD_VOICE (85)
+#define GM_LEAD_FIFTHS (86)
+#define GM_LEAD_BASS (87)
+
+#define GM_PAD(X) (88+(X))
+#define GM_PAD_NEW_AGE (88)
+#define GM_PAD_WARM (89)
+#define GM_PAD_POLYSYNTH (90)
+#define GM_PAD_CHOIR (91)
+#define GM_PAD_BOWED (92)
+#define GM_PAD_METALLIC (93)
+#define GM_PAD_HALO (94)
+#define GM_PAD_SWEEP (95)
+
+#define GM_FX(X) (96+(X))
+#define GM_FX_TRAIN (96)
+#define GM_FX_SOUNDTRACK (97)
+#define GM_FX_CRYSTAL (98)
+#define GM_FX_ATMOSPHERE (99)
+#define GM_FX_BRIGHTNESS (100)
+#define GM_FX_GOBLINS (101)
+#define GM_FX_ECHOES (102)
+#define GM_FX_SCI_FI (103)
+
+#define GM_ETHNIC(X) (104+(X))
+#define GM_SITAR (104)
+#define GM_BANJO (105)
+#define GM_SHAMISEN (106)
+#define GM_KOTO (107)
+#define GM_KALIMBA (108)
+#define GM_BAGPIPE (109)
+#define GM_FIDDLE (110)
+#define GM_SHANAI (111)
+
+#define GM_PERCUSSION(X) (112+(X))
+#define GM_TINKLE_BELL (112)
+#define GM_AGOGO (113)
+#define GM_STEEL_DRUMS (114)
+#define GM_WOODBLOCKS (115)
+#define GM_TAIKO_DRUM (116)
+#define GM_MELODIC_DRUM (117)
+#define GM_SYNTH_DRUM (118)
+#define GM_REVERSE_CYMBAL (119)
+
+#define GM_SOUNDEFFECT(X) (120+(X))
+#define GM_GUITAR_FRET_NOISE (120)
+#define GM_BREATH_NOISE (121)
+#define GM_SEASHORE (122)
+#define GM_BIRD_TWEET (123)
+#define GM_TELEPHONE_RING (124)
+#define GM_HELICOPTER (125)
+#define GM_APPLAUSE (126)
+#define GM_GUNSHOT (127)
+
+//
+// Percussion instruments on channel 10
+//
+
+#define GM_ACOUSTIC_BASS_DRUM (35)
+#define GM_BASS_DRUM_1 (36)
+#define GM_SIDE_STICK (37)
+#define GM_ACOUSTIC_SNARE (38)
+#define GM_HAND_CLAP (39)
+#define GM_ELECTRIC_SNARE (40)
+#define GM_LOW_FLOOR_TOM (41)
+#define GM_CLOSED_HI_HAT (42)
+#define GM_HIGH_FLOOR_TOM (43)
+#define GM_PEDAL_HI_HAT (44)
+#define GM_LOW_TOM (45)
+#define GM_OPEN_HI_HAT (46)
+#define GM_LOW_MID_TOM (47)
+#define GM_HIGH_MID_TOM (48)
+#define GM_CRASH_CYMBAL_1 (49)
+#define GM_HIGH_TOM (50)
+#define GM_RIDE_CYMBAL_1 (51)
+#define GM_CHINESE_CYMBAL (52)
+#define GM_RIDE_BELL (53)
+#define GM_TAMBOURINE (54)
+#define GM_SPLASH_CYMBAL (55)
+#define GM_COWBELL (56)
+#define GM_CRASH_CYMBAL_2 (57)
+#define GM_VIBRASLAP (58)
+#define GM_RIDE_CYMBAL_2 (59)
+#define GM_HI_BONGO (60)
+#define GM_LOW_BONGO (61)
+#define GM_MUTE_HI_CONGA (62)
+#define GM_OPEN_HI_CONGA (63)
+#define GM_LOW_CONGA (64)
+#define GM_HIGH_TIMBALE (65)
+#define GM_LOW_TIMBALE (66)
+#define GM_HIGH_AGOGO (67)
+#define GM_LOW_AGOGO (68)
+#define GM_CABASA (69)
+#define GM_MARACAS (70)
+#define GM_SHORT_WHISTLE (71)
+#define GM_LONG_WHISTLE (72)
+#define GM_SHORT_GUIRO (73)
+#define GM_LONG_GUIRO (74)
+#define GM_CLAVES (75)
+#define GM_HI_WOOD_BLOCK (76)
+#define GM_LOW_WOOD_BLOCK (77)
+#define GM_MUTE_CUICA (78)
+#define GM_OPEN_CUICA (79)
+#define GM_MUTE_TRIANGLE (80)
+#define GM_OPEN_TRIANGLE (81)
+
+
+#endif /* _GMINSTRUMENTS_H_INCLUDED */
+
+
+
+// md5sum: 6299d04892a6899533b9164aa9e1a874 - gminstruments.h =css= 20030102
diff --git a/src/midiio/include/midichannels.h b/src/midiio/include/midichannels.h
new file mode 100644
index 0000000..4526813
--- /dev/null
+++ b/src/midiio/include/midichannels.h
@@ -0,0 +1,42 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Wed Feb 11 22:49:59 GMT-0800 1998
+// Filename: ...sig/code/control/misc/midichannels.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/midichannels.h
+// Syntax: C++
+//
+// Description: Offset by 1 MIDI channel names.
+//
+
+#ifndef _MIDICHANNELS_H_INCLUDED
+#define _MIDICHANNELS_H_INCLUDED
+
+/* temporarily changed :
+
+// channel defines: offset from 0
+#define CH_1 (0x00)
+#define CH_2 (0x01)
+#define CH_3 (0x02)
+#define CH_4 (0x03)
+#define CH_5 (0x04)
+#define CH_6 (0x05)
+#define CH_7 (0x06)
+#define CH_8 (0x07)
+#define CH_9 (0x08)
+#define CH_10 (0x09)
+#define CH_11 (0x0a)
+#define CH_12 (0x0b)
+#define CH_13 (0x0c)
+#define CH_14 (0x0d)
+#define CH_15 (0x0e)
+#define CH_16 (0x0f)
+
+*/
+
+#endif /* _MIDICHANNELS_H_INCLUDED */
+
+
+
+
+// md5sum: 5267399f7ff90a6ea3ad2dc132afae3e - midichannels.h =css= 20030102
diff --git a/src/midiio/include/mididefines.h b/src/midiio/include/mididefines.h
new file mode 100644
index 0000000..4161c2f
--- /dev/null
+++ b/src/midiio/include/mididefines.h
@@ -0,0 +1,34 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Wed Feb 11 22:49:59 GMT-0800 1998
+// Filename: ...sig/code/control/misc/mididefines.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/mididefines.h
+// Syntax: C++
+//
+// Description: Collection of all of the MIDI convienience defines.
+//
+
+#ifndef _MIDIDEFINES_H_INCLUDED
+#define _MIDIDEFINES_H_INCLUDED
+
+
+// include channel defines
+#include "midichannels.h"
+
+
+// include note name defines
+#include "notenames.h"
+
+
+// include General MIDI instrument names
+#include "gminstruments.h"
+
+
+
+#endif /* _MIDIDEFINES_H_INCLUDED */
+
+
+
+
+// md5sum: 0f081c8e0b386a11e448b6088bfcd489 - mididefines.h =css= 20030102
diff --git a/src/midiio/include/midiiolib.h b/src/midiio/include/midiiolib.h
new file mode 100644
index 0000000..17d0430
--- /dev/null
+++ b/src/midiio/include/midiiolib.h
@@ -0,0 +1,57 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sat Nov 2 20:20:24 PST 2002
+// Last Modified: Thu Jan 2 18:51:20 PST 2003 (changed name from midio.h)
+// Filename: ...sig/code/misc/midiiolib.h
+// Web Address: http://sig.sapp.org/include/sig/midiiolib.h
+// Syntax: C++
+//
+// Description: Includes all of the header files for using the midiio
+// Library.
+//
+
+#ifndef _MIDIIOLIB_H_INCLUDED
+#define _MIDIIOLIB_H_INCLUDED
+
+#include "Array.h"
+#include "CircularBuffer.h"
+#include "Collection.h"
+#include "FileIO.h"
+#include "gminstruments.h"
+#include "midichannels.h"
+#include "mididefines.h"
+#include "MidiFile.h"
+#include "MidiFileWrite.h"
+#include "MidiInPort_alsa05.h"
+#include "MidiInPort_alsa.h"
+#include "MidiInPort.h"
+#include "MidiInPort_linux.h"
+#include "MidiInPort_oss.h"
+#include "MidiInPort_unsupported.h"
+#include "MidiInPort_visual.h"
+#include "MidiInput.h"
+#include "MidiIO.h"
+#include "MidiMessage.h"
+#include "MidiOutPort_alsa.h"
+#include "MidiOutPort.h"
+#include "MidiOutPort_linux.h"
+#include "MidiOutPort_oss.h"
+#include "MidiOutPort_unsupported.h"
+#include "MidiOutPort_visual.h"
+#include "MidiOutput.h"
+#include "MidiPort.h"
+#include "notenames.h"
+#include "Options.h"
+#include "Options_private.h"
+#include "Sequencer_alsa.h"
+#include "Sequencer_oss.h"
+#include "sigConfiguration.h"
+#include "SigTimer.h"
+#include "Voice.h"
+
+
+#endif /* _MIDIIO_H_INCLUDED */
+
+
+
+// md5sum: b389c20c620865344d827a88a0fb048d - midiiolib.h =css= 20030102
diff --git a/src/midiio/include/notenames.h b/src/midiio/include/notenames.h
new file mode 100644
index 0000000..ce9d505
--- /dev/null
+++ b/src/midiio/include/notenames.h
@@ -0,0 +1,219 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> (from 18Dec1997)
+// Creation Date: 26 December 1997
+// Last Modified: 26 December 1997
+// Filename: ...sig/code/control/misc/notenames.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/notenames.h
+// Syntax: C
+//
+// Description: Defines for pitch names of midi key numbers
+//
+
+#ifndef _NOTENAMES_H_INCLUDED
+#define _NOTENAMES_H_INCLUDED
+
+#define C00 (0)
+#define Cs00 (1)
+#define Db00 (1)
+#define D00 (2)
+#define Ds00 (3)
+#define Eb00 (3)
+#define E00 (4)
+#define F00 (5)
+#define Fs00 (6)
+#define Gb00 (6)
+#define G00 (7)
+#define Gs00 (8)
+#define Ab00 (8)
+#define A00 (9)
+#define As00 (10)
+#define Bb00 (10)
+#define B00 (11)
+
+#define C0 (12)
+#define Cs0 (13)
+#define Db0 (13)
+#define D0 (14)
+#define Ds0 (15)
+#define Eb0 (15)
+#define E0 (16)
+#define F0 (17)
+#define Fs0 (18)
+#define Gb0 (18)
+#define G0 (19)
+#define Gs0 (20)
+#define Ab0 (20)
+#define A0 (21)
+#define As0 (22)
+#define Bb0 (22)
+
+/*
+ * Note that the following symbol B0 is used in
+ * unix in the file /usr/include/termios.h also as
+ * a symbol, so It is disabled for now in this file.
+ * termios.h is need in Unix for the KeyboardInput.h file
+ */
+
+// #define B0 (23)
+
+#define C1 (24)
+#define Cs1 (25)
+#define Db1 (25)
+#define D1 (26)
+#define Ds1 (27)
+#define Eb1 (27)
+#define E1 (28)
+#define F1 (29)
+#define Fs1 (30)
+#define Gb1 (30)
+#define G1 (31)
+#define Gs1 (32)
+#define Ab1 (32)
+#define A1 (33)
+#define As1 (34)
+#define Bb1 (34)
+#define B1 (35)
+
+#define C2 (36)
+#define Cs2 (37)
+#define Db2 (37)
+#define D2 (38)
+#define Ds2 (39)
+#define Eb2 (39)
+#define E2 (40)
+#define F2 (41)
+#define Fs2 (42)
+#define Gb2 (42)
+#define G2 (43)
+#define Gs2 (44)
+#define Ab2 (44)
+#define A2 (45)
+#define As2 (46)
+#define Bb2 (46)
+#define B2 (47)
+
+#define C3 (48)
+#define Cs3 (49)
+#define Db3 (49)
+#define D3 (50)
+#define Ds3 (51)
+#define Eb3 (51)
+#define E3 (52)
+#define F3 (53)
+#define Fs3 (54)
+#define Gb3 (54)
+#define G3 (55)
+#define Gs3 (56)
+#define Ab3 (56)
+#define A3 (57)
+#define As3 (58)
+#define Bb3 (58)
+#define B3 (59)
+
+#define C4 (60)
+#define Cs4 (61)
+#define Db4 (61)
+#define D4 (62)
+#define Ds4 (63)
+#define Eb4 (63)
+#define E4 (64)
+#define F4 (65)
+#define Fs4 (66)
+#define Gb4 (66)
+#define G4 (67)
+#define Gs4 (68)
+#define Ab4 (68)
+#define A4 (69)
+#define As4 (70)
+#define Bb4 (70)
+#define B4 (71)
+
+#define C5 (72)
+#define Cs5 (73)
+#define Db5 (73)
+#define D5 (74)
+#define Ds5 (75)
+#define Eb5 (75)
+#define E5 (76)
+#define F5 (77)
+#define Fs5 (78)
+#define Gb5 (78)
+#define G5 (79)
+#define Gs5 (80)
+#define Ab5 (81)
+#define A5 (81)
+#define As5 (82)
+#define Bb5 (82)
+#define B5 (83)
+
+#define C6 (84)
+#define Cs6 (85)
+#define Db6 (85)
+#define D6 (86)
+#define Ds6 (87)
+#define Eb6 (87)
+#define E6 (88)
+#define F6 (89)
+#define Fs6 (90)
+#define Gb6 (90)
+#define G6 (91)
+#define Gs6 (92)
+#define Ab6 (92)
+#define A6 (93)
+#define As6 (94)
+#define Bb6 (94)
+#define B6 (95)
+
+#define C7 (96)
+#define Cs7 (97)
+#define Db7 (97)
+#define D7 (98)
+#define Ds7 (99)
+#define Eb7 (99)
+#define E7 (100)
+#define F7 (101)
+#define Fs7 (102)
+#define Gb7 (102)
+#define G7 (103)
+#define Gs7 (104)
+#define Ab7 (104)
+#define A7 (105)
+#define As7 (106)
+#define Bb7 (106)
+#define B7 (107)
+
+#define C8 (108)
+#define Cs8 (109)
+#define Db8 (109)
+#define D8 (110)
+#define Ds8 (111)
+#define Eb8 (111)
+#define E8 (112)
+#define F8 (113)
+#define Fs8 (114)
+#define Gb8 (114)
+#define G8 (115)
+#define Gs8 (116)
+#define Ab8 (116)
+#define A8 (117)
+#define As8 (118)
+#define Bb8 (118)
+#define B8 (119)
+
+#define C9 (120)
+#define Cs9 (121)
+#define Db9 (121)
+#define D9 (122)
+#define Ds9 (123)
+#define Eb9 (123)
+#define E9 (124)
+#define F9 (125)
+#define Fs9 (126)
+#define Gb9 (126)
+#define G9 (127)
+
+
+#endif /* _NOTENAMES_H_INCLUDED */
+
+
+// md5sum: c0f727163d32e04212a0ce5c8b6c4a6f - notenames.h =css= 20030102
diff --git a/src/midiio/include/sigConfiguration.h b/src/midiio/include/sigConfiguration.h
new file mode 100644
index 0000000..b1e5f17
--- /dev/null
+++ b/src/midiio/include/sigConfiguration.h
@@ -0,0 +1,100 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Mon Dec 1 18:16:57 GMT-0800 1997
+// Last Modified: Mon Dec 1 18:16:57 GMT-0800 1997
+// Filename: ...sig/maint/code/misc/sigConfiguration.h
+// Web Address: http://sig.sapp.org/include/sig/sigConfiguration.h
+// Syntax: C
+//
+// Description: This file defines flags for different code setups:
+// You specify the OS in a compiler flag and this file takes care
+// of the rest of the defines for that OS. This file should
+// automatically be included in any file which uses any of the
+// define flags below.
+//
+// OS setup defines to use in compiling files:
+//
+// -DLINUX: Linux running on intel computers
+// -DNEXTI: NeXT OS on Intel Hardware
+// -DNEXTM: NeXT OS on Motorola Hardware
+// -DSUN: Sun SPARCstations
+// -DVISUAL: Windows 95/NT using Microsoft Visual C++ 5.0
+// -DHPUX: Hewlett-Packard Unix Workstations.
+// -DIRIX: SGI computers with IRIX OS.
+//
+//
+// Various options that can be defined for each OS. These
+// defines may be mixed and matched in different OSes:
+//
+// -DOTHEREND: If the computer is little-endian, then this
+// define switches the byte ordering behavior for writing/reading
+// soundfiles. Intel computers need this define, most others
+// will not.need this define.
+//
+// -DSHORTRAND: Indicates that the rand() function generates
+// numbers between 0 and 0x7fff. The default without this
+// option is a range between 0 and 0x7fffffff.
+//
+// -DINTEL: Indicates that the computer hardware uses an
+// intel x86 CPU. Not used for anything right now except to
+// define the endian flag (OTHEREND).
+//
+// -DMOTOROLA: Indicates that the computer hardware uses a
+// Motorola 68k CPU. Not used for anything right now.
+//
+//
+
+#ifndef _SIGCONFIGURATION_H_INCLUDED
+#define _SIGCONFIGURATION_H_INCLUDED
+
+
+#ifdef LINUX
+ #define INTEL
+#endif
+
+
+#ifdef NEXTI
+ #define INTEL
+#endif
+
+
+#ifdef NEXT
+ #define MOTOROLA
+#endif
+
+
+#ifdef VISUAL
+ #define INTEL
+#endif
+
+
+#ifdef SUN
+ #define SHORTRAND
+#endif
+
+
+#ifdef HPUX
+ #define SHORTRAND
+#endif
+
+
+#ifdef IRIX
+ #define SHORTRAND
+#endif
+
+
+// These defines must come after the previous defines:
+
+
+#ifdef INTEL
+ #define OTHEREND
+#endif
+
+
+
+#endif /* _SIGCONFIGURATION_H_INCLUDED */
+
+
+
+// md5sum: 32f74a7c264b158b83ff38db1ea885f8 - sigConfiguration.h =css= 20030102
diff --git a/src/midiio/src/FileIO.cpp b/src/midiio/src/FileIO.cpp
new file mode 100644
index 0000000..93ef153
--- /dev/null
+++ b/src/midiio/src/FileIO.cpp
@@ -0,0 +1,761 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri May 9 22:30:32 PDT 1997
+// Last Modified: Sun Dec 14 03:29:39 GMT-0800 1997
+// Filename: ...sig/maint/code/sigBase/FileIO.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/FileIO.cpp
+// Documentation: http://sig.sapp.org/doc/classes/FileIO
+// Syntax: C++
+//
+// Description: Derived from the fstream class, this class has
+// functions which allow writing binary files in
+// both little and big endian formats. Useful for
+// writing files such as soundfiles and MIDI files
+// which require numbers to be stored in a particular
+// endian format.
+//
+
+#include "FileIO.h"
+#include "sigConfiguration.h"
+
+//////////////////////////////
+//
+// FileIO::FileIO --
+//
+
+FileIO::FileIO(void) {
+ // do nothing
+};
+
+FileIO::FileIO(const char* filename, std::ios::openmode state) :
+#ifdef VISUAL /* for stupid LF-CR prevention in DOS */
+ std::fstream(filename, state | ios::binary) {
+#else
+ std::fstream(filename, state) {
+#endif
+ // do nothing
+};
+
+
+
+//////////////////////////////
+//
+// FileIO::~FileIO --
+//
+
+FileIO::~FileIO() {
+ // do nothing
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::readBigEndian --
+// Read numbers from a file as big endian
+//
+
+void FileIO::readBigEndian(char& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(uchar& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(short& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(ushort& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(long& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(ulong& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(int& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(uint& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(float& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(double& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::readLittleEndian --
+// Read numbers from a file as little endian
+//
+
+void FileIO::readLittleEndian(char& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(uchar& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(short& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(ushort& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(long& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(ulong& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(int& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(uint& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(float& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(double& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::readMachineEndian --
+// Read numbers from a file in the same endian as the computer.
+//
+
+void FileIO::readMachineEndian(char& aNumber) {
+ this->read(&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(uchar& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(short& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(ushort& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(long& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(ulong& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(int& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(uint& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(float& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(double& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::readNotMachineEndian --
+// Read numbers from a file with different endian from the computer.
+//
+
+void FileIO::readNotMachineEndian(char& aNumber) {
+ this->read(&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(uchar& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(short& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(ushort& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(long& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(ulong& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(int& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(uint& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(float& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(double& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::writeBigEndian --
+//
+
+void FileIO::writeBigEndian(char aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(uchar aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(short aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(ushort aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(long aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(ulong aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(int aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(uint aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(float aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(double aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::writeLittleEndian --
+//
+
+void FileIO::writeLittleEndian(char aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(uchar aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(short aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(ushort aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(long aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(ulong aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(int aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(uint aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(float aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(double aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::writeMachineEndian --
+//
+
+void FileIO::writeMachineEndian(char aNumber) {
+ this->write(&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(uchar aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(short aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(ushort aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(long aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(ulong aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(int aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(uint aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(float aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(double aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::writeNotMachineEndian --
+//
+
+void FileIO::writeNotMachineEndian(char aNumber) {
+ // aNumber = flipBytes(aNumber);
+ this->write(&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(uchar aNumber) {
+ // aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(short aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(ushort aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(long aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(ulong aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(int aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(uint aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(float aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(double aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+
+//////////////////////////////
+//
+// flipBytes -- flip the bytes in a number
+//
+
+char FileIO::flipBytes(char aNumber) {
+ return aNumber;
+}
+
+
+uchar FileIO::flipBytes(uchar aNumber) {
+ return aNumber;
+}
+
+
+short FileIO::flipBytes(short aNumber) {
+ static uchar output[2];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[1];
+ output[1] = input[0];
+
+ return *((short*)(&output));
+}
+
+
+ushort FileIO::flipBytes(ushort aNumber) {
+ static uchar output[2];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[1];
+ output[1] = input[0];
+
+ return *((ushort*)(&output));
+}
+
+
+long FileIO::flipBytes(long aNumber) {
+ static uchar output[4];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[3];
+ output[1] = input[2];
+ output[2] = input[1];
+ output[3] = input[0];
+
+ return *((long*)(&output));
+}
+
+
+ulong FileIO::flipBytes(ulong aNumber) {
+ static uchar output[4];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[3];
+ output[1] = input[2];
+ output[2] = input[1];
+ output[3] = input[0];
+
+ return *((ulong*)(&output));
+}
+
+
+int FileIO::flipBytes(int aNumber) {
+ static uchar output[sizeof(uint)];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ for(uint i=0; i<sizeof(int); i++) {
+ output[i] = input[sizeof(int)-1-i];
+ }
+
+ return *((int*)(&output));
+}
+
+
+uint FileIO::flipBytes(uint aNumber) {
+ static uchar output[sizeof(uint)];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ for(uint i=0; i<sizeof(uint); i++) {
+ output[i] = input[sizeof(uint)-1-i];
+ }
+
+ return *((uint*)(&output));
+}
+
+
+
+float FileIO::flipBytes(float aNumber) {
+ static uchar output[4];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[3];
+ output[1] = input[2];
+ output[2] = input[1];
+ output[3] = input[0];
+
+ return *((float*)(&output));
+}
+
+
+double FileIO::flipBytes(double aNumber) {
+ static uchar output[8];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[7];
+ output[1] = input[6];
+ output[2] = input[5];
+ output[3] = input[4];
+ output[4] = input[3];
+ output[5] = input[2];
+ output[6] = input[1];
+ output[7] = input[0];
+
+ return *((double*)(&output));
+}
+
+
+
+/* This is what I want to use
+template<class type>
+type FileIO::flipBytes(type aThing) {
+ uchar* input = (uchar*)(&aNumber);
+ uchar output[sizeof(aThing)];
+
+ for(int i=0; i<sizeof(aThing); i++) {
+ output[i] = input[sizeof(aThing) - 1 - i];
+ }
+
+ return *((type*)(&output));
+}
+*/
+
+
+
+// md5sum: a82bcb961043a48d2cae34d5eaac0101 - FileIO.cpp =css= 20030102
diff --git a/src/midiio/src/MidiFile.cpp b/src/midiio/src/MidiFile.cpp
new file mode 100644
index 0000000..e3307ca
--- /dev/null
+++ b/src/midiio/src/MidiFile.cpp
@@ -0,0 +1,1200 @@
+//
+// Copyright 1999 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Nov 26 14:12:01 PST 1999
+// Last Modified: Fri Dec 2 13:26:29 PST 1999
+// Last Modified: Wed Dec 13 10:33:30 PST 2000 (modified sorting routine)
+// Last Modified: Tue Jan 22 23:23:37 PST 2002 (allowed reading of meta events)
+// Filename: ...sig/src/sigInfo/MidiFile.cpp
+// Web Address: http://sig.sapp.org/src/sigInfo/MidiFile.cpp
+// Syntax: C++
+//
+// Description: A class which can read/write Standard MIDI files.
+// MIDI data is stored by track in an array. This
+// class is used for example in the MidiPerform class.
+//
+
+#include "MidiFile.h"
+#include <iomanip>
+
+//////////////////////////////
+//
+// _MFEvent::_MFEvent --
+//
+
+_MFEvent::_MFEvent(void) {
+ time = 0;
+ track = 0;
+ data.allowGrowth();
+ data.setSize(0);
+}
+
+_MFEvent::_MFEvent(int command) {
+ time = 0;
+ track = 0;
+ data.allowGrowth();
+ data.setSize(1);
+ data[0] = (uchar)command;
+}
+
+_MFEvent::_MFEvent(int command, int param1) {
+ time = 0;
+ track = 0;
+ data.allowGrowth();
+ data.setSize(2);
+ data[0] = (uchar)command;
+ data[1] = (uchar)param1;
+}
+
+_MFEvent::_MFEvent(int command, int param1, int param2) {
+ time = 0;
+ track = 0;
+ data.allowGrowth();
+ data.setSize(3);
+ data[0] = (uchar)command;
+ data[1] = (uchar)param1;
+ data[2] = (uchar)param2;
+}
+
+_MFEvent::_MFEvent(int aTrack, int command, int param1, int param2) {
+ time = 0;
+ track = aTrack;
+ data.allowGrowth();
+ data.setSize(3);
+ data[0] = (uchar)command;
+ data[1] = (uchar)param1;
+ data[2] = (uchar)param2;
+}
+
+_MFEvent::_MFEvent(int aTime, int aTrack, int command, int param1, int param2) {
+ time = aTime;
+ track = aTrack;
+ data.allowGrowth();
+ data.setSize(3);
+ data[0] = (uchar)command;
+ data[1] = (uchar)param1;
+ data[2] = (uchar)param2;
+}
+
+
+
+//////////////////////////////
+//
+// _MFEvent::~MFEvent
+//
+
+_MFEvent::~_MFEvent() {
+ time = -1;
+ track = -1;
+ data.setSize(0);
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::MidiFile --
+//
+
+MidiFile::MidiFile(void) {
+ ticksPerQuarterNote = 48; // time base of file
+ trackCount = 1; // # of tracks in file
+ theTrackState = TRACK_STATE_SPLIT; // joined or split
+ theTimeState = TIME_STATE_DELTA; // absolute or delta
+ events.setSize(1);
+ events[0] = new Collection<_MFEvent>;
+ events[0]->setSize(0);
+ events[0]->allowGrowth(1);
+ readFileName = new char[1];
+ readFileName[0] = '\0';
+}
+
+
+MidiFile::MidiFile(char* aFile) {
+ ticksPerQuarterNote = 48; // time base of file
+ trackCount = 1; // # of tracks in file
+ theTrackState = TRACK_STATE_SPLIT; // joined or split
+ theTimeState = TIME_STATE_DELTA; // absolute or delta
+ events.setSize(1);
+ events[0] = new Collection<_MFEvent>;
+ events[0]->setSize(0);
+ events[0]->allowGrowth(1);
+ readFileName = new char[1];
+ readFileName[0] = '\0';
+ read(aFile);
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::~MidiFile --
+//
+
+MidiFile::~MidiFile() {
+ if (readFileName != NULL) {
+ delete [] readFileName;
+ readFileName = NULL;
+ }
+
+ erase();
+
+ if (events[0] != NULL) {
+ delete events[0];
+ events[0] = NULL;
+ }
+
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::absoluteTime -- convert the time data to
+// absolute time, which means that the time field
+// in the _MFEvent struct represents the exact tick
+// time to play the event rather than the time since
+// the last event to wait untill playing the current
+// event.
+//
+
+void MidiFile::absoluteTime(void) {
+ if (getTimeState() == TIME_STATE_ABSOLUTE) {
+ return;
+ }
+ int i, j;
+ int length = getNumTracks();
+ int* timedata = new int[length];
+ for (i=0; i<length; i++) {
+ timedata[i] = 0;
+ if (events[i]->getSize() > 0) {
+ timedata[i] = (*events[i])[0].time;
+ } else {
+ continue;
+ }
+ for (j=1; j<events[i]->getSize(); j++) {
+ timedata[i] += (*events[i])[j].time;
+ (*events[i])[j].time = timedata[i];
+ }
+ }
+ theTimeState = TIME_STATE_ABSOLUTE;
+ delete [] timedata;
+}
+
+//////////////////////////////
+//
+// MidiFile::addEvent --
+//
+
+int MidiFile::addEvent(int aTrack, int aTime, Array<uchar>& midiData) {
+ _MFEvent anEvent;
+ anEvent.time = aTime;
+ anEvent.track = aTrack;
+ anEvent.data = midiData;
+
+ events[aTrack]->append(anEvent);
+ return events[aTrack]->getSize() - 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::addTrack -- adds a blank track at end of the
+// track list. Returns the track number of the added
+// track.
+//
+
+int MidiFile::addTrack(void) {
+ int length = getNumTracks();
+ events.setSize(length+1);
+ events[length] = new Collection<_MFEvent>;
+ events[length]->setSize(10000);
+ events[length]->setSize(0);
+ events[length]->allowGrowth(1);
+ return length;
+}
+
+int MidiFile::addTrack(int count) {
+ int length = getNumTracks();
+ events.setSize(length+count);
+ int i;
+ for (i=0; i<count; i++) {
+ events[length + i] = new Collection<_MFEvent>;
+ events[length + i]->setSize(10000);
+ events[length + i]->setSize(0);
+ events[length + i]->allowGrowth(1);
+ }
+ return length + count - 1;
+}
+
+
+//////////////////////////////
+//
+// MidiFile::allocateEvents --
+//
+
+void MidiFile::allocateEvents(int track, int aSize) {
+ int oldsize = events[track]->getSize();
+ if (oldsize < aSize) {
+ events[track]->setSize(aSize);
+ events[track]->setSize(oldsize);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::deleteTrack -- remove a track from the MidiFile.
+// Tracks are numbered starting at track 0.
+//
+
+void MidiFile::deleteTrack(int aTrack) {
+ int length = getNumTracks();
+ if (aTrack < 0 || aTrack >= length) {
+ return;
+ }
+ if (length == 1) {
+ return;
+ }
+ delete events[aTrack];
+ for (int i=aTrack; i<length-1; i++) {
+ events[i] = events[i+1];
+ }
+
+ events[length] = NULL;
+ events.setSize(length-1);
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::deltaTime -- convert the time data to
+// delta time, which means that the time field
+// in the _MFEvent struct represents the time
+// since the last event was played. When a MIDI file
+// is read from a file, this is the default setting.
+//
+
+void MidiFile::deltaTime(void) {
+ if (getTimeState() == TIME_STATE_DELTA) {
+ return;
+ }
+ int i, j;
+ int temp;
+ int length = getNumTracks();
+ int *timedata = new int[length];
+ for (i=0; i<length; i++) {
+ timedata[i] = 0;
+ if (events[i]->getSize() > 0) {
+ timedata[i] = (*events[i])[0].time;
+ } else {
+ continue;
+ }
+ for (j=1; j<events[i]->getSize(); j++) {
+ temp = (*events[i])[j].time;
+ (*events[i])[j].time = temp - timedata[i];
+ timedata[i] = temp;
+ }
+ }
+ theTimeState = TIME_STATE_DELTA;
+ delete [] timedata;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::erase -- make the MIDI file empty with one
+// track with no data in it.
+//
+
+void MidiFile::erase(void) {
+ int length = getNumTracks();
+ for (int i=0; i<length; i++) {
+ delete events[i];
+ events[i] = NULL;
+ }
+ events.setSize(1);
+ events[0] = new Collection<_MFEvent>;
+ events[0]->setSize(0);
+ events[0]->allowGrowth(1);
+}
+
+
+void MidiFile::clear(void) {
+ MidiFile::erase();
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::getEvent -- return the event at the given index in the
+// specified track.
+//
+
+_MFEvent& MidiFile::getEvent(int aTrack, int anIndex) {
+ return (*events[aTrack])[anIndex];
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::getTicksPerQuarterNote -- returns the number of
+// time units that are supposed to occur during a quarternote.
+//
+
+int MidiFile::getTicksPerQuarterNote(void) {
+ return ticksPerQuarterNote;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::getTrackCount -- return the number of tracks in
+// the Midi File.
+//
+
+int MidiFile::getTrackCount(void) {
+ return events.getSize();
+}
+
+int MidiFile::getNumTracks(void) {
+ return events.getSize();
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::getNumEvents -- returns the number of events
+// in a given track.
+//
+
+int MidiFile::getNumEvents(int aTrack) {
+ return events[aTrack]->getSize();
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::joinTracks -- merge the data from all tracks,
+// but keeping the identity of the tracks unique so that
+// the function splitTracks can be called to split the
+// tracks into separate units again. The style of the
+// MidiFile when read from a file is with tracks split.
+//
+
+void MidiFile::joinTracks(void) {
+ if (getTrackState() == TRACK_STATE_JOINED) {
+ return;
+ }
+ if (getNumTracks() == 1) {
+ return;
+ }
+
+ Collection <_MFEvent>* joinedTrack;
+ joinedTrack = new Collection<_MFEvent>;
+ joinedTrack->setSize(200000);
+ joinedTrack->setSize(0);
+ int oldTimeState = getTimeState();
+ if (oldTimeState == TIME_STATE_DELTA) {
+ absoluteTime();
+ }
+ int i, j;
+ int length = getNumTracks();
+ for (i=0; i<length; i++) {
+ for (j=0; j<events[i]->getSize(); j++) {
+ joinedTrack->append((*events[i])[j]);
+ }
+ }
+
+ erase();
+
+ delete events[0];
+ events[0] = joinedTrack;
+ sortTracks();
+ if (oldTimeState == TIME_STATE_DELTA) {
+ deltaTime();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::mergeTracks -- combine the data from two
+// tracks into one. Placing the data in the first
+// track location listed, and Moving the other tracks
+// in the file around to fill in the spot where Track2
+// used to be. The results of this function call cannot
+// be reversed.
+//
+
+void MidiFile::mergeTracks(int aTrack1, int aTrack2) {
+ Collection <_MFEvent>* mergedTrack;
+ mergedTrack = new Collection<_MFEvent>;
+ mergedTrack->setSize(0);
+ int oldTimeState = getTimeState();
+ if (oldTimeState == TIME_STATE_DELTA) {
+ absoluteTime();
+ }
+ int i, j;
+ int length = getNumTracks();
+ for (i=0; i<events[aTrack1]->getSize(); i++) {
+ mergedTrack->append((*events[aTrack1])[i]);
+ }
+ for (j=0; j<events[aTrack2]->getSize(); i++) {
+ (*events[aTrack2])[i].track = aTrack1;
+ mergedTrack->append((*events[aTrack2])[i]);
+ }
+
+ sortTrack(*mergedTrack);
+
+ delete events[aTrack1];
+
+ events[aTrack1] = mergedTrack;
+
+ for (i=aTrack2; i<length-1; i++) {
+ events[i] = events[i+1];
+ }
+
+ events[length] = NULL;
+ events.setSize(length-1);
+
+ if (oldTimeState == TIME_STATE_DELTA) {
+ deltaTime();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::read -- read a MIDI file and store its contents.
+//
+
+int MidiFile::read(char* aFile) {
+
+ #ifdef VISUAL
+ FileIO inputfile(aFile, std::ios::in | std::ios::nocreate | std::ios::binary);
+ #else
+ // ios::nocreate does not exists anymore in GCC 3.x
+ FileIO inputfile(aFile, std::ios::in /*| std::ios::nocreate */);
+ #endif
+
+ if (!inputfile.is_open()) {
+ return 0;
+ }
+
+ // Read the MIDI header (4 bytes of ID, 4 byte data size, 6 bytes
+ // of data.
+
+ ulong longdata;
+ uchar chardata;
+ ushort shortdata;
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'M') {
+ std::cout << "File: " << aFile << " is not a MIDI file" << std::endl;
+ std::cout << "Chara data is" << chardata << std::endl;
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'T') {
+ std::cout << "File: " << aFile << " is not a MIDI file" << std::endl;
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'h') {
+ std::cout << "File: " << aFile << " is not a MIDI file" << std::endl;
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'd') {
+ std::cout << "File: " << aFile << " is not a MIDI file" << std::endl;
+ return 0;
+ }
+
+ // read header size
+ inputfile.readBigEndian(longdata);
+ if (longdata != 6) {
+ std::cout << "File: " << aFile
+ << " is not a MIDI 1.0 Standard MIDI file." << std::endl;
+ std::cout << "The header size is: " << longdata << std::endl;
+ return 0;
+ }
+
+ // read file type
+ int type;
+ inputfile.readBigEndian(shortdata);
+ switch (shortdata) {
+ case 0:
+ type = 0;
+ break;
+ case 1:
+ type = 1;
+ break;
+ default:
+ std::cout << "Error: cannot handle type " << shortdata
+ << " MIDI file" << std::endl;
+ return 0;
+ }
+
+ // read number of tracks
+ int tracks;
+ inputfile.readBigEndian(shortdata);
+ if (type == 0 && shortdata != 1) {
+ std::cout << "Error: Type 0 MIDI file can only contain one track" << std::endl;
+ return 0;
+ } else {
+ tracks = shortdata;
+ }
+ // std::cout << "Track count is: " << tracks << std::endl;
+ erase();
+ if (events[0] != NULL) {
+ delete events[0];
+ }
+ events.setSize(tracks);
+ for (int z=0; z<tracks; z++) {
+ events[z] = new Collection<_MFEvent>;
+ events[z]->setAllocSize(10000);
+ events[z]->setSize(0);
+ events[z]->allowGrowth(1);
+ }
+
+ // read ticks per quarter note
+ short signeddata;
+ inputfile.readBigEndian(signeddata);
+ if (signeddata <= 0) {
+ std::cout << "Error: cannot handle SMTP tick values for quarter notes"
+ " yet" << std::endl;
+ return 0;
+ }
+ ticksPerQuarterNote = signeddata;
+
+ //////////////////////////////////////////////////
+ //
+ // now read individual tracks:
+ //
+
+ uchar runningCommand = 0;
+ _MFEvent event;
+ int absticks;
+ int barline;
+
+ for (int i=0; i<tracks; i++) {
+ // std::cout << "\nReading Track: " << i + 1 << flush;
+ // read track header...
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'M') {
+ std::cout << "File: " << aFile << " has bad track info" << std::endl;
+ std::cout << "character 1 is: " << (int)chardata << std::endl;
+ inputfile.readBigEndian(chardata);
+ if (inputfile.eof()) {
+ std::cout << "End of file reached" << std::endl;
+ }
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'T') {
+ std::cout << "File: " << aFile << " has bad track info" << std::endl;
+ std::cout << "character 2 is: " << (int)chardata << std::endl;
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'r') {
+ std::cout << "File: " << aFile << " has bad track info" << std::endl;
+ std::cout << "character 3 is: " << (int)chardata << std::endl;
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'k') {
+ std::cout << "File: " << aFile << " has bad track info" << std::endl;
+ std::cout << "character 4 is: " << (int)chardata << std::endl;
+ return 0;
+ }
+
+ // Now read track chunk size and throw it away because it is
+ // not really necessary since the track MUST end with an
+ // end of track meta event, and 50% of Midi files or so
+ // do not correctly give the track size.
+ inputfile.readBigEndian(longdata);
+
+ // set the size of the track allocation so that it might
+ // approximately fit the data.
+ events[i]->setSize(longdata/2);
+ events[i]->setSize(0);
+
+ // process the track
+ absticks = 0;
+ barline = 1;
+ while (!inputfile.eof()) {
+ longdata = extractVlvTime(inputfile);
+//std::cout << "ticks = " << longdata << std::endl;
+ absticks += longdata;
+ extractMidiData(inputfile, event.data, runningCommand);
+//std::cout << "command = " << std::hex << (int)event.data[0] << std::dec << std::endl;
+ if (event.data[0] == 0xff && (event.data[1] == 1 ||
+ event.data[1] == 2 || event.data[1] == 3 || event.data[1] == 4)) {
+ // mididata.append('\0');
+ // std::cout << '\t';
+ // for (int m=0; m<event.data[2]; m++) {
+ // std::cout << event.data[m+3];
+ // }
+ // std::cout.flush();
+ } else if (event.data[0] == 0xff && event.data[1] == 0x2f) {
+ break;
+ }
+
+ if (event.data[0] != 0xff && event.data[0] != 0xf0) {
+ event.time = absticks;
+ if ((event.data[0] & 0xf0) == 0x90) {
+ if (event.data[1] < 12) {
+ event.data[0] = event.data[1];
+ switch (event.data[0]) {
+ case 2: event.data[2] = barline++; // barline
+ break;
+ case 0: break; // beat
+ }
+ }
+ }
+ event.track = i;
+ events[i]->append(event);
+ } else {
+ event.time = absticks;
+ event.track = i;
+ events[i]->append(event);
+ }
+
+ }
+
+ }
+ // std::cout << std::endl;
+
+ theTimeState = TIME_STATE_ABSOLUTE;
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::setTicksPerQuarterNote --
+//
+
+void MidiFile::setTicksPerQuarterNote(int ticks) {
+ ticksPerQuarterNote = ticks;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::sortTrack --
+//
+
+void MidiFile::sortTrack(Collection<_MFEvent>& trackData) {
+ qsort(trackData.getBase(), trackData.getSize(),
+ sizeof(_MFEvent), eventcompare);
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::sortTracks -- sort all tracks in the MidiFile.
+//
+
+void MidiFile::sortTracks(void) {
+ for (int i=0; i<getTrackCount(); i++) {
+ sortTrack(*events[i]);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::splitTracks -- take the joined tracks and split them
+// back into their separate track identities.
+//
+
+void MidiFile::splitTracks(void) {
+ if (getTrackState() == TRACK_STATE_SPLIT) {
+ return;
+ }
+
+ int oldTimeState = getTimeState();
+ if (oldTimeState == TIME_STATE_DELTA) {
+ absoluteTime();
+ }
+
+ int maxTrack = 0;
+ int i;
+ int length = events[0]->getSize();
+ for (i=0; i<length; i++) {
+ if ((*events[0])[i].track > maxTrack) {
+ maxTrack = (*events[0])[i].track;
+ }
+ }
+
+ Collection<_MFEvent>* olddata = events[0];
+ events[0] = NULL;
+ events.setSize(maxTrack);
+ for (i=0; i<maxTrack; i++) {
+ events[i] = new Collection<_MFEvent>;
+ events[i]->setSize(0);
+ events[i]->allowGrowth();
+ }
+
+ int trackValue = 0;
+ for (i=0; length; i++) {
+ trackValue = (*olddata)[i].track;
+ events[trackValue]->append((*olddata)[i]);
+ }
+
+ delete olddata;
+
+ if (oldTimeState == TIME_STATE_DELTA) {
+ deltaTime();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::timeState -- returns what type of time method is
+// being used: either TIME_STATE_ABSOLUTE or TIME_STATE_DELTA.
+//
+
+int MidiFile::getTimeState(void) {
+ return theTimeState;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::getTrackState -- returns what type of track method
+// is being used: either TRACK_STATE_JOINED or TRACK_STATE_SPLIT.
+//
+
+int MidiFile::getTrackState(void) {
+ return theTrackState;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::write -- write a standard MIDI file from data.
+//
+
+int MidiFile::write(const char* aFile) {
+ int oldTimeState = getTimeState();
+ if (oldTimeState == TIME_STATE_ABSOLUTE) {
+ deltaTime();
+ }
+
+ #ifdef VISUAL
+ FileIO outputfile(aFile, ios::out | ios::noreplace | ios::binary);
+ #else
+ // ios::noreplace does not exists anymore in GCC 3.x
+ FileIO outputfile(aFile, std::ios::out /* | std::ios::noreplace */);
+ #endif
+
+ if (!outputfile.is_open()) {
+ std::cout << "Error: could not write: " << aFile << std::endl;
+ exit(1);
+ }
+
+ // write the header of the Standard MIDI File
+
+ char ch;
+ // 1. The characters "MThd"
+ ch = 'M';
+ outputfile.writeBigEndian(ch);
+ ch = 'T';
+ outputfile.writeBigEndian(ch);
+ ch = 'h';
+ outputfile.writeBigEndian(ch);
+ ch = 'd';
+ outputfile.writeBigEndian(ch);
+
+ // 2. write the size of the header (alwas a "6" stored in unsigned long
+ ulong longdata = 6;
+ outputfile.writeBigEndian(longdata);
+
+ // 3. MIDI file format, type 0, 1, or 2
+ ushort shortdata;
+ if (getNumTracks() == 1) {
+ shortdata = 0;
+ } else {
+ shortdata = 1;
+ }
+ outputfile.writeBigEndian(shortdata);
+
+ // 4. write out the number of tracks.
+ shortdata = getNumTracks();
+ outputfile.writeBigEndian(shortdata);
+
+ // 5. write out the number of ticks per quarternote. (avoiding SMTPE for now)
+ shortdata = getTicksPerQuarterNote();
+ outputfile.writeBigEndian(shortdata);
+
+ // now write each track.
+ Array<uchar> trackdata;
+ uchar endoftrack[4] = {0, 0xff, 0x2f, 0x00};
+ int i, j, k;
+ int size;
+ for (i=0; i<getNumTracks(); i++) {
+ trackdata.setSize(1000000); // make the track data larger than
+ // expected data input
+ trackdata.setGrowth(1000000);
+ trackdata.setSize(0);
+ trackdata.allowGrowth();
+ for (j=0; j<events[i]->getSize(); j++) {
+ writeVLValue((*events[i])[j].time, trackdata);
+ for (k=0; k<(*events[i])[j].data.getSize(); k++) {
+ trackdata.append((*events[i])[j].data[k]);
+ }
+ }
+ size = trackdata.getSize();
+ if ((trackdata[size-3] != 0xff) && (trackdata[size-2] != 0x2f)) {
+ trackdata.append(endoftrack[0]);
+ trackdata.append(endoftrack[1]);
+ trackdata.append(endoftrack[2]);
+ trackdata.append(endoftrack[3]);
+ }
+
+ // now ready to write to MIDI file.
+
+ // first write the track ID marker "MTrk":
+ ch = 'M';
+ outputfile.writeBigEndian(ch);
+ ch = 'T';
+ outputfile.writeBigEndian(ch);
+ ch = 'r';
+ outputfile.writeBigEndian(ch);
+ ch = 'k';
+ outputfile.writeBigEndian(ch);
+
+ // A. write the size of the MIDI data to follow:
+ longdata = trackdata.getSize();
+ outputfile.writeBigEndian(longdata);
+
+ // B. write the actual data
+ outputfile.write((char*)trackdata.getBase(), trackdata.getSize());
+ }
+
+ if (oldTimeState == TIME_STATE_ABSOLUTE) {
+ absoluteTime();
+ }
+
+ outputfile.close();
+
+ return 1;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+
+//////////////////////////////
+//
+// MidiF::extractMidiData --
+//
+
+void MidiFile::extractMidiData(FileIO& inputfile, Array<uchar>& array,
+ uchar& runningCommand) {
+
+ uchar byte;
+ array.setSize(0);
+ array.allowGrowth();
+ int runningQ;
+
+ inputfile.readBigEndian(byte);
+
+ if (byte < 0x80) {
+ runningQ = 1;
+ if (runningCommand == 0) {
+ std::cout << "Error: running command with no previous command" << std::endl;
+ exit(1);
+ }
+ } else {
+ runningCommand = byte;
+ runningQ = 0;
+ }
+
+ array.append(runningCommand);
+ if (runningQ) {
+ array.append(byte);
+ }
+
+ uchar metai;
+ switch (runningCommand & 0xf0) {
+ case 0x80: // note off (2 more bytes)
+ case 0x90: // note on (2 more bytes)
+ case 0xA0: // aftertouch (2 more bytes)
+ case 0xB0: // cont. controller (2 more bytes)
+ case 0xE0: // pitch wheel (2 more bytes)
+ inputfile.readBigEndian(byte);
+ array.append(byte);
+ if (!runningQ) {
+ inputfile.readBigEndian(byte);
+ array.append(byte);
+ }
+ break;
+ case 0xC0: // patch change (1 more byte)
+ case 0xD0: // channel pressure (1 more byte)
+ if (!runningQ) {
+ inputfile.readBigEndian(byte);
+ array.append(byte);
+ }
+ break;
+ case 0xF0:
+ switch (runningCommand) {
+ case 0xff: // meta event
+ {
+ if (!runningQ) {
+ inputfile.readBigEndian(byte); // meta type
+ array.append(byte);
+ }
+ inputfile.readBigEndian(metai); // meta size
+ array.append(metai);
+ for (uchar j=0; j<metai; j++) {
+ inputfile.readBigEndian(byte); // meta data
+ array.append(byte);
+ }
+ }
+ break;
+ case 0xf0: // sysex
+ // read until you find a 0xf7 character
+ byte = 0;
+ while (byte != 0xf7 && !inputfile.eof()) {
+ inputfile.readBigEndian(byte); // meta data
+ }
+ break;
+ }
+ break;
+ default:
+ std::cout << "Error reading midifile" << std::endl;
+ std::cout << "Command byte was " << (int)runningCommand << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiF::extractVlvTime --
+//
+
+ulong MidiFile::extractVlvTime(FileIO& inputfile) {
+ uchar b[5] = {0};
+
+ for (int i=0; i<5; i++) {
+ inputfile.readBigEndian(b[i]);
+ if (b[i] < 0x80) {
+ break;
+ }
+ }
+
+ return unpackVLV(b[0], b[1], b[2], b[3], b[4]);
+}
+
+
+
+//////////////////////////////
+//
+// MidiF::unpackVLV -- converts a VLV value to pure unsigned long value.
+// default values: a = b = c = d = e = 0;
+//
+
+ulong MidiFile::unpackVLV(uchar a, uchar b, uchar c, uchar d, uchar e) {
+ if (e > 0x7f) {
+ std::cout << "Error: VLV value was too long" << std::endl;
+ exit(1);
+ }
+
+ uchar bytes[5] = {a, b, c, d, e};
+ int count = 0;
+ while (bytes[count] > 0x7f && count < 5) {
+ count++;
+ }
+ count++;
+
+ ulong output = 0;
+ for (int i=0; i<count; i++) {
+ output = output << 7;
+ output = output | (bytes[i] & 0x7f);
+ }
+
+ return output;
+}
+
+
+//////////////////////////////
+//
+// MidiFileWrite::writeVLValue -- write a number to the midifile
+// as a variable length value which segments a file into 7-bit
+// values. Maximum size of aValue is 0x7fffffff
+//
+
+void MidiFile::writeVLValue(long aValue, Array<uchar>& outdata) {
+ uchar bytes[5] = {0};
+ bytes[0] = (uchar)(((ulong)aValue >> 28) & 0x7f); // most significant 5 bits
+ bytes[1] = (uchar)(((ulong)aValue >> 21) & 0x7f); // next largest 7 bits
+ bytes[2] = (uchar)(((ulong)aValue >> 14) & 0x7f);
+ bytes[3] = (uchar)(((ulong)aValue >> 7) & 0x7f);
+ bytes[4] = (uchar)(((ulong)aValue) & 0x7f); // least significant 7 bits
+
+ int start = 0;
+ while (start<5 && bytes[start] == 0) start++;
+
+ for (int i=start; i<4; i++) {
+ bytes[i] = bytes[i] | 0x80;
+ outdata.append(bytes[i]);
+ }
+ outdata.append(bytes[4]);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// external functions
+//
+
+
+//////////////////////////////
+//
+// eventcompare -- for sorting the tracks
+//
+
+int eventcompare(const void* a, const void* b) {
+ _MFEvent& aevent = *((_MFEvent*)a);
+ _MFEvent& bevent = *((_MFEvent*)b);
+
+ if (aevent.time > bevent.time) {
+ return 1;
+ } else if (aevent.time < bevent.time) {
+ return -1;
+ } else if (aevent.data[0] == 0xff && bevent.data[0] != 0xff) {
+ return 1;
+ } else if (bevent.data[0] == 0xff && aevent.data[0] != 0xff) {
+ return -1;
+ } else if (bevent.data[0] == 0xff && bevent.data[1] == 0x2f) {
+ return -1;
+ } else if (aevent.data[0] == 0xff && aevent.data[1] == 0x2f) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// operator<< -- for printing an ASCII version of the MIDI file
+//
+
+std::ostream& operator<<(std::ostream& out, MidiFile& aMidiFile) {
+ int i, j, k;
+ out << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
+ out << "Number of Tracks: " << aMidiFile.getTrackCount() << "\n";
+ out << "Time method: " << aMidiFile.getTimeState();
+ if (aMidiFile.getTimeState() == TIME_STATE_DELTA) {
+ out << " (Delta timing)";
+ } else if (aMidiFile.getTimeState() == TIME_STATE_ABSOLUTE) {
+ out << " (Absolute timing)";
+ } else {
+ out << " (unknown method)";
+ }
+ out << "\n";
+
+ out << "Divisions per Quarter Note: " << std::dec << aMidiFile.getTicksPerQuarterNote() << "\n";
+ for (i=0; i<aMidiFile.getNumTracks(); i++) {
+ out << "\nTrack " << i
+ << " +++++++++++++++++++++++++++++++++++++++++++++++++++\n\n";
+ for (j=0; j<aMidiFile.getNumEvents(i); j++) {
+ out << std::dec << aMidiFile.getEvent(i, j).time << "\t"
+ << "0x" << std::hex << (int)aMidiFile.getEvent(i, j).data[0] << " ";
+ if (aMidiFile.getEvent(i, j).data[0] == 0xff) {
+
+ if (aMidiFile.getEvent(i, j).data[1] == 0x01) {
+ out << "TEXT [";
+ for (k=3; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << (char)aMidiFile.getEvent(i, j).data[k];
+ }
+ out << "]";
+
+ } else if (aMidiFile.getEvent(i, j).data[1] == 0x02) {
+ out << "COPY [";
+ for (k=3; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << (char)aMidiFile.getEvent(i, j).data[k];
+ }
+ out << "]";
+
+ } else if (aMidiFile.getEvent(i, j).data[1] == 0x03) {
+ out << "TRACK [";
+ for (k=3; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << (char)aMidiFile.getEvent(i, j).data[k];
+ }
+ out << "]";
+
+ } else if (aMidiFile.getEvent(i, j).data[1] == 0x04) {
+ out << "INSTR [";
+ for (k=3; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << (char)aMidiFile.getEvent(i, j).data[k];
+ }
+ out << "]";
+
+ } else if (aMidiFile.getEvent(i, j).data[1] == 0x05) {
+ out << "LYRIC [";
+ for (k=3; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << (char)aMidiFile.getEvent(i, j).data[k];
+ }
+ out << "]";
+
+ } else {
+ for (k=1; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << std::dec << (int)aMidiFile.getEvent(i, j).data[k] << " ";
+ }
+ }
+
+ } else {
+ for (k=1; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << std::dec << (int)aMidiFile.getEvent(i, j).data[k] << " ";
+ }
+ }
+ out << "\n";
+ }
+ }
+ out << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n";
+ return out;
+}
+
+
+
+// md5sum: cd4fb330dd874cc263921ec55222a199 - MidiFile.cpp =css= 20030102
diff --git a/src/midiio/src/MidiFileWrite.cpp b/src/midiio/src/MidiFileWrite.cpp
new file mode 100644
index 0000000..a22e70c
--- /dev/null
+++ b/src/midiio/src/MidiFileWrite.cpp
@@ -0,0 +1,259 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Mar 15 10:55:56 GMT-0800 1998
+// Last Modified: Sun Mar 15 10:55:56 GMT-0800 1998
+// Filename: ...sig/code/control/MidiFileWrite/MidiFileWrite.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiFileWrite.cpp
+// Syntax: C++
+//
+// Description: The MidiFileWrite class will write out a Type 0 MidiFile.
+// Used for recording MIDI data streams into Standard
+// MIDI files.
+//
+
+#include "MidiFileWrite.h"
+#include "SigTimer.h"
+#include <assert.h>
+
+
+//////////////////////////////
+//
+// MidiFileWrite::MidiFileWrite
+// default value: startTime = -1
+//
+
+MidiFileWrite::MidiFileWrite(void) {
+ trackSize = 0;
+ lastPlayTime = 0;
+ midifile = NULL;
+ openQ = 0;
+}
+
+
+MidiFileWrite::MidiFileWrite(const char* aFilename, int startTime) {
+ trackSize = 0;
+ lastPlayTime = 0;
+ midifile = NULL;
+ openQ = 0;
+ setup(aFilename, startTime);
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::~MidiFileWrite
+//
+
+MidiFileWrite::~MidiFileWrite() {
+ close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::close
+//
+
+void MidiFileWrite::close(void) {
+ writeRaw(0, 0xff, 0x2f, 0); // end of track meta event
+
+ midifile->seekg(18);
+ midifile->writeBigEndian(trackSize);
+
+ midifile->close();
+
+ midifile = NULL;
+ openQ = 0;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::setup -- writes the Midi file header and
+// prepares the midifile for writing of data
+// default value: startTime = -1
+//
+
+void MidiFileWrite::setup(const char* aFilename, int startTime) {
+ if (openQ) {
+ close();
+ }
+
+ if (midifile != NULL) delete midifile;
+ midifile = new FileIO;
+ midifile->open(aFilename, std::ios::out);
+
+ // write the header chunk
+ *midifile << "MThd"; // file identification: MIDI file
+ midifile->writeBigEndian(6L); // size of header (always 6)
+ midifile->writeBigEndian((short)0); // format: type 0;
+ midifile->writeBigEndian((short)0); // num of tracks (always 0 for type 0)
+ midifile->writeBigEndian((short)1000); // divisions per quarter note
+
+
+ // write the track header
+ *midifile << "MTrk";
+ midifile->writeBigEndian(0xffffL); // the track size which will
+ // be corrected with close()
+
+
+ // the midifile stream is now setup for writing
+ // track events
+
+ openQ = 1;
+
+ start(); // start can be called later and will behave well
+ // as long as no track events have been written
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::start
+// default value: startTime = -1;
+//
+
+void MidiFileWrite::start(int startTime) {
+ if (startTime < 0) {
+ SigTimer localTime;
+ lastPlayTime = localTime.getTime();
+ } else {
+ lastPlayTime = startTime;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::writeAbsolute -- considers the time data
+// to be the current time. It will generate a difference
+// time with the previously stored last playing time.
+//
+
+void MidiFileWrite::writeAbsolute(int aTime, int command, int p1, int p2) {
+ writeVLValue(aTime - lastPlayTime);
+ writeRaw((uchar)command, (uchar)p1, (uchar)p2);
+ lastPlayTime = aTime;
+}
+
+void MidiFileWrite::writeAbsolute(int aTime, int command, int p1) {
+ writeVLValue(aTime - lastPlayTime);
+ writeRaw((uchar)command, (uchar)p1);
+ lastPlayTime = aTime;
+}
+
+void MidiFileWrite::writeAbsolute(int aTime, int command) {
+ writeVLValue(aTime - lastPlayTime);
+ writeRaw((uchar)command);
+ lastPlayTime = aTime;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::writeRaw -- write an event byte to the midifile
+//
+
+void MidiFileWrite::writeRaw(uchar aByte) {
+ assert(midifile != NULL);
+ *midifile << aByte;
+ trackSize++;
+}
+
+
+void MidiFileWrite::writeRaw(uchar aByte, uchar bByte) {
+ writeRaw(aByte);
+ writeRaw(bByte);
+}
+
+
+void MidiFileWrite::writeRaw(uchar aByte, uchar bByte, uchar cByte) {
+ writeRaw(aByte);
+ writeRaw(bByte);
+ writeRaw(cByte);
+}
+
+
+void MidiFileWrite::writeRaw(uchar aByte, uchar bByte, uchar cByte,
+ uchar dByte) {
+ writeRaw(aByte);
+ writeRaw(bByte);
+ writeRaw(cByte);
+ writeRaw(dByte);
+}
+
+
+void MidiFileWrite::writeRaw(uchar aByte, uchar bByte, uchar cByte,
+ uchar dByte, uchar eByte) {
+ writeRaw(aByte);
+ writeRaw(bByte);
+ writeRaw(cByte);
+ writeRaw(dByte);
+ writeRaw(eByte);
+}
+
+
+void MidiFileWrite::writeRaw(uchar* anArray, int arraySize) {
+ for (int i=0; i<arraySize; i++) {
+ writeRaw(anArray[i]);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::writeRelative -- cosiders the time data
+// to be a delta time from the last input message.
+//
+
+void MidiFileWrite::writeRelative(int aTime, int command, int p1, int p2) {
+ writeVLValue(aTime);
+ writeRaw((uchar)command, (uchar)p1, (uchar)p2);
+ lastPlayTime += aTime;
+}
+
+void MidiFileWrite::writeRelative(int aTime, int command, int p1) {
+ writeVLValue(aTime);
+ writeRaw((uchar)command, (uchar)p1);
+ lastPlayTime += aTime;
+}
+
+void MidiFileWrite::writeRelative(int aTime, int command) {
+ writeVLValue(aTime);
+ writeRaw((uchar)command);
+ lastPlayTime += aTime;
+}
+
+
+//////////////////////////////
+//
+// MidiFileWrite::writeVLValue -- write a number to the midifile
+// as a variable length value which segments a file into 7-bit
+// values. Maximum size of aValue is 0x7fffffff
+//
+
+void MidiFileWrite::writeVLValue(long aValue) {
+ uchar bytes[5];
+ bytes[0] = (uchar)((aValue >> 28) & 0x7f); // most significant 5 bits
+ bytes[1] = (uchar)((aValue >> 21) & 0x7f); // next largest 7 bits
+ bytes[2] = (uchar)((aValue >> 14) & 0x7f);
+ bytes[3] = (uchar)((aValue >> 7) & 0x7f);
+ bytes[4] = (uchar)((aValue) & 0x7f); // least significant 7 bits
+
+ int start = 0;
+ while (start<5 && bytes[start] == 0) start++;
+
+ for (int i=start; i<4; i++) {
+ writeRaw((uchar)(bytes[i] | 0x80));
+ }
+ writeRaw(bytes[4]);
+}
+
+// md5sum: 251468fa23862745f0cf36f359bccc17 - MidiFileWrite.cpp =css= 20030102
diff --git a/src/midiio/src/MidiIO.cpp b/src/midiio/src/MidiIO.cpp
new file mode 100644
index 0000000..26363f2
--- /dev/null
+++ b/src/midiio/src/MidiIO.cpp
@@ -0,0 +1,283 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Sun Jan 25 15:45:18 GMT-0800 1998
+// Filename: ...sig/code/control/MidiIO/MidiIO.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiIO.cpp
+// Syntax: C++
+//
+// Description: A unified class for MidiInput and MidiOutput that handles
+// MIDI input and output connections. The Synthesizer
+// and RadioBaton classes are derived from this class.
+//
+
+#include "MidiIO.h"
+
+
+//////////////////////////////
+//
+// MidiIO::MidiIO
+//
+
+MidiIO::MidiIO(void) : MidiOutput(), MidiInput() {
+ // does nothing
+}
+
+
+MidiIO::MidiIO(int outPort, int inPort) :
+ MidiOutput(outPort), MidiInput(inPort) {
+ // does nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::~MidiIO
+//
+
+MidiIO::~MidiIO() {
+ // does nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::close
+//
+
+void MidiIO::close(void) {
+ MidiInput::close();
+ MidiOutput::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::closeInput
+//
+
+void MidiIO::closeInput(void) {
+ MidiInput::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::closeOutput
+//
+
+void MidiIO::closeOutput(void) {
+ MidiOutput::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getChannelInOffset -- return the MIDI channel offset of
+// the MIDI input.
+//
+
+int MidiIO::getChannelInOffset(void) const {
+ return MidiInPort::getChannelOffset();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getChannelOutOffset -- return the MIDI channel offset of
+// the MIDI output.
+//
+
+int MidiIO::getChannelOutOffset (void) const {
+ return MidiOutPort::getChannelOffset();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getInputPort
+//
+
+int MidiIO::getInputPort(void) {
+ return MidiInput::getPort();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getInputTrace
+//
+
+int MidiIO::getInputTrace(void) {
+ return MidiInput::getTrace();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getNumInputPorts
+//
+
+int MidiIO::getNumInputPorts(void) {
+ return MidiInput::getNumPorts();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getNumOutputPorts
+//
+
+int MidiIO::getNumOutputPorts(void) {
+ return MidiOutput::getNumPorts();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getOutputPort
+//
+
+int MidiIO::getOutputPort(void) {
+ return MidiOutput::getPort();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getOutputTrace
+//
+
+int MidiIO::getOutputTrace(void) {
+ return MidiOutput::getTrace();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::open
+//
+
+int MidiIO::open(void) {
+ if (MidiInput::open()) {
+ return MidiOutput::open();
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::openInput
+//
+
+int MidiIO::openInput(void) {
+ return MidiInput::open();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::openOutput
+//
+
+int MidiIO::openOutput(void) {
+ return MidiOutput::open();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::setChannelOffset -- sets the MIDI channel offset
+//
+
+void MidiIO::setChannelOffset(int anOffset) {
+ MidiInPort::setChannelOffset(anOffset);
+ MidiOutPort::setChannelOffset(anOffset);
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::setInputPort
+//
+
+void MidiIO::setInputPort(int aPort) {
+ MidiInput::setPort(aPort);
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::setInputTrace
+//
+
+void MidiIO::setInputTrace(int aState) {
+ MidiInput::setTrace(aState);
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::setOutputPort
+//
+
+void MidiIO::setOutputPort(int aPort) {
+ MidiOutput::setPort(aPort);
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::setOutputTrace
+//
+
+void MidiIO::setOutputTrace(int aState) {
+ MidiOutput::setTrace(aState);
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::toggleInputTrace
+//
+
+void MidiIO::toggleInputTrace(void) {
+ MidiInput::toggleTrace();
+}
+
+
+//////////////////////////////
+//
+// MidiIO::toggleOutputTrace
+//
+
+void MidiIO::toggleOutputTrace(void) {
+ MidiOutput::toggleTrace();
+}
+
+
+
+// md5sum: 860227c67236eb6f8897ae67f1338cb0 - MidiIO.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_alsa.cpp b/src/midiio/src/MidiInPort_alsa.cpp
new file mode 100644
index 0000000..55d22b0
--- /dev/null
+++ b/src/midiio/src/MidiInPort_alsa.cpp
@@ -0,0 +1,1038 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:03:16 PDT 2000
+// Last Modified: Sat Oct 13 16:11:10 PDT 2001 (updated for ALSA 0.9)
+// Last Modified: Fri Oct 26 14:41:36 PDT 2001 (running status for 0xa0 and 0xd0
+// fixed by Daniel Gardner)
+// Last Modified: Mon Nov 19 17:52:15 PST 2001 (thread on exit improved)
+// Filename: ...sig/code/control/MidiInPort/linux/MidiInPort_alsa.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiInPort_alsa.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux ALSA sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#if defined(LINUX) && defined(ALSA)
+
+#include "MidiInPort_alsa.h"
+#include <iostream>
+#include <stdlib.h>
+#include <pthread.h>
+#include <alsa/asoundlib.h>
+#include <unistd.h>
+
+#define DEFAULT_INPUT_BUFFER_SIZE (1024)
+
+// initialized static variables
+
+int MidiInPort_alsa::numDevices = 0;
+int MidiInPort_alsa::objectCount = 0;
+int* MidiInPort_alsa::portObjectCount = NULL;
+CircularBuffer<MidiMessage>** MidiInPort_alsa::midiBuffer = NULL;
+int MidiInPort_alsa::channelOffset = 0;
+SigTimer MidiInPort_alsa::midiTimer;
+int* MidiInPort_alsa::pauseQ = NULL;
+int* MidiInPort_alsa::trace = NULL;
+std::ostream* MidiInPort_alsa::tracedisplay = &std::cout;
+Array<pthread_t> MidiInPort_alsa::midiInThread;
+int* MidiInPort_alsa::sysexWriteBuffer = NULL;
+Array<uchar>** MidiInPort_alsa::sysexBuffers = NULL;
+
+Array<int> MidiInPort_alsa::threadinitport;
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::MidiInPort_alsa
+// default values: autoOpen = 1
+//
+
+MidiInPort_alsa::MidiInPort_alsa(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiInPort_alsa::MidiInPort_alsa(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::~MidiInPort_alsa
+//
+
+MidiInPort_alsa::~MidiInPort_alsa() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cerr << "Error: bad MidiInPort_alsa object count!: "
+ << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::clearSysex -- clears the data from a sysex
+// message and sets the allocation size to the default size (of 32
+// bytes).
+//
+
+void MidiInPort_alsa::clearSysex(int buffer) {
+ buffer = 0x7f | buffer; // limit buffer range from 0 to 127
+
+ if (getPort() == -1) {
+ return;
+ }
+
+ sysexBuffers[getPort()][buffer].setSize(0);
+ if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) {
+ // shrink the storage buffer's size if necessary
+ sysexBuffers[getPort()][buffer].setAllocSize(32);
+ }
+}
+
+
+void MidiInPort_alsa::clearSysex(void) {
+ // clear all sysex buffers
+ for (int i=0; i<128; i++) {
+ clearSysex(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::close
+//
+
+void MidiInPort_alsa::close(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+ Sequencer_alsa::closeInput(getPort());
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::closeAll --
+//
+
+void MidiInPort_alsa::closeAll(void) {
+ for (int i=0; i<getNumPorts(); i++) {
+ pauseQ[i] = 1;
+ Sequencer_alsa::closeInput(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::extract -- returns the next MIDI message
+// received since that last extracted message.
+//
+
+MidiMessage MidiInPort_alsa::extract(void) {
+ if (getPort() == -1) {
+ MidiMessage temp;
+ return temp;
+ }
+
+ return midiBuffer[getPort()]->extract();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getBufferSize -- returns the maximum possible number
+// of MIDI messages that can be stored in the buffer
+//
+
+int MidiInPort_alsa::getBufferSize(void) {
+ if (getPort() == -1) return 0;
+
+ return midiBuffer[getPort()]->getSize();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiInPort_alsa::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getCount -- returns the number of unexamined
+// MIDI messages waiting in the input buffer.
+//
+
+int MidiInPort_alsa::getCount(void) {
+ if (getPort() == -1) return 0;
+ return midiBuffer[getPort()]->getCount();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until all instances
+// of MIDI classes are.
+//
+
+const char* MidiInPort_alsa::getName(void) {
+ if (getPort() == -1) {
+ return "Null ALSA MIDI Input";
+ }
+ return getInputName(getPort());
+}
+
+
+const char* MidiInPort_alsa::getName(int i) {
+ return getInputName(i);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getNumPorts -- returns the number of available
+// ports for MIDI input
+//
+
+int MidiInPort_alsa::getNumPorts(void) {
+ return getNumInputs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiInPort_alsa::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiInPort_alsa::getPortStatus(void) {
+ return is_open_in(getPort());
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getSysex -- returns the sysex message contents
+// of a given buffer. You should check to see that the size is
+// non-zero before looking at the data. The data pointer will
+// be NULL if there is no data in the buffer.
+//
+
+uchar* MidiInPort_alsa::getSysex(int buffer) {
+ buffer &= 0x7f; // limit the buffer access to indices 0 to 127.
+ if (getPort() == -1) {
+ return NULL;
+ }
+
+ if (sysexBuffers[getPort()][buffer].getSize() < 2) {
+ return NULL;
+ } else {
+ return sysexBuffers[getPort()][buffer].getBase();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getSysexSize -- returns the sysex message byte
+// count of a given buffer. Buffers are in the range from
+// 0 to 127.
+//
+
+int MidiInPort_alsa::getSysexSize(int buffer) {
+ if (getPort() == -1) {
+ return 0;
+ } else {
+ return sysexBuffers[getPort()][buffer & 0x7f].getSize();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getTrace -- returns true if trace is on or false
+// if trace is off. if trace is on, then prints to standard
+// output the Midi message received.
+//
+
+int MidiInPort_alsa::getTrace(void) {
+ if (getPort() == -1) return -1;
+
+ return trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::insert
+//
+
+void MidiInPort_alsa::insert(const MidiMessage& aMessage) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->insert(aMessage);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::installSysex -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_alsa::installSysex(uchar* anArray, int aSize) {
+ if (getPort() == -1) {
+ return -1;
+ } else {
+ return installSysexPrivate(getPort(), anArray, aSize);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::installSysexPrivate -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_alsa::installSysexPrivate(int port, uchar* anArray, int aSize) {
+ // choose a buffer to install sysex data into:
+ int bufferNumber = sysexWriteBuffer[port];
+ sysexWriteBuffer[port]++;
+ if (sysexWriteBuffer[port] >= 128) {
+ sysexWriteBuffer[port] = 0;
+ }
+
+ // copy contents of sysex message into the chosen buffer
+ sysexBuffers[port][bufferNumber].setSize(aSize);
+ uchar* dataptr = sysexBuffers[port][bufferNumber].getBase();
+ uchar* indataptr = anArray;
+ for (int i=0; i<aSize; i++) {
+ *dataptr = *indataptr;
+ dataptr++;
+ indataptr++;
+ }
+
+ // return the buffer number that was used
+ return bufferNumber;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::message -- look at an incoming MIDI message
+// without extracting it from the input buffer.
+//
+
+MidiMessage& MidiInPort_alsa::message(int index) {
+ if (getPort() == -1) {
+ static MidiMessage x;
+ return x;
+ }
+
+ CircularBuffer<MidiMessage>& temp = *midiBuffer[getPort()];
+ return temp[index];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::open -- returns true if MIDI input port was
+// opened.
+//
+
+int MidiInPort_alsa::open(void) {
+ if (getPort() == -1) return 0;
+
+ int status = Sequencer_alsa::openInput(getPort());
+ if (status) {
+ pauseQ[getPort()] = 0;
+ return 1;
+ } else {
+ pauseQ[getPort()] = 1;
+ return 0;
+ }
+
+ return 0;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::pause -- stop the Midi input port from
+// inserting MIDI messages into the buffer, but keeps the
+// port open. Use unpause() to reverse the effect of pause().
+//
+
+void MidiInPort_alsa::pause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::setBufferSize -- sets the allocation
+// size of the MIDI input buffer.
+//
+
+void MidiInPort_alsa::setBufferSize(int aSize) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->setSize(aSize);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::setChannelOffset -- sets the MIDI chan offset,
+// either 0 or 1.
+//
+
+void MidiInPort_alsa::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::setPort --
+//
+
+void MidiInPort_alsa::setPort(int aPort) {
+// if (aPort == -1) return;
+ if (aPort < -1 || aPort >= getNumPorts()) {
+// std::cerr << "Error: maximum port number is: " << getNumPorts()-1
+// << ", but you tried to access port: " << aPort << std::endl;
+// exit(1);
+ }
+ else {
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::setTrace -- if false, then don't print MIDI messages
+// to the screen.
+//
+
+int MidiInPort_alsa::setTrace(int aState) {
+ if (getPort() == -1) return -1;
+
+
+ int oldtrace = trace[getPort()];
+ if (aState == 0) {
+ trace[getPort()] = 0;
+ } else {
+ trace[getPort()] = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::toggleTrace -- switches the state of trace
+// Returns the previous value of the trace variable.
+//
+
+void MidiInPort_alsa::toggleTrace(void) {
+ if (getPort() == -1) return;
+
+ trace[getPort()] = !trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::unpause -- enables the Midi input port
+// to inserting MIDI messages into the buffer after the
+// port is already open.
+//
+
+void MidiInPort_alsa::unpause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 0;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_alsa::deinitialize(void) {
+ closeAll();
+
+ for (int i=0; i<getNumPorts(); i++) {
+ if (sysexBuffers != NULL && sysexBuffers[i] != NULL) {
+ delete [] sysexBuffers[i];
+ sysexBuffers[i] = NULL;
+ }
+ }
+
+ if (sysexBuffers != NULL) {
+ delete [] sysexBuffers;
+ sysexBuffers = NULL;
+ }
+
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ midiBuffer = NULL;
+ }
+
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ portObjectCount = NULL;
+ }
+
+ if (trace != NULL) {
+ delete [] trace;
+ trace = NULL;
+ }
+
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ pauseQ = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_alsa::initialize(void) {
+ // set the number of ports
+ numDevices = Sequencer_alsa::indevcount;
+
+ if (getNumPorts() <= 0) {
+// std::cerr << "Warning: no MIDI input devices" << std::endl;
+ } else {
+
+ // allocate space for pauseQ, the port pause status
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ }
+ pauseQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ }
+ portObjectCount = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (trace != NULL) {
+ delete [] trace;
+ }
+ trace = new int[numDevices];
+
+ // allocate space for the Midi input buffers
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ }
+ midiBuffer = new CircularBuffer<MidiMessage>*[numDevices];
+
+ // allocate space for Midi input sysex buffer write indices
+ if (sysexWriteBuffer != NULL) {
+ delete [] sysexWriteBuffer;
+ }
+ sysexWriteBuffer = new int[numDevices];
+
+ // allocate space for Midi input sysex buffers
+ if (sysexBuffers != NULL) {
+ std::cout << "Error: memory leak on sysex buffers initialization" << std::endl;
+ exit(1);
+ }
+ sysexBuffers = new Array<uchar>*[numDevices];
+
+ int flag;
+ midiInThread.setSize(getNumPorts());
+ threadinitport.setSize(getNumPorts());
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ portObjectCount[i] = 0;
+ trace[i] = 0;
+ pauseQ[i] = 0;
+ midiBuffer[i] = new CircularBuffer<MidiMessage>;
+ midiBuffer[i]->setSize(DEFAULT_INPUT_BUFFER_SIZE);
+
+ sysexWriteBuffer[i] = 0;
+ sysexBuffers[i] = new Array<uchar>[128];
+ for (int n=0; n<128; n++) {
+ sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow
+ sysexBuffers[i][n].setAllocSize(32);
+ sysexBuffers[i][n].setSize(0);
+ sysexBuffers[i][n].setGrowth(32); // in case it will ever grow
+ }
+
+ threadinitport[i] = i;
+ flag = pthread_create(&midiInThread[i], NULL,
+ interpretMidiInputStreamPrivateALSA, &threadinitport[i]);
+ if (flag == -1) {
+ std::cout << "Unable to create MIDI input thread." << std::endl;
+ exit(1);
+ }
+ }
+
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// friendly functions
+//
+
+
+//////////////////////////////
+//
+// interpretMidiInputStreamPrivateALSA -- handles the MIDI input stream
+// for the various input devices from the ALSA MIDI driver.
+//
+// Note about system exclusive messages:
+// System Exclusive messages are stored in a separate buffer from
+// Other Midi messages since they can be variable in length. If
+// The Midi Input returns a message with command byte 0xf0, then
+// the p1() byte indicates the system exclusive buffer number that is
+// holding the system exclusive data for that Midi message. There
+// are 128 system exclusive buffers that are numbered between
+// 0 and 127. These buffers are filled in a cycle.
+// To extract a System exclusive message from MidiInPort_alsa,
+// you first will receive a Message with a command byte of 0xf0.
+// you can then access the data for that sysex by the command:
+// MidiInPort_alsa::getSysex(buffer_number), this will return
+// a pointer to the beginning of the sysex data. The first byte
+// of the sysex data should be 0xf0, and the last byte of the data
+// is 0xf7. All other bytes of data should be in the range from
+// 0 to 127. You can also get the size of the sysex buffer by the
+// following command: MidiInPort_alsa::getSysexSize(buffer_number).
+// This command will tell you the number of bytes in the system
+// exclusive message including the starting 0xf0 and the ending 0xf7.
+//
+// If you want to minimize memory useage of the system exclusive
+// buffers you can run the command:
+// MidiInPort_alsa::clearSysex(buffer_number); Otherwise the sysex
+// buffer will be erased automatically the next time that the
+// buffer number is cycled through when receiving more system exclusives.
+// Allocated the allocated size of the system exclusive storage will
+// not be adjusted when the computer replaces the system exclusive
+// message unless more storage size is needed, clearSysex however,
+// will resize the sysex buffer to its default size (currently 32 bytes).
+// clearSysex() without arguments will resize all buffers so that
+// they are allocated to the default size and will erase data from
+// all buffers. You can spoof a system exclusive message coming in
+// by installing a system exclusive message and then inserting
+// the system message command into the input buffer of the MidiInPort
+// class, int sysex_buffer = MidiInPort_alsa::installSysex(
+// uchar *data, int size); will put the data into a sysex buffer and
+// return the buffer number that it was placed into.
+//
+// This function assumes that System Exclusive messages cannot be sent
+// as a running status messages.
+//
+// Note about MidiMessage time stamps:
+// The MidiMessage::time field is a recording of the time that the
+// first byte of the MidiMessage arrived. If the message is from
+// running status mode, then the time that the first parameter byte
+// arrived is stored. System exclusive message arrival times are
+// recoreded at the time of the last byte (0xf7) arriving. This is
+// because other system messages can be coming in while the sysex
+// message is coming in. Anyway, sysex messages are not really to
+// be used for real time MIDI messaging, so the exact moment that the
+// first byte of the sysex came in is not important to me.
+//
+//
+
+void *interpretMidiInputStreamPrivateALSA(void * arg) {
+ int portToWatch = *(int*)arg;
+ if (portToWatch < 0 || portToWatch > 1000) {
+ // the port to watch is invalid -- because the program has died
+ // before the thread function could start. Cause of invalid port
+ // data should be examined more carefully.
+ return NULL;
+ }
+
+ int* argsExpected = NULL; // MIDI parameter bytes expected to follow
+ int* argsLeft = NULL; // MIDI parameter bytes left to wait for
+ uchar packet[1]; // bytes for sequencer driver
+ MidiMessage* message = NULL; // holder for current MIDI message
+ int newSigTime = 0; // for millisecond timer
+ int lastSigTime = -1; // for millisecond timer
+ int zeroSigTime = -1; // for timing incoming events
+ int device = -1; // for sorting out the bytes by input device
+ Array<uchar>* sysexIn; // MIDI Input sysex temporary storage
+
+ // Note on the use of argsExpected and argsLeft for sysexs:
+ // If argsExpected is -1, then a sysex message is coming in.
+ // If argsLeft < 0, then the sysex message has not finished comming
+ // in. If argsLeft == 0 and argsExpected == -1, then the sysex
+ // has finished coming in and is to be sent to the correct
+ // location.
+
+ // allocate space for MIDI messages, each device has a different message
+ // holding spot in case the messages overlap in the input stream
+ message = new MidiMessage[MidiInPort_alsa::numDevices];
+ argsExpected = new int[MidiInPort_alsa::numDevices];
+ argsLeft = new int[MidiInPort_alsa::numDevices];
+
+ sysexIn = new Array<uchar>[MidiInPort_alsa::numDevices];
+ for (int j=0; j<MidiInPort_alsa::numDevices; j++) {
+ sysexIn[j].allowGrowth();
+ sysexIn[j].setSize(32);
+ sysexIn[j].setSize(0);
+ sysexIn[j].setGrowth(512);
+ }
+
+ // interpret MIDI bytes as they come into the computer
+ // and repackage them as MIDI messages.
+ int packetReadCount;
+ while (1) {
+top_of_loop:
+ packetReadCount = 0;
+
+ // If the all Sequencer_alsa classes have been deleted,
+ // then Sequencer_alsa::rawmidi_in will have zero size.
+ // If the size is zero, then that means the thread will be
+ // killed soon, and we do not want any processing to happen
+ // in this thread. If the port to watch is NULL, then that
+ // means that the MIDI input is not open, and we should not
+ // add any MIDI data to the input buffers. These cases are
+ // handled by the following if-else statement:
+ if (Sequencer_alsa::rawmidi_in.getSize() > 0 &&
+ Sequencer_alsa::rawmidi_in[portToWatch] != NULL) {
+ packetReadCount = snd_rawmidi_read(
+ Sequencer_alsa::rawmidi_in[portToWatch], packet, 1);
+ } else {
+ usleep(100000); // sleep for 1/10th of a second if the Input
+ // port is not open.
+ continue;
+ }
+
+
+ if (packetReadCount != 1) {
+ // this if statement is used to prevent cases where the
+ // read function above will time out and return 0 bytes
+ // read. This if statment will also take care of -1
+ // error return values by ignoring them.
+ continue;
+ }
+
+ if (Sequencer_alsa::initialized == 0) {
+ continue;
+ }
+
+ // determination of a full MIDI message from the input MIDI
+ // stream is based here on the observation that MIDI status
+ // bytes and subsequent data bytes are NOT returned in the same
+ // read() call. Rather, they are spread out over multiple read()
+ // returns, with only a single value per return. So if we
+ // find a status byte, we then determine the number of expected
+ // operands and process that number of subsequent read()s to
+ // to determine the complete midi message.
+
+ // store the MIDI input device to which the incoming MIDI
+ // byte belongs.
+ device = portToWatch;
+
+ // ignore the active sensing 0xfe and MIDI clock 0xf8 commands:
+ if (packet[0] == 0xfe || packet[0] == 0xf8) {
+ continue;
+ }
+
+ if (packet[0] & 0x80) { // a command byte has arrived
+ switch (packet[0] & 0xf0) {
+ case 0xf0:
+ if (packet[0] == 0xf0) {
+ argsExpected[device] = -1;
+ argsLeft[device] = -1;
+ if (sysexIn[device].getSize() != 0) {
+ // ignore the command for now. It is most
+ // likely an active sensing message.
+ goto top_of_loop;
+ } else {
+ uchar datum = 0xf0;
+ sysexIn[device].append(datum);
+ }
+ } if (packet[0] == 0xf7) {
+ argsLeft[device] = 0; // indicates sysex is done
+ uchar datum = 0xf7;
+ sysexIn[device].append(datum);
+ } else if (argsExpected[device] != -1) {
+ // this is a system message that may or may
+ // not be coming while a sysex is coming in
+ argsExpected[device] = 0;
+ } else {
+ // this is a system message that is not coming
+ // while a system exclusive is coming in
+ //argsExpected[device] = 0;
+ }
+ break;
+ case 0xc0:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received program change during sysex"
+ << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ case 0xd0:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received aftertouch message during"
+ " sysex" << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ default:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received another message during sysex"
+ << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 2;
+ }
+ break;
+ }
+ if (argsExpected[device] >= 0) {
+ argsLeft[device] = argsExpected[device];
+ }
+
+ newSigTime = MidiInPort_alsa::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+
+ if (packet[0] != 0xf7) {
+ message[device].p0() = packet[0];
+ }
+ message[device].p1() = 0;
+ message[device].p2() = 0;
+ message[device].p3() = 0;
+
+ if (packet[0] == 0xf7) {
+ goto sysex_done;
+ }
+ } else if (argsLeft[device]) { // not a command byte coming in
+ if (message[device].time == 0) {
+ // store the receipt time of the first message byte
+ newSigTime = MidiInPort_alsa::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+ }
+
+ if (argsExpected[device] < 0) {
+ // continue processing a sysex message
+ sysexIn[device].append(packet[0]);
+ } else {
+ // handle a message other than a sysex message
+ if (argsLeft[device] == argsExpected[device]) {
+ message[device].p1() = packet[0];
+ } else {
+ message[device].p2() = packet[0];
+ }
+ argsLeft[device]--;
+ }
+
+ // if MIDI message is complete, setup for running status, and
+ // insert note into proper buffer.
+
+ if (argsExpected[device] >= 0 && !argsLeft[device]) {
+
+ // store parameter data for running status
+ switch (message[device].p0() & 0xf0) {
+ case 0xc0: argsLeft[device] = 1; break;
+ case 0xd0: argsLeft[device] = 1; break; // fix by dan
+ default: argsLeft[device] = 2; break;
+ // 0x80 expects two arguments
+ // 0x90 expects two arguments
+ // 0xa0 expects two arguments
+ // 0xb0 expects two arguments
+ // 0xe0 expects two arguments
+ }
+
+ lastSigTime = newSigTime;
+
+ sysex_done: // come here when a sysex is completely done
+
+ // insert the MIDI message into the appropriate buffer
+ // do not insert into buffer if the MIDI input device
+ // is paused (which can mean closed). Or if the
+ // pauseQ array is pointing to NULL (which probably means that
+ // things are about to shut down).
+ if (MidiInPort_alsa::pauseQ != NULL &&
+ MidiInPort_alsa::pauseQ[device] == 0) {
+ if (argsExpected[device] < 0) {
+ // store the sysex in the MidiInPort_alsa
+ // buffer for sysexs and return the storage
+ // location:
+ int sysexlocation =
+ MidiInPort_alsa::installSysexPrivate(device,
+ sysexIn[device].getBase(),
+ sysexIn[device].getSize());
+
+ message[device].p0() = 0xf0;
+ message[device].p1() = sysexlocation;
+
+ sysexIn[device].setSize(0); // empty the sysex storage
+ argsExpected[device] = 0; // no run status for sysex
+ argsLeft[device] = 0; // turn off sysex input flag
+ }
+ MidiInPort_alsa::midiBuffer[device]->insert(
+ message[device]);
+// if (MidiInPort_alsa::callbackFunction != NULL) {
+// MidiInPort_alsa::callbackFunction(device);
+// }
+ if (MidiInPort_alsa::trace[device]) {
+ std::cout << '[' << std::hex << (int)message[device].p0()
+ << ':' << std::dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << std::flush;
+ }
+ message[device].time = 0;
+ } else {
+ if (MidiInPort_alsa::trace[device]) {
+ std::cout << '[' << std::hex << (int)message[device].p0()
+ << 'P' << std::dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << std::flush;
+ }
+ }
+ }
+ }
+
+ } // end while (1)
+
+ // This code is not yet reached, but should be made to do so eventually
+
+ if (message != NULL) {
+ delete message;
+ message = NULL;
+ }
+
+ if (argsExpected != NULL) {
+ delete argsExpected;
+ argsExpected = NULL;
+ }
+
+ if (argsLeft != NULL) {
+ delete argsLeft;
+ argsLeft = NULL;
+ }
+
+ if (sysexIn != NULL) {
+ delete sysexIn;
+ sysexIn = NULL;
+ }
+
+
+ return NULL;
+}
+
+
+
+#endif // LINUX && ALSA
+
+
+
+// md5sum: 14663a91d1f5283e05ca36399d5ab767 - MidiInPort_alsa.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_alsa05.cpp b/src/midiio/src/MidiInPort_alsa05.cpp
new file mode 100644
index 0000000..1aad849
--- /dev/null
+++ b/src/midiio/src/MidiInPort_alsa05.cpp
@@ -0,0 +1,995 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:03:16 PDT 2000
+// Last Modified: Wed Oct 3 22:28:20 PDT 2001 (frozen for ALSA 0.5)
+// Last Modified: Fri Oct 26 14:41:36 PDT 2001 (running status for 0xa0 and 0xd0
+// fixed by Daniel Gardner)
+// Filename: ...sig/code/control/MidiInPort/linux/MidiInPort_alsa05.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiInPort_alsa05.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux ALSA sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#if defined(LINUX) && defined(ALSA05)
+
+#include "MidiInPort_alsa05.h"
+#include <iostream.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/asoundlib.h>
+
+#define DEFAULT_INPUT_BUFFER_SIZE (1024)
+
+// initialized static variables
+
+int MidiInPort_alsa05::numDevices = 0;
+int MidiInPort_alsa05::objectCount = 0;
+int* MidiInPort_alsa05::portObjectCount = NULL;
+CircularBuffer<MidiMessage>** MidiInPort_alsa05::midiBuffer = NULL;
+int MidiInPort_alsa05::channelOffset = 0;
+SigTimer MidiInPort_alsa05::midiTimer;
+int* MidiInPort_alsa05::pauseQ = NULL;
+int* MidiInPort_alsa05::trace = NULL;
+ostream* MidiInPort_alsa05::tracedisplay = &cout;
+Array<pthread_t> MidiInPort_alsa05::midiInThread;
+int* MidiInPort_alsa05::sysexWriteBuffer = NULL;
+Array<uchar>** MidiInPort_alsa05::sysexBuffers = NULL;
+
+Array<int> MidiInPort_alsa05::threadinitport;
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::MidiInPort_alsa05
+// default values: autoOpen = 1
+//
+
+MidiInPort_alsa05::MidiInPort_alsa05(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiInPort_alsa05::MidiInPort_alsa05(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::~MidiInPort_alsa05
+//
+
+MidiInPort_alsa05::~MidiInPort_alsa05() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ cerr << "Error: bad MidiInPort_alsa05 object count!: "
+ << objectCount << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::clearSysex -- clears the data from a sysex
+// message and sets the allocation size to the default size (of 32
+// bytes).
+//
+
+void MidiInPort_alsa05::clearSysex(int buffer) {
+ buffer = 0x7f | buffer; // limit buffer range from 0 to 127
+
+ if (getPort() == -1) {
+ return;
+ }
+
+ sysexBuffers[getPort()][buffer].setSize(0);
+ if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) {
+ // shrink the storage buffer's size if necessary
+ sysexBuffers[getPort()][buffer].setAllocSize(32);
+ }
+}
+
+
+void MidiInPort_alsa05::clearSysex(void) {
+ // clear all sysex buffers
+ for (int i=0; i<128; i++) {
+ clearSysex(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::close
+//
+
+void MidiInPort_alsa05::close(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::closeAll --
+//
+
+void MidiInPort_alsa05::closeAll(void) {
+ Sequencer_alsa05::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::extract -- returns the next MIDI message
+// received since that last extracted message.
+//
+
+MidiMessage MidiInPort_alsa05::extract(void) {
+ if (getPort() == -1) {
+ MidiMessage temp;
+ return temp;
+ }
+
+ return midiBuffer[getPort()]->extract();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getBufferSize -- returns the maximum possible number
+// of MIDI messages that can be stored in the buffer
+//
+
+int MidiInPort_alsa05::getBufferSize(void) {
+ if (getPort() == -1) return 0;
+
+ return midiBuffer[getPort()]->getSize();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiInPort_alsa05::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getCount -- returns the number of unexamined
+// MIDI messages waiting in the input buffer.
+//
+
+int MidiInPort_alsa05::getCount(void) {
+ if (getPort() == -1) return 0;
+ return midiBuffer[getPort()]->getCount();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until all instances
+// of MIDI classes are.
+//
+
+const char* MidiInPort_alsa05::getName(void) {
+ if (getPort() == -1) {
+ return "Null ALSA MIDI Input";
+ }
+ return getInputName(getPort());
+}
+
+
+const char* MidiInPort_alsa05::getName(int i) {
+ return getInputName(i);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getNumPorts -- returns the number of available
+// ports for MIDI input
+//
+
+int MidiInPort_alsa05::getNumPorts(void) {
+ return getNumInputs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiInPort_alsa05::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiInPort_alsa05::getPortStatus(void) {
+ return is_open_in(0);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getSysex -- returns the sysex message contents
+// of a given buffer. You should check to see that the size is
+// non-zero before looking at the data. The data pointer will
+// be NULL if there is no data in the buffer.
+//
+
+uchar* MidiInPort_alsa05::getSysex(int buffer) {
+ buffer &= 0x7f; // limit the buffer access to indices 0 to 127.
+ if (getPort() == -1) {
+ return NULL;
+ }
+
+ if (sysexBuffers[getPort()][buffer].getSize() < 2) {
+ return NULL;
+ } else {
+ return sysexBuffers[getPort()][buffer].getBase();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getSysexSize -- returns the sysex message byte
+// count of a given buffer. Buffers are in the range from
+// 0 to 127.
+//
+
+int MidiInPort_alsa05::getSysexSize(int buffer) {
+ if (getPort() == -1) {
+ return 0;
+ } else {
+ return sysexBuffers[getPort()][buffer & 0x7f].getSize();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getTrace -- returns true if trace is on or false
+// if trace is off. if trace is on, then prints to standard
+// output the Midi message received.
+//
+
+int MidiInPort_alsa05::getTrace(void) {
+ if (getPort() == -1) return -1;
+
+ return trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::insert
+//
+
+void MidiInPort_alsa05::insert(const MidiMessage& aMessage) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->insert(aMessage);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::installSysex -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_alsa05::installSysex(uchar* anArray, int aSize) {
+ if (getPort() == -1) {
+ return -1;
+ } else {
+ return installSysexPrivate(getPort(), anArray, aSize);
+ }
+}
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::installSysexPrivate -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_alsa05::installSysexPrivate(int port, uchar* anArray, int aSize) {
+ // choose a buffer to install sysex data into:
+ int bufferNumber = sysexWriteBuffer[port];
+ sysexWriteBuffer[port]++;
+ if (sysexWriteBuffer[port] >= 128) {
+ sysexWriteBuffer[port] = 0;
+ }
+
+ // copy contents of sysex message into the chosen buffer
+ sysexBuffers[port][bufferNumber].setSize(aSize);
+ uchar* dataptr = sysexBuffers[port][bufferNumber].getBase();
+ uchar* indataptr = anArray;
+ for (int i=0; i<aSize; i++) {
+ *dataptr = *indataptr;
+ dataptr++;
+ indataptr++;
+ }
+
+ // return the buffer number that was used
+ return bufferNumber;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::message
+//
+
+MidiMessage& MidiInPort_alsa05::message(int index) {
+ if (getPort() == -1) {
+ static MidiMessage x;
+ return x;
+ }
+
+ CircularBuffer<MidiMessage>& temp = *midiBuffer[getPort()];
+ return temp[index];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::open -- returns true if MIDI input port was
+// opened.
+//
+
+int MidiInPort_alsa05::open(void) {
+ if (getPort() == -1) return 0;
+
+ return Sequencer_alsa05::open();
+ pauseQ[getPort()] = 0;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::pause -- stop the Midi input port from
+// inserting MIDI messages into the buffer, but keeps the
+// port open. Use unpause() to reverse the effect of pause().
+//
+
+void MidiInPort_alsa05::pause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::setBufferSize -- sets the allocation
+// size of the MIDI input buffer.
+//
+
+void MidiInPort_alsa05::setBufferSize(int aSize) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->setSize(aSize);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::setChannelOffset -- sets the MIDI chan offset,
+// either 0 or 1.
+//
+
+void MidiInPort_alsa05::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ cout << "Error: Channel offset can be only 0 or 1." << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::setPort --
+//
+
+void MidiInPort_alsa05::setPort(int aPort) {
+// if (aPort == -1) return;
+ if (aPort < -1 || aPort >= getNumPorts()) {
+ cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::setTrace -- if false, then don't print MIDI messages
+// to the screen.
+//
+
+int MidiInPort_alsa05::setTrace(int aState) {
+ if (getPort() == -1) return -1;
+
+
+ int oldtrace = trace[getPort()];
+ if (aState == 0) {
+ trace[getPort()] = 0;
+ } else {
+ trace[getPort()] = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::toggleTrace -- switches the state of trace
+// Returns the previous value of the trace variable.
+//
+
+void MidiInPort_alsa05::toggleTrace(void) {
+ if (getPort() == -1) return;
+
+ trace[getPort()] = !trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::unpause -- enables the Midi input port
+// to inserting MIDI messages into the buffer after the
+// port is already open.
+//
+
+void MidiInPort_alsa05::unpause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 0;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_alsa05::deinitialize(void) {
+ closeAll();
+
+ for (int i=0; i<getNumPorts(); i++) {
+ if (sysexBuffers != NULL && sysexBuffers[i] != NULL) {
+ delete [] sysexBuffers[i];
+ sysexBuffers[i] = NULL;
+ }
+ }
+
+ if (sysexBuffers != NULL) {
+ delete [] sysexBuffers;
+ sysexBuffers = NULL;
+ }
+
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ midiBuffer = NULL;
+ }
+
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ portObjectCount = NULL;
+ }
+
+ if (trace != NULL) {
+ delete [] trace;
+ trace = NULL;
+ }
+
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ pauseQ = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_alsa05::initialize(void) {
+ // set the number of ports
+ numDevices = Sequencer_alsa05::indevcount;
+
+ if (getNumPorts() <= 0) {
+ cerr << "Warning: no MIDI input devices" << endl;
+ } else {
+
+ // allocate space for pauseQ, the port pause status
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ }
+ pauseQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ }
+ portObjectCount = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (trace != NULL) {
+ delete [] trace;
+ }
+ trace = new int[numDevices];
+
+ // allocate space for the Midi input buffers
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ }
+ midiBuffer = new CircularBuffer<MidiMessage>*[numDevices];
+
+ // allocate space for Midi input sysex buffer write indices
+ if (sysexWriteBuffer != NULL) {
+ delete [] sysexWriteBuffer;
+ }
+ sysexWriteBuffer = new int[numDevices];
+
+ // allocate space for Midi input sysex buffers
+ if (sysexBuffers != NULL) {
+ cout << "Error: memory leak on sysex buffers initialization" << endl;
+ exit(1);
+ }
+ sysexBuffers = new Array<uchar>*[numDevices];
+
+ int flag;
+ midiInThread.setSize(getNumPorts());
+ threadinitport.setSize(getNumPorts());
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ portObjectCount[i] = 0;
+ trace[i] = 0;
+ pauseQ[i] = 0;
+ midiBuffer[i] = new CircularBuffer<MidiMessage>;
+ midiBuffer[i]->setSize(DEFAULT_INPUT_BUFFER_SIZE);
+
+ sysexWriteBuffer[i] = 0;
+ sysexBuffers[i] = new Array<uchar>[128];
+ for (int n=0; n<128; n++) {
+ sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow
+ sysexBuffers[i][n].setAllocSize(32);
+ sysexBuffers[i][n].setSize(0);
+ sysexBuffers[i][n].setGrowth(32); // in case it will ever grow
+ }
+
+ threadinitport[i] = i;
+ flag = pthread_create(&midiInThread[i], NULL,
+ interpretMidiInputStreamPrivateALSA05, &threadinitport[i]);
+ if (flag == -1) {
+ cout << "Unable to create MIDI input thread." << endl;
+ exit(1);
+ }
+ }
+
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// friendly functions
+//
+
+
+//////////////////////////////
+//
+// interpretMidiInputStreamPrivateALSA05 -- handles the MIDI input stream
+// for the various input devices from the ALSA MIDI driver.
+//
+// Note about system exclusive messages:
+// System Exclusive messages are stored in a separate buffer from
+// Other Midi messages since they can be variable in length. If
+// The Midi Input returns a message with command byte 0xf0, then
+// the p1() byte indicates the system exclusive buffer number that is
+// holding the system exclusive data for that Midi message. There
+// are 128 system exclusive buffers that are numbered between
+// 0 and 127. These buffers are filled in a cycle.
+// To extract a System exclusive message from MidiInPort_alsa05,
+// you first will receive a Message with a command byte of 0xf0.
+// you can then access the data for that sysex by the command:
+// MidiInPort_alsa05::getSysex(buffer_number), this will return
+// a pointer to the beginning of the sysex data. The first byte
+// of the sysex data should be 0xf0, and the last byte of the data
+// is 0xf7. All other bytes of data should be in the range from
+// 0 to 127. You can also get the size of the sysex buffer by the
+// following command: MidiInPort_alsa05::getSysexSize(buffer_number).
+// This command will tell you the number of bytes in the system
+// exclusive message including the starting 0xf0 and the ending 0xf7.
+//
+// If you want to minimize memory useage of the system exclusive
+// buffers you can run the command:
+// MidiInPort_alsa05::clearSysex(buffer_number); Otherwise the sysex
+// buffer will be erased automatically the next time that the that
+// buffer number is cycled through when receiving more system exclusives.
+// Allocated the allocated size of the system exclusive storage will
+// not be adjusted when the computer replaces the system exclusive
+// message unless more storage size is needed, clearSysex however,
+// will resize the sysex buffer to its default size (currently 32 bytes).
+// clearSysex() without arguments will resize all buffers so that
+// they are allocated to the default size and will erase data from
+// all buffers. You can spoof a system exclusive message coming in
+// by installing a system exclusive message and then inserting
+// the system message command into the input buffer of the MidiInPort
+// class, int sysex_buffer = MidiInPort_alsa05::installSysex(
+// uchar *data, int size); will put the data into a sysex buffer and
+// return the buffer number that it was placed into.
+//
+// This function assumes that System Exclusive messages cannot be sent
+// as a running status messages.
+//
+// Note about MidiMessage time stamps:
+// The MidiMessage::time field is a recording of the time that the
+// first byte of the MidiMessage arrived. If the message is from
+// running status mode, then the time that the first parameter byte
+// arrived is stored. System exclusive message arrival times are
+// recoreded at the time of the last byte (0xf7) arriving. This is
+// because other system messages can be coming in while the sysex
+// message is coming in. Anyway, sysex messages are not really to
+// be used for real time MIDI messaging, so the exact moment that the
+// first byte of the sysex came in is not important to me.
+//
+//
+
+void *interpretMidiInputStreamPrivateALSA05(void * arg) {
+ int portToWatch = *(int*)arg;
+
+ int* argsExpected = NULL; // MIDI parameter bytes expected to follow
+ int* argsLeft = NULL; // MIDI parameter bytes left to wait for
+ uchar packet[1]; // bytes for sequencer driver
+ MidiMessage* message = NULL; // holder for current MIDI message
+ int newSigTime = 0; // for millisecond timer
+ int lastSigTime = -1; // for millisecond timer
+ int zeroSigTime = -1; // for timing incoming events
+ int device = -1; // for sorting out the bytes by input device
+ Array<uchar>* sysexIn; // MIDI Input sysex temporary storage
+
+ // Note on the use of argsExpected and argsLeft for sysexs:
+ // If argsExpected is -1, then a sysex message is coming in.
+ // If argsLeft < 0, then the sysex message has not finished comming
+ // in. If argsLeft == 0 and argsExpected == -1, then the sysex
+ // has finished coming in and is to be sent to the correct
+ // location.
+
+ // allocate space for MIDI messages, each device has a different message
+ // holding spot in case the messages overlap in the input stream
+ message = new MidiMessage[MidiInPort_alsa05::numDevices];
+ argsExpected = new int[MidiInPort_alsa05::numDevices];
+ argsLeft = new int[MidiInPort_alsa05::numDevices];
+
+ sysexIn = new Array<uchar>[MidiInPort_alsa05::numDevices];
+ for (int j=0; j<MidiInPort_alsa05::numDevices; j++) {
+ sysexIn[j].allowGrowth();
+ sysexIn[j].setSize(32);
+ sysexIn[j].setSize(0);
+ sysexIn[j].setGrowth(512);
+ }
+
+ // interpret MIDI bytes as they come into the computer
+ // and repackage them as MIDI messages.
+ int packetReadCount;
+ while (1) {
+top_of_loop:
+ packetReadCount = snd_rawmidi_read(
+ Sequencer_alsa05::rawmidi_in[portToWatch], packet, 1);
+ if (packetReadCount != 1) {
+ // this if statement is used to prevent cases where the
+ // read function above will time out and return 0 bytes
+ // read. This if statment will also take care of -1
+ // error return values by ignoring them.
+ continue;
+ }
+
+ if (Sequencer_alsa05::initialized == 0) {
+ continue;
+ }
+
+ // determination of a full MIDI message from the input MIDI
+ // stream is based here on the observation that MIDI status
+ // bytes and subsequent data bytes are NOT returned in the same
+ // read() call. Rather, they are spread out over multiple read()
+ // returns, with only a single value per return. So if we
+ // find a status byte, we then determine the number of expected
+ // operands and process that number of subsequent read()s to
+ // to determine the complete midi message.
+
+ // store the MIDI input device to which the incoming MIDI
+ // byte belongs.
+ device = portToWatch;
+
+ // ignore the active sensing 0xfe and MIDI clock 0xf8 commands:
+ if (packet[0] == 0xfe || packet[0] == 0xf8) {
+ continue;
+ }
+
+ if (packet[0] & 0x80) { // a command byte has arrived
+ switch (packet[0] & 0xf0) {
+ case 0xf0:
+ if (packet[0] == 0xf0) {
+ argsExpected[device] = -1;
+ argsLeft[device] = -1;
+ if (sysexIn[device].getSize() != 0) {
+ // ignore the command for now. It is most
+ // likely an active sensing message.
+ goto top_of_loop;
+ } else {
+ uchar datum = 0xf0;
+ sysexIn[device].append(datum);
+ }
+ } if (packet[0] == 0xf7) {
+ argsLeft[device] = 0; // indicates sysex is done
+ uchar datum = 0xf7;
+ sysexIn[device].append(datum);
+ } else if (argsExpected[device] != -1) {
+ // this is a system message that may or may
+ // not be coming while a sysex is coming in
+ argsExpected[device] = 0;
+ } else {
+ // this is a system message that is not coming
+ // while a system exclusive is coming in
+ //argsExpected[device] = 0;
+ }
+ break;
+ case 0xc0:
+ if (argsExpected[device] < 0) {
+ cout << "Error: received program change during sysex"
+ << endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ case 0xd0:
+ if (argsExpected[device] < 0) {
+ cout << "Error: received aftertouch message during"
+ " sysex" << endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ default:
+ if (argsExpected[device] < 0) {
+ cout << "Error: received another message during sysex"
+ << endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 2;
+ }
+ break;
+ }
+ if (argsExpected[device] >= 0) {
+ argsLeft[device] = argsExpected[device];
+ }
+
+ newSigTime = MidiInPort_alsa05::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+
+ if (packet[0] != 0xf7) {
+ message[device].p0() = packet[0];
+ }
+ message[device].p1() = 0;
+ message[device].p2() = 0;
+ message[device].p3() = 0;
+
+ if (packet[0] == 0xf7) {
+ goto sysex_done;
+ }
+ } else if (argsLeft[device]) { // not a command byte coming in
+ if (message[device].time == 0) {
+ // store the receipt time of the first message byte
+ newSigTime = MidiInPort_alsa05::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+ }
+
+ if (argsExpected[device] < 0) {
+ // continue processing a sysex message
+ sysexIn[device].append(packet[0]);
+ } else {
+ // handle a message other than a sysex message
+ if (argsLeft[device] == argsExpected[device]) {
+ message[device].p1() = packet[0];
+ } else {
+ message[device].p2() = packet[0];
+ }
+ argsLeft[device]--;
+ }
+
+ // if MIDI message is complete, setup for running status, and
+ // insert note into proper buffer.
+
+ if (argsExpected[device] >= 0 && !argsLeft[device]) {
+
+ // store parameter data for running status
+ switch (message[device].p0() & 0xf0) {
+ case 0xc0: argsLeft[device] = 1; break;
+ case 0xd0: argsLeft[device] = 1; break; // fix by dan
+ default: argsLeft[device] = 2; break;
+ // 0x80 expects two arguments
+ // 0x90 expects two arguments
+ // 0xa0 expects two arguments
+ // 0xb0 expects two arguments
+ // 0xe0 expects two arguments
+ }
+
+ lastSigTime = newSigTime;
+
+ sysex_done: // come here when a sysex is completely done
+
+ // insert the MIDI message into the appropriate buffer
+ // do not insert into buffer if the MIDI input device
+ // is paused (which can mean closed). Or if the
+ // pauseQ array is pointing to NULL (which probably means that
+ // things are about to shut down).
+ if (MidiInPort_alsa05::pauseQ != NULL &&
+ MidiInPort_alsa05::pauseQ[device] == 0) {
+ if (argsExpected[device] < 0) {
+ // store the sysex in the MidiInPort_alsa05
+ // buffer for sysexs and return the storage
+ // location:
+ int sysexlocation =
+ MidiInPort_alsa05::installSysexPrivate(device,
+ sysexIn[device].getBase(),
+ sysexIn[device].getSize());
+
+ message[device].p0() = 0xf0;
+ message[device].p1() = sysexlocation;
+
+ sysexIn[device].setSize(0); // empty the sysex storage
+ argsExpected[device] = 0; // no run status for sysex
+ argsLeft[device] = 0; // turn off sysex input flag
+ }
+ MidiInPort_alsa05::midiBuffer[device]->insert(
+ message[device]);
+// if (MidiInPort_alsa05::callbackFunction != NULL) {
+// MidiInPort_alsa05::callbackFunction(device);
+// }
+ if (MidiInPort_alsa05::trace[device]) {
+ cout << '[' << hex << (int)message[device].p0()
+ << ':' << dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << flush;
+ }
+ message[device].time = 0;
+ } else {
+ if (MidiInPort_alsa05::trace[device]) {
+ cout << '[' << hex << (int)message[device].p0()
+ << 'P' << dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << flush;
+ }
+ }
+ }
+ }
+
+ } // end while (1)
+
+ // This code is not yet reached, but should be made to do so eventually
+
+ if (message != NULL) {
+ delete message;
+ message = NULL;
+ }
+
+ if (argsExpected != NULL) {
+ delete argsExpected;
+ argsExpected = NULL;
+ }
+
+ if (argsLeft != NULL) {
+ delete argsLeft;
+ argsLeft = NULL;
+ }
+
+ if (sysexIn != NULL) {
+ delete sysexIn;
+ sysexIn = NULL;
+ }
+
+
+ return NULL;
+}
+
+
+
+#endif /* LINUX and ALSA05 */
+
+
+
+// md5sum: cc5ea6a6078cb534fc6c39543aa57a83 - MidiInPort_alsa05.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_linux.cpp b/src/midiio/src/MidiInPort_linux.cpp
new file mode 100644
index 0000000..01274e2
--- /dev/null
+++ b/src/midiio/src/MidiInPort_linux.cpp
@@ -0,0 +1,491 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:35:27 PDT 2000
+// Last Modified: Thu May 18 23:36:00 PDT 2000
+// Last Modified: Sat Nov 2 20:37:49 PST 2002 (added ifdef ALSA OSS)
+// Filename: ...sig/maint/code/control/MidiInPort/MidiInPort_linux.cpp
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort_linux.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of an
+// operating-system specific MIDI input method.
+// Provides control of all low-level MIDI input
+// functionality such that it will work on all
+// computers in the same manner.
+//
+
+#ifdef LINUX
+#if defined(ALSA) && defined(OSS)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "MidiInPort_linux.h"
+
+
+// initialize static variables oss_input->close(); break;
+int MidiInPort_linux::objectCount = 0;
+int MidiInPort_linux::current = MIDI_IN_OSS_SELECT;
+int MidiInPort_linux::alsaQ = 0;
+int MidiInPort_linux::ossQ = 0;
+MidiInPort_oss *MidiInPort_linux::oss_input = NULL;
+MidiInPort_alsa *MidiInPort_linux::alsa_input = NULL;
+MidiInPort_unsupported *MidiInPort_linux::unknown_input = NULL;
+
+
+MidiInPort_linux::MidiInPort_linux(void) {
+ if (objectCount == 0) {
+ determineDrivers();
+ } else if (objectCount < 0) {
+ cout << "Error: unusual MidiInPort_linux object count" << endl;
+ exit(1);
+ }
+
+ objectCount++;
+}
+
+
+MidiInPort_linux::MidiInPort_linux(int aPort, int autoOpen = 1) {
+ if (objectCount == 0) {
+ determineDrivers();
+ setAndOpenPort(aPort);
+ } else if (objectCount < 0) {
+ cout << "Error: unusual MidiInPort_linux object count" << endl;
+ exit(1);
+ }
+
+ objectCount++;
+}
+
+
+MidiInPort_linux::~MidiInPort_linux() {
+ objectCount--;
+ if (objectCount == 0) {
+ if (oss_input != NULL) {
+ delete oss_input;
+ oss_input = NULL;
+ }
+ if (alsa_input != NULL) {
+ delete alsa_input;
+ alsa_input = NULL;
+ }
+ if (unknown_input != NULL) {
+ delete unknown_input;
+ unknown_input = NULL;
+ }
+ }
+
+ if (objectCount < 0) {
+ cout << "Error: unusual MidiOutPort_linux count when destructing" << endl;
+ exit(1);
+ }
+}
+
+
+void MidiInPort_linux::clearSysex(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->clearSysex(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->clearSysex(); break;
+ default: unknown_input->clearSysex(); break;
+ }
+}
+
+
+void MidiInPort_linux::clearSysex(int buffer) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->clearSysex(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->clearSysex(); break;
+ default: unknown_input->clearSysex(); break;
+ }
+}
+
+
+void MidiInPort_linux::close(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->close(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->close(); break;
+ default: unknown_input->close(); break;
+ }
+}
+
+
+void MidiInPort_linux::closeAll(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->closeAll(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->closeAll(); break;
+ default: unknown_input->closeAll(); break;
+ }
+}
+
+
+MidiMessage MidiInPort_linux::extract(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->extract(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->extract(); break;
+ default: return unknown_input->extract(); break;
+ }
+}
+
+
+int MidiInPort_linux::getBufferSize(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getBufferSize(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getBufferSize(); break;
+ default: return unknown_input->getBufferSize(); break;
+ }
+}
+
+
+int MidiInPort_linux::getChannelOffset(void) const {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getChannelOffset(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getChannelOffset(); break;
+ default: return unknown_input->getChannelOffset(); break;
+ }
+}
+
+
+int MidiInPort_linux::getCount(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getCount(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getCount(); break;
+ default: return unknown_input->getCount(); break;
+ }
+}
+
+
+const char* MidiInPort_linux::getName(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getName(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getName(); break;
+ default: return unknown_input->getName(); break;
+ }
+}
+
+
+const char* MidiInPort_linux::getName(int i) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getName(i); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getName(i); break;
+ default: return unknown_input->getName(i); break;
+ }
+}
+
+
+int MidiInPort_linux::getNumPorts(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getNumPorts(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getNumPorts(); break;
+ default: return unknown_input->getNumPorts(); break;
+ }
+}
+
+
+int MidiInPort_linux::getPort(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getPort(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getPort(); break;
+ default: return unknown_input->getPort(); break;
+ }
+}
+
+
+int MidiInPort_linux::getPortStatus(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getPortStatus(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getPortStatus(); break;
+ default: return unknown_input->getPortStatus(); break;
+ }
+}
+
+
+uchar* MidiInPort_linux::getSysex(int buffer) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getSysex(buffer); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getSysex(buffer); break;
+ default: return unknown_input->getSysex(buffer); break;
+ }
+}
+
+
+int MidiInPort_linux::getSysexSize(int buffer) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getSysexSize(buffer); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getSysexSize(buffer); break;
+ default: return unknown_input->getSysexSize(buffer); break;
+ }
+}
+
+
+int MidiInPort_linux::getTrace(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getTrace(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getTrace(); break;
+ default: return unknown_input->getTrace(); break;
+ }
+}
+
+
+void MidiInPort_linux::insert(const MidiMessage& aMessage) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->insert(aMessage); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->insert(aMessage); break;
+ default: unknown_input->insert(aMessage); break;
+ }
+}
+
+
+int MidiInPort_linux::installSysex(uchar* anArray, int aSize) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT:
+ return oss_input->installSysex(anArray, aSize);
+ break;
+ case MIDI_IN_ALSA_SELECT:
+ return alsa_input->installSysex(anArray, aSize);
+ break;
+ default:
+ return unknown_input->installSysex(anArray, aSize);
+ break;
+ }
+}
+
+
+MidiMessage& MidiInPort_linux::message(int index) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->message(index); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->message(index); break;
+ default: return unknown_input->message(index); break;
+ }
+}
+
+int MidiInPort_linux::open(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->open(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->open(); break;
+ default: return unknown_input->open(); break;
+ }
+}
+
+
+MidiMessage& MidiInPort_linux::operator[](int index) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->message(index); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->message(index); break;
+ default: return unknown_input->message(index); break;
+ }
+}
+
+
+void MidiInPort_linux::pause(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->pause(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->pause(); break;
+ default: unknown_input->pause(); break;
+ }
+}
+
+
+void MidiInPort_linux::setBufferSize(int aSize) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->setBufferSize(aSize); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->setBufferSize(aSize); break;
+ default: unknown_input->setBufferSize(aSize); break;
+ }
+}
+
+
+void MidiInPort_linux::setChannelOffset(int anOffset) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->setChannelOffset(anOffset); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->setChannelOffset(anOffset); break;
+ default: unknown_input->setChannelOffset(anOffset); break;
+ }
+}
+
+
+void MidiInPort_linux::setAndOpenPort(int aPort) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT:
+ oss_input->setPort(aPort);
+ oss_input->open();
+ break;
+ case MIDI_IN_ALSA_SELECT:
+ alsa_input->setPort(aPort);
+ alsa_input->open();
+ break;
+ default:
+ unknown_input->setPort(aPort);
+ unknown_input->open();
+ break;
+ }
+}
+
+
+void MidiInPort_linux::setPort(int aPort) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->setPort(aPort); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->setPort(aPort); break;
+ default: unknown_input->setPort(aPort); break;
+ }
+}
+
+
+int MidiInPort_linux::setTrace(int aState) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->setTrace(aState); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->setTrace(aState); break;
+ default: return unknown_input->setTrace(aState); break;
+ }
+}
+
+
+void MidiInPort_linux::toggleTrace(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->toggleTrace(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->toggleTrace(); break;
+ default: unknown_input->toggleTrace(); break;
+ }
+}
+
+
+void MidiInPort_linux::unpause(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->unpause(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->unpause(); break;
+ default: unknown_input->unpause(); break;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_linux::getSelect -- return the type of MIDI which
+// is being used to send MIDI output.
+//
+
+int MidiInPort_linux::getSelect(void) {
+ return current;
+}
+
+
+//////////////////////////////
+//
+// MidiInPort_linux::selectOSS -- select the OSS MIDI output
+// returns 1 if OSS is available, otherwise returns 0.
+//
+
+int MidiInPort_linux::selectOSS(void) {
+ if (ossQ) {
+ current = MIDI_IN_OSS_SELECT;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_linux::selectALSA -- select the ALSA MIDI output
+// returns 1 if ALSA is available, otherwise returns 0.
+//
+
+int MidiInPort_linux::selectALSA(void) {
+ if (alsaQ) {
+ current = MIDI_IN_ALSA_SELECT;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_linux::selectUnknown -- select the Unknown MIDI output
+// returns 1 always.
+//
+
+int MidiInPort_linux::selectUnknown(void) {
+ current = MIDI_IN_UNKNOWN_SELECT;
+ return 1;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Private Functions
+//
+
+//////////////////////////////
+//
+// MidiInPort_linux::determineDrivers -- see if OSS/ALSA are
+// available. If /dev/sequencer is present, assume that OSS is
+// available. If /dev/snd/sdq is present, assume that ALSA is
+// available.
+//
+
+void MidiInPort_linux::determineDrivers(void) {
+ struct stat filestats;
+ int status;
+ status = stat("/dev/sequencer", &filestats);
+
+ if (status != 0) {
+ ossQ = 0;
+ } else {
+ ossQ = 1;
+ }
+
+ status = stat("/dev/snd/seq", &filestats);
+
+ if (status != 0) {
+ alsaQ = 0;
+ } else {
+ alsaQ = 1;
+ }
+
+
+ current = MIDI_IN_UNKNOWN_SELECT;
+
+ if (ossQ) {
+ current = MIDI_IN_OSS_SELECT;
+ }
+
+ if (alsaQ) {
+ current = MIDI_IN_ALSA_SELECT;
+ }
+
+ // create MIDI output types which are available:
+
+ if (oss_input != NULL) {
+ delete oss_input;
+ oss_input = NULL;
+ }
+ if (alsa_input != NULL) {
+ delete alsa_input;
+ alsa_input = NULL;
+ }
+ if (unknown_input != NULL) {
+ delete unknown_input;
+ unknown_input = NULL;
+ }
+
+ if (ossQ) {
+ oss_input = new MidiInPort_oss;
+ }
+ if (alsaQ) {
+ alsa_input = new MidiInPort_alsa;
+ }
+
+ unknown_input = new MidiInPort_unsupported;
+
+}
+
+
+#endif /* ALSA and OSS */
+#endif /* LINUX */
+
+
+// md5sum: d634dd5c3b7e8c4d75b99d7459c3f073 - MidiInPort_linux.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_oss.cpp b/src/midiio/src/MidiInPort_oss.cpp
new file mode 100644
index 0000000..d16c865
--- /dev/null
+++ b/src/midiio/src/MidiInPort_oss.cpp
@@ -0,0 +1,1036 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Jan 21 22:46:30 GMT-0800 1998
+// Last Modified: Sat Jan 9 06:05:24 PST 1999
+// Last Modified: Tue Jun 29 16:18:45 PDT 1999 (added sysex capability)
+// Last Modified: Mon Dec 6 16:28:45 PST 1999
+// Last Modified: Wed Jan 12 10:59:33 PST 2000 (orphan 0xf0 behavior change)
+// Last Modified: Wed May 10 17:10:05 PDT 2000 (name change from _linux to _oss)
+// Last Modified: Fri Oct 26 14:41:36 PDT 2001 (running status for 0xa0 and 0xd0
+// fixed by Daniel Gardner)
+// Filename: ...sig/code/control/MidiInPort/linux/MidiInPort_oss.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiInPort_oss.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux OSS sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#ifdef LINUX
+
+#include "MidiInPort_oss.h"
+#include <iostream>
+#include <stdlib.h>
+#include <pthread.h>
+#include <linux/soundcard.h>
+
+
+#define DEFAULT_INPUT_BUFFER_SIZE (1024)
+
+// initialized static variables
+
+int MidiInPort_oss::numDevices = 0;
+int MidiInPort_oss::objectCount = 0;
+int* MidiInPort_oss::portObjectCount = NULL;
+CircularBuffer<MidiMessage>** MidiInPort_oss::midiBuffer = NULL;
+int MidiInPort_oss::channelOffset = 0;
+SigTimer MidiInPort_oss::midiTimer;
+int* MidiInPort_oss::pauseQ = NULL;
+int* MidiInPort_oss::trace = NULL;
+std::ostream* MidiInPort_oss::tracedisplay = &std::cout;
+pthread_t MidiInPort_oss::midiInThread;
+int* MidiInPort_oss::sysexWriteBuffer = NULL;
+Array<uchar>** MidiInPort_oss::sysexBuffers = NULL;
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::MidiInPort_oss
+// default values: autoOpen = 1
+//
+
+MidiInPort_oss::MidiInPort_oss(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiInPort_oss::MidiInPort_oss(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::~MidiInPort_oss
+//
+
+MidiInPort_oss::~MidiInPort_oss() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cerr << "Error: bad MidiInPort_oss object count!: "
+ << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::clearSysex -- clears the data from a sysex
+// message and sets the allocation size to the default size (of 32
+// bytes).
+//
+
+void MidiInPort_oss::clearSysex(int buffer) {
+ buffer = 0x7f | buffer; // limit buffer range from 0 to 127
+ if (getPort() == -1) {
+ return;
+ }
+
+ sysexBuffers[getPort()][buffer].setSize(0);
+ if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) {
+ // shrink the storage buffer's size if necessary
+ sysexBuffers[getPort()][buffer].setAllocSize(32);
+ }
+}
+
+
+void MidiInPort_oss::clearSysex(void) {
+ // clear all sysex buffers
+ for (int i=0; i<128; i++) {
+ clearSysex(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::close
+//
+
+void MidiInPort_oss::close(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::closeAll --
+//
+
+void MidiInPort_oss::closeAll(void) {
+ Sequencer_oss::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::extract -- returns the next MIDI message
+// received since that last extracted message.
+//
+
+MidiMessage MidiInPort_oss::extract(void) {
+ if (getPort() == -1) {
+ MidiMessage temp;
+ return temp;
+ }
+
+ return midiBuffer[getPort()]->extract();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getBufferSize -- returns the maximum possible number
+// of MIDI messages that can be stored in the buffer
+//
+
+int MidiInPort_oss::getBufferSize(void) {
+ if (getPort() == -1) return 0;
+
+ return midiBuffer[getPort()]->getSize();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiInPort_oss::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getCount -- returns the number of unexamined
+// MIDI messages waiting in the input buffer.
+//
+
+int MidiInPort_oss::getCount(void) {
+ if (getPort() == -1) return 0;
+
+ return midiBuffer[getPort()]->getCount();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until all instances
+// of MIDI classes are.
+//
+
+const char* MidiInPort_oss::getName(void) {
+ if (getPort() == -1) {
+ return "Null OSS MIDI Input";
+ }
+ return getInputName(getPort());
+}
+
+
+const char* MidiInPort_oss::getName(int i) {
+ return getInputName(i);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getNumPorts -- returns the number of available
+// ports for MIDI input
+//
+
+int MidiInPort_oss::getNumPorts(void) {
+ return getNumInputs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiInPort_oss::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiInPort_oss::getPortStatus(void) {
+ return is_open();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getSysex -- returns the sysex message contents
+// of a given buffer. You should check to see that the size is
+// non-zero before looking at the data. The data pointer will
+// be NULL if there is no data in the buffer.
+//
+
+uchar* MidiInPort_oss::getSysex(int buffer) {
+ buffer &= 0x7f; // limit the buffer access to indices 0 to 127.
+
+ if (getPort() == -1) {
+ return NULL;
+ }
+
+ if (sysexBuffers[getPort()][buffer].getSize() < 2) {
+ return NULL;
+ } else {
+ return sysexBuffers[getPort()][buffer].getBase();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getSysexSize -- returns the sysex message byte
+// count of a given buffer. Buffers are in the range from
+// 0 to 127.
+//
+
+int MidiInPort_oss::getSysexSize(int buffer) {
+ if (getPort() == -1) {
+ return 0;
+ } else {
+ return sysexBuffers[getPort()][buffer & 0x7f].getSize();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getTrace -- returns true if trace is on or false
+// if trace is off. if trace is on, then prints to standard
+// output the Midi message received.
+//
+
+int MidiInPort_oss::getTrace(void) {
+ if (getPort() == -1) return -1;
+
+ return trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::insert
+//
+
+void MidiInPort_oss::insert(const MidiMessage& aMessage) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->insert(aMessage);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::installSysex -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_oss::installSysex(uchar* anArray, int aSize) {
+ if (getPort() == -1) {
+ return -1;
+ } else {
+ return installSysexPrivate(getPort(), anArray, aSize);
+ }
+}
+
+//////////////////////////////
+//
+// MidiInPort_oss::installSysexPrivate -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_oss::installSysexPrivate(int port, uchar* anArray, int aSize) {
+ // choose a buffer to install sysex data into:
+ int bufferNumber = sysexWriteBuffer[port];
+ sysexWriteBuffer[port]++;
+ if (sysexWriteBuffer[port] >= 128) {
+ sysexWriteBuffer[port] = 0;
+ }
+
+ // copy contents of sysex message into the chosen buffer
+ sysexBuffers[port][bufferNumber].setSize(aSize);
+ uchar* dataptr = sysexBuffers[port][bufferNumber].getBase();
+ uchar* indataptr = anArray;
+ for (int i=0; i<aSize; i++) {
+ *dataptr = *indataptr;
+ dataptr++;
+ indataptr++;
+ }
+
+ // return the buffer number that was used
+ return bufferNumber;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::message
+//
+
+MidiMessage& MidiInPort_oss::message(int index) {
+ if (getPort() == -1) {
+ static MidiMessage x;
+ return x;
+ }
+
+ CircularBuffer<MidiMessage>& temp = *midiBuffer[getPort()];
+ return temp[index];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::open -- returns true if MIDI input port was
+// opened.
+//
+
+int MidiInPort_oss::open(void) {
+ if (getPort() == -1) return 0;
+
+ return Sequencer_oss::open();
+ pauseQ[getPort()] = 0;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::pause -- stop the Midi input port from
+// inserting MIDI messages into the buffer, but keeps the
+// port open. Use unpause() to reverse the effect of pause().
+//
+
+void MidiInPort_oss::pause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::setBufferSize -- sets the allocation
+// size of the MIDI input buffer.
+//
+
+void MidiInPort_oss::setBufferSize(int aSize) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->setSize(aSize);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::setChannelOffset -- sets the MIDI chan offset,
+// either 0 or 1.
+//
+
+void MidiInPort_oss::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::setPort
+//
+
+void MidiInPort_oss::setPort(int aPort) {
+// if (aPort == -1) return;
+ if (aPort < -1 || aPort >= getNumPorts()) {
+// std::cerr << "Error: maximum port number is: " << getNumPorts()-1
+// << ", but you tried to access port: " << aPort << std::endl;
+// exit(1);
+ }
+ else {
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::setTrace -- if false, then don't print MIDI messages
+// to the screen.
+//
+
+int MidiInPort_oss::setTrace(int aState) {
+ if (getPort() == -1) return -1;
+
+
+ int oldtrace = trace[getPort()];
+ if (aState == 0) {
+ trace[getPort()] = 0;
+ } else {
+ trace[getPort()] = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::toggleTrace -- switches the state of trace
+// Returns the previous value of the trace variable.
+//
+
+void MidiInPort_oss::toggleTrace(void) {
+ if (getPort() == -1) return;
+
+ trace[getPort()] = !trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::unpause -- enables the Midi input port
+// to inserting MIDI messages into the buffer after the
+// port is already open.
+//
+
+void MidiInPort_oss::unpause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 0;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_oss::deinitialize(void) {
+ closeAll();
+
+ for (int i=0; i<getNumPorts(); i++) {
+ if (sysexBuffers != NULL && sysexBuffers[i] != NULL) {
+ delete [] sysexBuffers[i];
+ sysexBuffers[i] = NULL;
+ }
+ }
+
+ if (sysexBuffers != NULL) {
+ delete [] sysexBuffers;
+ sysexBuffers = NULL;
+ }
+
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ midiBuffer = NULL;
+ }
+
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ portObjectCount = NULL;
+ }
+
+ if (trace != NULL) {
+ delete [] trace;
+ trace = NULL;
+ }
+
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ pauseQ = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_oss::initialize(void) {
+ // set the number of ports
+ numDevices = Sequencer_oss::indevcount;
+
+ if (getNumPorts() <= 0) {
+// std::cerr << "Warning: no MIDI input devices" << std::endl;
+ } else {
+
+ // allocate space for pauseQ, the port pause status
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ }
+ pauseQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ }
+ portObjectCount = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (trace != NULL) {
+ delete [] trace;
+ }
+ trace = new int[numDevices];
+
+ // allocate space for the Midi input buffers
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ }
+ midiBuffer = new CircularBuffer<MidiMessage>*[numDevices];
+
+ // allocate space for Midi input sysex buffer write indices
+ if (sysexWriteBuffer != NULL) {
+ delete [] sysexWriteBuffer;
+ }
+ sysexWriteBuffer = new int[numDevices];
+
+ // allocate space for Midi input sysex buffers
+ if (sysexBuffers != NULL) {
+ std::cout << "Error: memory leak on sysex buffers initialization" << std::endl;
+ exit(1);
+ }
+ sysexBuffers = new Array<uchar>*[numDevices];
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ portObjectCount[i] = 0;
+ trace[i] = 0;
+ pauseQ[i] = 0;
+ midiBuffer[i] = new CircularBuffer<MidiMessage>;
+ midiBuffer[i]->setSize(DEFAULT_INPUT_BUFFER_SIZE);
+
+ sysexWriteBuffer[i] = 0;
+ sysexBuffers[i] = new Array<uchar>[128];
+ for (int n=0; n<128; n++) {
+ sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow
+ sysexBuffers[i][n].setAllocSize(32);
+ sysexBuffers[i][n].setSize(0);
+ sysexBuffers[i][n].setGrowth(32); // in case it will ever grow
+ }
+ }
+
+ int flag = pthread_create(&midiInThread, NULL,
+ interpretMidiInputStreamPrivate, NULL);
+ if (flag == -1) {
+ std::cout << "Unable to create MIDI input thread." << std::endl;
+ exit(1);
+ }
+
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// friendly functions
+//
+
+
+//////////////////////////////
+//
+// interpretMidiInputStreamPrivate -- handles the MIDI input stream
+// for the various input devices.
+//
+// Note about system exclusive messages:
+// System Exclusive messages are stored in a separate buffer from
+// Other Midi messages since they can be variable in length. If
+// The Midi Input returns a message with command byte 0xf0, then
+// the p1() byte indicates the system exclusive buffer number that is
+// holding the system exclusive data for that Midi message. There
+// are 128 system exclusive buffers that are numbered between
+// 0 and 127. These buffers are filled in a cycle.
+// To extract a System exclusive message from MidiInPort_oss,
+// you first will receive a Message with a command byte of 0xf0.
+// you can then access the data for that sysex by the command:
+// MidiInPort_oss::getSysex(buffer_number), this will return
+// a pointer to the beginning of the sysex data. The first byte
+// of the sysex data should be 0xf0, and the last byte of the data
+// is 0xf7. All other bytes of data should be in the range from
+// 0 to 127. You can also get the size of the sysex buffer by the
+// following command: MidiInPort_oss::getSysexSize(buffer_number).
+// This command will tell you the number of bytes in the system
+// exclusive message including the starting 0xf0 and the ending 0xf7.
+//
+// If you want to minimize memory useage of the system exclusive
+// buffers you can run the command:
+// MidiInPort_oss::clearSysex(buffer_number); Otherwise the sysex
+// buffer will be erased automatically the next time that the that
+// buffer number is cycled through when receiving more system exclusives.
+// Allocated the allocated size of the system exclusive storage will
+// not be adjusted when the computer replaces the system exclusive
+// message unless more storage size is needed, clearSysex however,
+// will resize the sysex buffer to its default size (currently 32 bytes).
+// clearSysex() without arguments will resize all buffers so that
+// they are allocated to the default size and will erase data from
+// all buffers. You can spoof a system exclusive message coming in
+// by installing a system exclusive message and then inserting
+// the system message command into the input buffer of the MidiInPort
+// class, int sysex_buffer = MidiInPort_oss::installSysex(
+// uchar *data, int size); will put the data into a sysex buffer and
+// return the buffer number that it was placed into.
+//
+// This function assumes that System Exclusive messages cannot be sent
+// as a running status messages.
+//
+// Note about MidiMessage time stamps:
+// The MidiMessage::time field is a recording of the time that the
+// first byte of the MidiMessage arrived. If the message is from
+// running status mode, then the time that the first parameter byte
+// arrived is stored. System exclusive message arrival times are
+// recoreded at the time of the last byte (0xf7) arriving. This is
+// because other system messages can be coming in while the sysex
+// message is coming in. Anyway, sysex messages are not really to
+// be used for real time MIDI messaging, so the exact moment that the
+// first byte of the sysex came in is not important to me.
+//
+//
+
+void *interpretMidiInputStreamPrivate(void *) {
+
+ int* argsExpected = NULL; // MIDI parameter bytes expected to follow
+ int* argsLeft = NULL; // MIDI parameter bytes left to wait for
+ uchar packet[4]; // bytes for sequencer driver
+ MidiMessage* message = NULL; // holder for current MIDI message
+ int newSigTime = 0; // for millisecond timer
+ int lastSigTime = -1; // for millisecond timer
+ int zeroSigTime = -1; // for timing incoming events
+ int device = -1; // for sorting out the bytes by input device
+ Array<uchar>* sysexIn; // MIDI Input sysex temporary storage
+
+ // Note on the use of argsExpected and argsLeft for sysexs:
+ // If argsExpected is -1, then a sysex message is coming in.
+ // If argsLeft < 0, then the sysex message has not finished comming
+ // in. If argsLeft == 0 and argsExpected == -1, then the sysex
+ // has finished coming in and is to be sent to the correct
+ // location.
+
+ static int count = 0;
+ if (count != 0) {
+ std::cerr << "Cannot run this function more than once" << std::endl;
+ exit(1);
+ } else {
+ // allocate space for MIDI messages, each device has a different message
+ // holding spot in case the messages overlap in the input stream
+ message = new MidiMessage[MidiInPort_oss::numDevices];
+ argsExpected = new int[MidiInPort_oss::numDevices];
+ argsLeft = new int[MidiInPort_oss::numDevices];
+
+ sysexIn = new Array<uchar>[MidiInPort_oss::numDevices];
+ for (int j=0; j<MidiInPort_oss::numDevices; j++) {
+ sysexIn[j].allowGrowth();
+ sysexIn[j].setSize(32);
+ sysexIn[j].setSize(0);
+ sysexIn[j].setGrowth(512);
+ }
+
+ count++;
+ }
+
+ // interpret MIDI bytes as they come into the computer
+ // and repackage them as MIDI messages.
+ int packetReadCount;
+ while (1) {
+top_of_loop:
+ packetReadCount = ::read(MidiInPort_oss::sequencer_fd,
+ &packet, sizeof(packet));
+
+ if (packetReadCount != 4) {
+ // this if statement is used to prevent cases where the
+ // read function above will time out and return 0 bytes
+ // read. This if statment will also take care of -1
+ // error return values by ignoring them.
+ continue;
+ }
+
+
+/*
+ std::cout << "packet bytes "
+ << " 0x" << std::hex << (int)packet[0] // packet type
+ << " 0x" << std::hex << (int)packet[1] // possible MIDI byte
+ << " 0x" << std::hex << (int)packet[2] // device number
+ << " 0x" << std::hex << (int)packet[3] // unused for MIDI bytes
+ << std::endl;
+*/
+
+ switch (packet[0]) {
+ case SEQ_WAIT:
+ // MIDI clock ticks ... the first MIDI message deltaTime is
+ // calculated wrt the start of the MIDI clock.
+ if (zeroSigTime < 0) {
+ zeroSigTime = MidiInPort_oss::midiTimer.getTime();
+ }
+/*
+ int newTime;
+ newTime = packet[3];
+ newTime = (newTime << 8) | packet[2];
+ newTime = (newTime << 8) | packet[1];
+*/
+ break;
+
+ case SEQ_ECHO:
+ // echo events
+ break;
+
+ case SEQ_MIDIPUTC: // SEQ_MIDIPUTC = 5
+ // determination of a full MIDI message from the input MIDI
+ // stream is based here on the observation that MIDI status
+ // bytes and subsequent data bytes are NOT returned in the same
+ // read() call. Rather, they are spread out over multiple read()
+ // returns, with only a single value per return. So if we
+ // find a status byte, we then determine the number of expected
+ // operands and process that number of subsequent read()s to
+ // to determine the complete midi message.
+
+/*
+ std::cout << "MIDI byte: " << (int)packet[1] << std::endl;
+*/
+
+ // store the MIDI input device to which the incoming MIDI
+ // byte belongs.
+ device = packet[2];
+
+ // ignore the active sensing 0xfe and MIDI clock 0xf8 commands:
+ if (packet[1] == 0xfe || packet[1] == 0xf8) {
+ break;
+ }
+
+ if (packet[1] & 0x80) { // a command byte has arrived
+ switch (packet[1] & 0xf0) {
+ case 0xf0:
+ if (packet[1] == 0xf0) {
+ argsExpected[device] = -1;
+ argsLeft[device] = -1;
+ if (sysexIn[device].getSize() != 0) {
+ // ignore the command for now. It is most
+ // likely an active sensing message.
+ goto top_of_loop;
+ } else {
+ uchar datum = 0xf0;
+ sysexIn[device].append(datum);
+ }
+ } if (packet[1] == 0xf7) {
+ argsLeft[device] = 0; // indicates sysex is done
+ uchar datum = 0xf7;
+ sysexIn[device].append(datum);
+ } else if (argsExpected[device] != -1) {
+ // this is a system message that may or may
+ // not be coming while a sysex is coming in
+ argsExpected[device] = 0;
+ } else {
+ // this is a system message that is not coming
+ // while a system exclusive is coming in
+ //argsExpected[device] = 0;
+ }
+ break;
+ case 0xc0:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received program change during sysex"
+ << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ case 0xd0:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received aftertouch message during"
+ " sysex" << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ default:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received another message during sysex"
+ << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 2;
+ }
+ break;
+ }
+ if (argsExpected[device] >= 0) {
+ argsLeft[device] = argsExpected[device];
+ }
+
+ newSigTime = MidiInPort_oss::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+
+ if (packet[1] != 0xf7) {
+ message[device].p0() = packet[1];
+ }
+ message[device].p1() = 0;
+ message[device].p2() = 0;
+ message[device].p3() = 0;
+
+ if (packet[1] == 0xf7) {
+ goto sysex_done;
+ }
+ } else if (argsLeft[device]) { // not a command byte coming in
+ if (message[device].time == 0) {
+ // store the receipt time of the first message byte
+ newSigTime = MidiInPort_oss::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+ }
+
+ if (argsExpected[device] < 0) {
+ // continue processing a sysex message
+ sysexIn[device].append(packet[1]);
+ } else {
+ // handle a message other than a sysex message
+ if (argsLeft[device] == argsExpected[device]) {
+ message[device].p1() = packet[1];
+ } else {
+ message[device].p2() = packet[1];
+ }
+ argsLeft[device]--;
+ }
+
+ // if MIDI message is complete, setup for running status, and
+ // insert note into proper buffer.
+
+ if (argsExpected[device] >= 0 && !argsLeft[device]) {
+
+ // store parameter data for running status
+ switch (message[device].p0() & 0xf0) {
+ case 0xc0: argsLeft[device] = 1; break;
+ case 0xd0: argsLeft[device] = 1; break; // fix by dan
+ default: argsLeft[device] = 2; break;
+ // 0x80 expects two arguments
+ // 0x90 expects two arguments
+ // 0xa0 expects two arguments
+ // 0xb0 expects two arguments
+ // 0xe0 expects two arguments
+ }
+
+ lastSigTime = newSigTime;
+
+ sysex_done: // come here when a sysex is completely done
+
+ // insert the MIDI message into the appropriate buffer
+ // do not insert into buffer if the MIDI input device
+ // is paused (which can mean closed). Or if the
+ // pauseQ array is pointing to NULL (which probably means that
+ // things are about to shut down).
+ if (MidiInPort_oss::pauseQ != NULL &&
+ MidiInPort_oss::pauseQ[device] == 0) {
+ if (argsExpected[device] < 0) {
+ // store the sysex in the MidiInPort_oss
+ // buffer for sysexs and return the storage
+ // location:
+ int sysexlocation =
+ MidiInPort_oss::installSysexPrivate(device,
+ sysexIn[device].getBase(),
+ sysexIn[device].getSize());
+
+ message[device].p0() = 0xf0;
+ message[device].p1() = sysexlocation;
+
+ sysexIn[device].setSize(0); // empty the sysex storage
+ argsExpected[device] = 0; // no run status for sysex
+ argsLeft[device] = 0; // turn off sysex input flag
+ }
+ MidiInPort_oss::midiBuffer[device]->insert(
+ message[device]);
+// if (MidiInPort_oss::callbackFunction != NULL) {
+// MidiInPort_oss::callbackFunction(device);
+// }
+ if (MidiInPort_oss::trace[device]) {
+ std::cout << '[' << std::hex << (int)message[device].p0()
+ << ':' << std::dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << std::flush;
+ }
+ message[device].time = 0;
+ } else {
+ if (MidiInPort_oss::trace[device]) {
+ std::cout << '[' << std::hex << (int)message[device].p0()
+ << 'P' << std::dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << std::flush;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ } // end switch
+ } // end while (1)
+
+ // This code is not yet reached, but should be made to do so eventually
+
+ if (message != NULL) {
+ delete message;
+ message = NULL;
+ }
+
+ if (argsExpected != NULL) {
+ delete argsExpected;
+ argsExpected = NULL;
+ }
+
+ if (argsLeft != NULL) {
+ delete argsLeft;
+ argsLeft = NULL;
+ }
+
+ if (sysexIn != NULL) {
+ delete sysexIn;
+ sysexIn = NULL;
+ }
+
+}
+
+
+
+#endif // LINUX
+
+
+
+// md5sum: 2008f4a298bef0cd85620a5507815866 - MidiInPort_oss.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_unsupported.cpp b/src/midiio/src/MidiInPort_unsupported.cpp
new file mode 100644
index 0000000..584a468
--- /dev/null
+++ b/src/midiio/src/MidiInPort_unsupported.cpp
@@ -0,0 +1,487 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Jan 21 22:46:30 GMT-0800 1998
+// Last Modified: Thu Jan 22 22:53:53 GMT-0800 1998
+// Last Modified: Wed Jun 30 11:42:59 PDT 1999 (added sysex capability)
+// Filename: ...sig/code/control/MidiInPort/unsupported/MidiInPort_unsupported.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiInPort_unsupported.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// an unknown sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+// This class is used when there is no MIDI input, so
+// that MIDI programs can otherwise be compiled and run.
+// This file can also serve as a template for creating
+// an OS specific class for MIDI input.
+//
+
+#include "MidiInPort_unsupported.h"
+#include <iostream>
+#include <stdlib.h>
+
+
+#define DEFAULT_INPUT_BUFFER_SIZE (1024)
+
+// initialized static variables
+int MidiInPort_unsupported::numDevices = 0;
+int MidiInPort_unsupported::objectCount = 0;
+int* MidiInPort_unsupported::openQ = NULL;
+int* MidiInPort_unsupported::portObjectCount = NULL;
+CircularBuffer<MidiMessage>* MidiInPort_unsupported::midiBuffer = NULL;
+int MidiInPort_unsupported::channelOffset = 0;
+int* MidiInPort_unsupported::sysexWriteBuffer = NULL;
+Array<uchar>** MidiInPort_unsupported::sysexBuffers = NULL;
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::MidiInPort_unsupported
+// default values: autoOpen = 1
+//
+
+MidiInPort_unsupported::MidiInPort_unsupported(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiInPort_unsupported::MidiInPort_unsupported(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::~MidiInPort_unsupported
+//
+
+MidiInPort_unsupported::~MidiInPort_unsupported() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cerr << "Error: bad MidiInPort_unsupported object count!: "
+ << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::close
+//
+
+void MidiInPort_unsupported::close(void) {
+ if (getPortStatus() == 1) {
+ openQ[getPort()] = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::closeAll
+//
+
+void MidiInPort_unsupported::closeAll(void) {
+ for (int i=0; i<getNumPorts(); i++) {
+ if (openQ[i] == 1) {
+ openQ[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::extract -- returns the next MIDI message
+// received since that last extracted message.
+//
+
+MidiMessage MidiInPort_unsupported::extract(void) {
+ return midiBuffer[getPort()].extract();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiInPort_unsupported::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getCount -- returns the number of unexamined
+// MIDI messages waiting in the input buffer.
+//
+
+int MidiInPort_unsupported::getCount(void) {
+ return midiBuffer[getPort()].getCount();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiInPort_unsupported::getName(void) {
+ return "none";
+}
+
+const char* MidiInPort_unsupported::getName(int i) {
+ return "none";
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getNumPorts -- returns the number of available
+// ports for MIDI input
+//
+
+int MidiInPort_unsupported::getNumPorts(void) {
+ return numDevices;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiInPort_unsupported::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiInPort_unsupported::getPortStatus(void) {
+ if (openQ[getPort()] == 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getTrace -- returns true if trace is on or false
+// if trace is off. if trace is on, then prints to standard
+// output the Midi message received.
+//
+
+int MidiInPort_unsupported::getTrace(void) {
+ return trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::insert
+//
+
+void MidiInPort_unsupported::insert(const MidiMessage& aMessage) {
+ midiBuffer[getPort()].insert(aMessage);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::message
+//
+
+MidiMessage& MidiInPort_unsupported::message(int index) {
+ return midiBuffer[getPort()][index];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::open -- returns true if MIDI input port was
+// opened.
+//
+
+int MidiInPort_unsupported::open(void) {
+ if (getPortStatus() == 0) {
+ openQ[getPort()] = 1;
+ }
+ return openQ[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::pause -- stop the Midi input port from
+// inserting MIDI messages into the buffer, but keep the
+// port open. Use unpause() to reverse the effect of pause().
+//
+
+void MidiInPort_unsupported::pause(void) {
+ // nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::setBufferSize -- sets the allocation
+// size of the MIDI input buffer.
+//
+
+void MidiInPort_unsupported::setBufferSize(int aSize) {
+ midiBuffer[getPort()].setSize(aSize);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::setChannelOffset -- sets the MIDI channel offset, either 0 or 1.
+//
+
+void MidiInPort_unsupported::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::setPort
+//
+
+void MidiInPort_unsupported::setPort(int aPort) {
+ if (aPort < 0 || aPort >= getNumPorts()) {
+ std::cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << std::endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ portObjectCount[port]++;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::setTrace -- if false, then don't print MIDI messages
+// to the screen.
+//
+
+int MidiInPort_unsupported::setTrace(int aState) {
+ int oldtrace = trace;
+ if (aState == 0) {
+ trace = 0;
+ } else {
+ trace = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::toggleTrace -- switches the state of trace
+// Returns the previous value of the trace variable.
+//
+
+void MidiInPort_unsupported::toggleTrace(void) {
+ trace = !trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::unpause -- enables the Midi input port
+// to inserting MIDI messages into the buffer after the
+// port is already open.
+//
+
+void MidiInPort_unsupported::unpause(void) {
+ // nothing
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_unsupported::deinitialize(void) {
+ int deviceCount = numDevices;
+ closeAll();
+
+ if (sysexBuffers != NULL) {
+ for (int i=0; i<deviceCount; i++) {
+ if (sysexBuffers[i] != NULL) {
+ delete [] sysexBuffers[i];
+ sysexBuffers[i] = NULL;
+ }
+ }
+ delete [] sysexBuffers;
+ sysexBuffers = NULL;
+ }
+
+ if (sysexWriteBuffer != NULL) {
+ delete [] sysexWriteBuffer;
+ sysexWriteBuffer = NULL;
+ }
+
+ if (openQ != NULL) {
+ delete [] openQ;
+ openQ = NULL;
+ }
+
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ midiBuffer = NULL;
+ }
+
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ portObjectCount = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_unsupported::initialize(void) {
+ // get the number of ports
+ numDevices = 9;
+ if (getNumPorts() <= 0) {
+ std::cerr << "Error: no MIDI input devices" << std::endl;
+ exit(1);
+ }
+
+
+ // allocate space for sysexBuffers, the port open/close status
+ if (sysexBuffers != NULL) {
+ std::cout << "Error: sysexBuffers are not empty, don't know size" << std::endl;
+ exit(1);
+ }
+ sysexBuffers = new Array<uchar>*[numDevices];
+
+ // allocate space for sysexWriteBuffer, the port open/close status
+ if (sysexWriteBuffer != NULL) delete [] sysexWriteBuffer;
+ sysexWriteBuffer = new int[numDevices];
+
+ // allocate space for openQ, the port open/close status
+ if (openQ != NULL) delete [] openQ;
+ openQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+ // allocate space for the Midi input buffers
+ if (midiBuffer != NULL) delete [] midiBuffer;
+ midiBuffer = new CircularBuffer<MidiMessage>[numDevices];
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ openQ[i] = 0;
+ portObjectCount[i] = 0;
+ midiBuffer[i].setSize(DEFAULT_INPUT_BUFFER_SIZE);
+
+ sysexWriteBuffer[i] = 0;
+ sysexBuffers[i] = new Array<uchar>[128];
+ for (int n=0; n<128; n++) {
+ sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow
+ sysexBuffers[i][n].setAllocSize(32);
+ sysexBuffers[i][n].setSize(0);
+ sysexBuffers[i][n].setGrowth(32); // in case it will ever grow
+ }
+
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::setPortStatus
+//
+
+void MidiInPort_unsupported::setPortStatus(int aStatus) {
+ if (aStatus) {
+ openQ[getPort()] = 1;
+ } else {
+ openQ[getPort()] = 0;
+ }
+}
+
+
+// md5sum: d8b8f65af70a9b3c33e62794c2a4a91e - MidiInPort_unsupported.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_visual.cpp b/src/midiio/src/MidiInPort_visual.cpp
new file mode 100644
index 0000000..b4659bf
--- /dev/null
+++ b/src/midiio/src/MidiInPort_visual.cpp
@@ -0,0 +1,1267 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Jan 21 22:46:30 GMT-0800 1998
+// Last Modified: Wed Jun 30 11:29:51 PDT 1999 (added sysex capability)
+// Last Modified: Wed Oct 13 10:18:22 PDT 1999 (midiInUnprepareHeader change)
+// Last Modified: Tue Nov 23 15:01:17 PST 1999 (fixed sysex NULL init)
+// Filename: ...sig/code/control/MidiInPort/visual/MidiInPort_visual.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiInPort_visual.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// Windows 95/NT/98 specific MIDI input methods.
+// as defined in winmm.lib. This class is inherited
+// privately by the MidiInPort class.
+//
+
+#ifdef VISUAL
+
+
+#include "MidiInPort_visual.h"
+
+#include <windows.h>
+#include <mmsystem.h>
+
+#include <iostream.h>
+
+
+// initialized static variables
+int MidiInPort_visual::numDevices = 0;
+int MidiInPort_visual::objectCount = 0;
+int* MidiInPort_visual::openQ = NULL;
+int* MidiInPort_visual::inrunningQ = NULL;
+int* MidiInPort_visual::portObjectCount = NULL;
+HMIDIIN* MidiInPort_visual::device = NULL;
+MIDIHDR** MidiInPort_visual::sysexDriverBuffer1 = NULL;
+MIDIHDR** MidiInPort_visual::sysexDriverBuffer2 = NULL;
+int* MidiInPort_visual::sysexDBnumber = NULL;
+HANDLE* MidiInPort_visual::hMutex = NULL;
+CircularBuffer<MidiMessage>* MidiInPort_visual::midiBuffer = NULL;
+int MidiInPort_visual::channelOffset = 0;
+int* MidiInPort_visual::sysexWriteBuffer = NULL;
+Array<uchar>** MidiInPort_visual::sysexBuffers = NULL;
+int* MidiInPort_visual::sysexStatus = NULL;
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::MidiInPort_visual
+// default values: autoOpen = 1
+//
+
+MidiInPort_visual::MidiInPort_visual(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ trace = 0;
+ port = -1;
+ setPort(0);
+}
+
+
+MidiInPort_visual::MidiInPort_visual(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ trace = 0;
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::~MidiInPort_visual
+//
+
+MidiInPort_visual::~MidiInPort_visual() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ cerr << "Error: bad MidiInPort_visual object count!: "
+ << objectCount << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::clearSysex -- clears the data from a sysex
+// message and sets the allocation size to the default size (of 32
+// bytes).
+//
+
+void MidiInPort_visual::clearSysex(int buffer) {
+ buffer = 0x7f | buffer; // limit buffer range from 0 to 127
+
+ if (getPort() == -1) {
+ return;
+ }
+
+ sysexBuffers[getPort()][buffer].setSize(0);
+ if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) {
+ // shrink the storage buffer's size if necessary
+ sysexBuffers[getPort()][buffer].setAllocSize(32);
+ }
+}
+
+
+void MidiInPort_visual::clearSysex(void) {
+ // clear all sysex buffers
+ for (int i=0; i<128; i++) {
+ clearSysex(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::close
+//
+
+void MidiInPort_visual::close(void) {
+ if (getPort() == -1) {
+ return;
+ }
+ if (getPortStatus() == 1 && device[getPort()] != NULL) {
+ midiInReset(device[getPort()]);
+ midiInClose(device[getPort()]);
+ uninstallSysexStuff(device[getPort()], port);
+ openQ[getPort()] = 0;
+ inrunningQ[getPort()] = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::closeAll
+//
+
+void MidiInPort_visual::closeAll(void) {
+ for (int i=0; i<getNumPorts(); i++) {
+ if (openQ[i] == 1 && device[i] != NULL) {
+ midiInReset(device[i]);
+ midiInClose(device[i]);
+ if (getPort() != 1) {
+ uninstallSysexStuff(device[getPort()], port);
+ }
+ openQ[i] = 0;
+ inrunningQ[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::extract -- returns the next MIDI message
+// received since that last extracted message.
+//
+
+MidiMessage MidiInPort_visual::extract(void) {
+ MidiMessage output;
+
+ waitForMutex();
+ if (getPort() != -1) {
+ output = midiBuffer[getPort()].extract();
+ }
+ releaseMutex();
+
+ return output;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getBufferSize
+//
+
+int MidiInPort_visual::getBufferSize(void) {
+ if (getPort() != -1) {
+ return midiBuffer[getPort()].getSize();
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiInPort_visual::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getCount -- returns the number of unexamined
+// MIDI messages waiting in the input buffer.
+//
+
+int MidiInPort_visual::getCount(void) {
+ int output;
+
+ waitForMutex();
+ if (getPort() != -1) {
+ output = midiBuffer[getPort()].getCount();
+ } else {
+ output = 0;
+ }
+ releaseMutex();
+
+ return output;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiInPort_visual::getName(void) {
+ static MIDIINCAPS inputCapabilities;
+
+ if (getPort() == -1) {
+ return "Null MIDI Input";
+ }
+
+ if (openQ[getPort()]) { // port already open
+ midiInGetDevCaps(getPort(), &inputCapabilities, sizeof(MIDIINCAPS));
+ } else { // port is currently closed
+ if(open()) {;
+ midiInGetDevCaps(getPort(), &inputCapabilities, sizeof(MIDIINCAPS));
+ close();
+ } else {
+ return "";
+ }
+ }
+ return inputCapabilities.szPname;
+}
+
+
+const char* MidiInPort_visual::getName(int i) {
+ static MIDIINCAPS inputCapabilities;
+
+ if (i < 0 || i > getNumPorts()) {
+ cerr << "Error invalid index for getName: " << i << endl;
+ exit(1);
+ }
+
+ midiInGetDevCaps(i, &inputCapabilities, sizeof(MIDIINCAPS));
+
+ return inputCapabilities.szPname;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getNumPorts -- returns the number of available
+// ports for MIDI input
+//
+
+int MidiInPort_visual::getNumPorts(void) {
+ return midiInGetNumDevs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiInPort_visual::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getPortStatus -- 0 if closed, 1 if open, 2 if
+// specifically not connected to any MIDI port.
+//
+
+int MidiInPort_visual::getPortStatus(void) {
+ if (getPort() == -1) {
+ return 2;
+ }
+
+ if (openQ[getPort()] == 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getSysex -- returns the sysex message contents
+// of a given buffer. You should check to see that the size is
+// non-zero before looking at the data. The data pointer will
+// be NULL if there is no data in the buffer.
+//
+
+uchar* MidiInPort_visual::getSysex(int buffer) {
+ buffer &= 0x7f; // limit the buffer access to indices 0 to 127.
+
+ if (getPort() == -1) {
+ return NULL;
+ }
+
+ if (sysexBuffers[getPort()][buffer].getSize() < 2) {
+ return NULL;
+ } else {
+ return sysexBuffers[getPort()][buffer].getBase();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getSysexSize -- returns the sysex message byte
+// count of a given buffer. Buffers are in the range from
+// 0 to 127.
+//
+
+int MidiInPort_visual::getSysexSize(int buffer) {
+ if (getPort() == -1) {
+ return 0;
+ } else {
+ return sysexBuffers[getPort()][buffer & 0x7f].getSize();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getTrace -- returns true if trace is on or false
+// if trace is off. if trace is on, then prints to standard
+// output the Midi message received.
+//
+
+int MidiInPort_visual::getTrace(void) {
+ return trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::insert
+//
+
+void MidiInPort_visual::insert(const MidiMessage& aMessage) {
+ waitForMutex();
+ if (getPort() == -1) {
+ // do nothing
+ } else {
+ midiBuffer[getPort()].insert(aMessage);
+ }
+ releaseMutex();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::installSysex -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_visual::installSysex(uchar* anArray, int aSize) {
+ return installSysexPrivate(getPort(), anArray, aSize);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::installSysexPrivate -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_visual::installSysexPrivate(int port, uchar* anArray, int aSize){
+ if (port == -1) {
+ return -1;
+ }
+
+ // choose a buffer to install sysex data into:
+ int bufferNumber = sysexWriteBuffer[port];
+ sysexWriteBuffer[port]++;
+ if (sysexWriteBuffer[port] >= 128) {
+ sysexWriteBuffer[port] = 0;
+ }
+
+ // copy contents of sysex message into the chosen buffer
+ sysexBuffers[port][bufferNumber].setSize(aSize);
+ uchar* dataptr = sysexBuffers[port][bufferNumber].getBase();
+ uchar* indataptr = anArray;
+ for (int i=0; i<aSize; i++) {
+ *dataptr = *indataptr;
+ dataptr++;
+ indataptr++;
+ }
+
+ // return the buffer number that was used
+ return bufferNumber;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::message
+//
+
+MidiMessage& MidiInPort_visual::message(int index) {
+ if (getPort() != -1) {
+ return midiBuffer[getPort()][index];
+ } else {
+ static MidiMessage nullmessage;
+ return nullmessage;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::open -- returns true if MIDI input port was
+// opened.
+//
+
+int MidiInPort_visual::open(void) {
+ if (getPort() == -1) {
+ return 1;
+ }
+
+ if (getPortStatus() == 0) {
+ int flag;
+ flag = midiInOpen(&device[getPort()], getPort(),
+ (DWORD)&midiInputCallback, (DWORD)this, CALLBACK_FUNCTION);
+ if (flag == MMSYSERR_NOERROR) {
+ openQ[getPort()] = 1;
+ installSysexStuff(device[getPort()], port);
+ unpause();
+ return 1;
+ } else { // failed to open
+ openQ[getPort()] = 0;
+ device[getPort()] = NULL;
+ return 0;
+ }
+ } else { // already open
+ return 1;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::pause -- stop the Midi input port from
+// inserting MIDI messages into the buffer, but keep the
+// port open. Use unpause() to reverse the effect of pause().
+//
+
+void MidiInPort_visual::pause(void) {
+ if (getPort() == -1) {
+ return;
+ }
+
+ if (openQ[getPort()]) {
+ if (inrunningQ[getPort()] == 1) {
+ midiInStop(device[getPort()]);
+ inrunningQ[getPort()] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::setBufferSize -- sets the allocation
+// size of the MIDI input buffer.
+//
+
+void MidiInPort_visual::setBufferSize(int aSize) {
+ if (getPort() != -1) {
+ midiBuffer[getPort()].setSize(aSize);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::setChannelOffset -- sets the MIDI channel offset, either 0 or 1.
+//
+
+void MidiInPort_visual::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ cout << "Error: Channel offset can be only 0 or 1." << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::setPort --
+//
+
+void MidiInPort_visual::setPort(int aPort) {
+ if (aPort < -1 || aPort >= getNumPorts()) {
+ cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::setTrace -- if false, then don't print MIDI messages
+// to the screen.
+//
+
+int MidiInPort_visual::setTrace(int aState) {
+ int oldtrace = trace;
+ if (aState == 0) {
+ trace = 0;
+ } else {
+ trace = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::toggleTrace -- switches the state of trace
+// Returns the previous value of the trace variable.
+//
+
+void MidiInPort_visual::toggleTrace(void) {
+ trace = !trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::unpause -- enables the Midi input port
+// to inserting MIDI messages into the buffer after the
+// port is already open.
+//
+
+void MidiInPort_visual::unpause(void) {
+ if (getPort() == -1) {
+ return;
+ }
+
+ if (openQ[getPort()]) {
+ if (inrunningQ[getPort()] == 0) {
+ midiInStart(device[getPort()]);
+ inrunningQ[getPort()] = 1;
+ }
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_visual::deinitialize(void) {
+ int num = numDevices;
+
+ closeAll();
+
+ if (sysexBuffers != NULL) {
+ for (int i=0; i<numDevices; i++) {
+ if (sysexBuffers[i] != NULL) {
+ delete sysexBuffers[i];
+ sysexBuffers[i] = NULL;
+ }
+ }
+ delete [] sysexBuffers;
+ sysexBuffers = NULL;
+ }
+
+
+ if (sysexDriverBuffer1 != NULL) {
+ for (int i=0; i<numDevices; i++) {
+ if (sysexDriverBuffer1[i] != NULL) {
+ delete sysexDriverBuffer1[i];
+ sysexDriverBuffer1[i] = NULL;
+ }
+ }
+ delete [] sysexDriverBuffer1;
+ sysexDriverBuffer1 = NULL;
+ }
+
+ if (sysexDriverBuffer2 != NULL) {
+ for (int i=0; i<numDevices; i++) {
+ if (sysexDriverBuffer2[i] != NULL) {
+ delete sysexDriverBuffer2[i];
+ sysexDriverBuffer2[i] = NULL;
+ }
+ }
+ delete [] sysexDriverBuffer2;
+ sysexDriverBuffer2 = NULL;
+ }
+
+ if (sysexDBnumber != NULL) {
+ delete [] sysexDBnumber;
+ sysexDBnumber = NULL;
+ }
+
+
+ if (sysexWriteBuffer != NULL) {
+ delete [] sysexWriteBuffer;
+ sysexWriteBuffer = NULL;
+ }
+
+ if (sysexStatus != NULL) {
+ delete [] sysexStatus;
+ sysexStatus = NULL;
+ }
+
+ if (device != NULL) {
+ delete [] device;
+ device = NULL;
+ }
+
+ if (openQ != NULL) {
+ delete [] openQ;
+ openQ = NULL;
+ }
+
+ if (inrunningQ != NULL) {
+ delete [] inrunningQ;
+ inrunningQ = NULL;
+ }
+
+ if (hMutex != NULL) {
+ delete [] hMutex;
+ hMutex = NULL;
+ }
+
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ midiBuffer = NULL;
+ }
+
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ portObjectCount = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_visual::initialize(void) {
+ int i;
+
+ // get the number of ports
+ numDevices = midiInGetNumDevs();
+ if (getNumPorts() <= 0) {
+ cerr << "Error: no MIDI input devices" << endl;
+ exit(1);
+ }
+
+ // allocate space for Windoze MIDI input structures
+ if (device != NULL) {
+ cerr << "Error: device array should be NULL when calling "
+ << "initialize() in MidiInPort_visual." << endl;
+ exit(1);
+ }
+ device = new HMIDIIN[numDevices];
+
+ // allocate space for openQ, the port open/close status
+ if (openQ != NULL) delete [] openQ;
+ openQ = new int[numDevices];
+
+ // allocate space to keep track of an active/inactive input port
+ if (inrunningQ != NULL) delete [] inrunningQ;
+ inrunningQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+ // allocate space for mutual exclusive
+ if (hMutex != NULL) delete [] hMutex;
+ hMutex = new HANDLE[numDevices];
+
+ // allocate space for the Midi input buffers
+ if (midiBuffer != NULL) delete [] midiBuffer;
+ midiBuffer = new CircularBuffer<MidiMessage>[numDevices];
+
+ // allocate space for the MIDI sysex buffer indices
+ if (sysexWriteBuffer != NULL) delete [] sysexWriteBuffer;
+ sysexWriteBuffer = new int[numDevices];
+
+ // allocate space for the sysex MIM_LONGDATA message tracking
+ if (sysexStatus != NULL) delete [] sysexStatus;
+ sysexStatus = new int[numDevices];
+
+ // allocate space for sysex buffers
+ if (sysexBuffers != NULL) {
+ cout << "Error: memory leak on sysex buffers initialization" << endl;
+ exit(1);
+ }
+ sysexBuffers = new Array<uchar>*[numDevices];
+
+ // allocate system exclusive buffers for MIDI driver
+ if (sysexDriverBuffer1 != NULL) {
+ cout << "Error: memory leak on sysex buffer for drivers creation" << endl;
+ exit(1);
+ }
+ sysexDriverBuffer1 = new MIDIHDR*[numDevices];
+ for (i=0; i<numDevices; i++) {
+ sysexDriverBuffer1[i] = NULL;
+ }
+
+ // allocate system exclusive buffers for MIDI driver
+ if (sysexDriverBuffer2 != NULL) {
+ cout << "Error: memory leak on sysex buffer for drivers creation" << endl;
+ exit(1);
+ }
+ sysexDriverBuffer2 = new MIDIHDR*[numDevices];
+ for (i=0; i<numDevices; i++) {
+ sysexDriverBuffer2[i] = NULL;
+ }
+
+ // allocate space for keeping track of which buffer to look at
+ if (sysexDBnumber != NULL) delete [] sysexDBnumber;
+ sysexDBnumber = new int[numDevices];
+
+
+ // initialize the static arrays
+ for (i=0; i<getNumPorts(); i++) {
+ device[i] = NULL;
+ openQ[i] = 0;
+ inrunningQ[i] = 0;
+ portObjectCount[i] = 0;
+ hMutex[i] = CreateMutex(NULL, FALSE, "M");
+ midiBuffer[i].setSize(DEFAULT_INPUT_BUFFER_SIZE);
+
+ sysexStatus[i] = -1;
+ sysexWriteBuffer[i] = 0;
+ sysexDBnumber[i] = 0;
+ sysexBuffers[i] = new Array<uchar>[128];
+ for (int n=0; n<128; n++) {
+ sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow
+ sysexBuffers[i][n].setAllocSize(32);
+ sysexBuffers[i][n].setSize(0);
+ sysexBuffers[i][n].setGrowth(32); // in case it will ever grow
+ }
+
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::installSysexStuff -- install all the mess that
+// a MIDIIN structure needs in order to receive system exclusives.
+//
+
+void MidiInPort_visual::installSysexStuff(HMIDIIN dev, int port) {
+ if (sysexDriverBuffer1 != NULL) {
+ if (sysexDriverBuffer1[port] != NULL) {
+ // some memory leaks here
+ delete sysexDriverBuffer1[port];
+ sysexDriverBuffer1[port] = NULL;
+ }
+ }
+ if (sysexDriverBuffer2 != NULL) {
+ if (sysexDriverBuffer2[port] != NULL) {
+ // some memory leaks here
+ delete sysexDriverBuffer2[port];
+ sysexDriverBuffer2[port] = NULL;
+ }
+ }
+
+ // allocate space for Drivers sysex byte buffer
+ sysexDriverBuffer1[port] = (LPMIDIHDR)GlobalLock(GlobalAlloc(GMEM_MOVEABLE |
+ GMEM_SHARE, sizeof(MIDIHDR)));
+ sysexDriverBuffer2[port] = (LPMIDIHDR)GlobalLock(GlobalAlloc(GMEM_MOVEABLE |
+ GMEM_SHARE, sizeof(MIDIHDR)));
+
+ if (sysexDriverBuffer1[port] == NULL) {
+ cout << "Error: could not allocate sysex driver's buffer" << endl;
+ exit(1);
+ }
+
+ if (sysexDriverBuffer2[port] == NULL) {
+ cout << "Error: could not allocate sysex driver's buffer" << endl;
+ exit(1);
+ }
+
+ // allocate buffer inside of sysexDriverBuffer
+ sysexDriverBuffer1[port]->lpData = (LPSTR)GlobalLock(GlobalAlloc(
+ GMEM_MOVEABLE | GMEM_SHARE, (DWORD)1024));
+ sysexDriverBuffer2[port]->lpData = (LPSTR)GlobalLock(GlobalAlloc(
+ GMEM_MOVEABLE | GMEM_SHARE, (DWORD)1024));
+
+ if (sysexDriverBuffer1[port]->lpData == NULL) {
+ cout << "Error: there was not enought space to allocate sysex buffer"
+ << endl;
+ // leaking memory here
+ exit(1);
+ }
+
+ if (sysexDriverBuffer2[port]->lpData == NULL) {
+ cout << "Error: there was not enought space to allocate sysex buffer"
+ << endl;
+ // leaking memory here
+ exit(1);
+ }
+
+
+ // setup other sysexDriverBuffer data fields
+ sysexDriverBuffer1[port]->dwBufferLength = 1024; // total size of buffer
+ sysexDriverBuffer1[port]->dwBytesRecorded = 0L; // number of byte in buffer
+ sysexDriverBuffer1[port]->dwFlags = 0L; // initialize flags
+ sysexDriverBuffer1[port]->dwUser = 0L; // userdata: used for sysex time
+
+ // setup other sysexDriverBuffer data fields
+ sysexDriverBuffer2[port]->dwBufferLength = 1024; // total size of buffer
+ sysexDriverBuffer2[port]->dwBytesRecorded = 0L; // number of byte in buffer
+ sysexDriverBuffer2[port]->dwFlags = 0L; // initialize flags
+ sysexDriverBuffer2[port]->dwUser = 0L; // userdata: used for sysex time
+
+ // prepare the header
+ int status = midiInPrepareHeader(device[port], sysexDriverBuffer1[port],
+ sizeof(MIDIHDR));
+
+ if (status != 0) {
+ cout << "Error preparing sysex buffer number: " << port << endl;
+ // leaking some memory here?
+ exit(1);
+ }
+
+ // prepare the header
+ status = midiInPrepareHeader(device[port], sysexDriverBuffer2[port],
+ sizeof(MIDIHDR));
+
+ if (status != 0) {
+ cout << "Error preparing sysex buffer number: " << port << endl;
+ // leaking some memory here?
+ exit(1);
+ }
+
+ // add the sysex buffer to the driver
+ status = midiInAddBuffer(device[port], sysexDriverBuffer1[port],
+ sizeof(MIDIHDR));
+
+ if (status != 0) {
+ cout << "Error adding sysex buffer to driver: " << port << endl;
+ // leaking some memory here?
+ exit(1);
+ }
+
+ status = midiInAddBuffer(device[port], sysexDriverBuffer2[port],
+ sizeof(MIDIHDR));
+
+ if (status != 0) {
+ cout << "Error adding sysex buffer to driver: " << port << endl;
+ // leaking some memory here?
+ exit(1);
+ }
+
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::uninstallSysexStuff -- uninstalls all the mess that
+// a MIDIIN structure needs in order to receive system exclusives.
+//
+
+void MidiInPort_visual::uninstallSysexStuff(HMIDIIN dev, int port) {
+ if (port == -1) {
+ return;
+ }
+ // unprepare the headers
+ midiInUnprepareHeader(device[port], sysexDriverBuffer1[port],
+ sizeof(MIDIHDR));
+ midiInUnprepareHeader(device[port], sysexDriverBuffer2[port],
+ sizeof(MIDIHDR));
+
+ // deallocate buffer inside of sysexDriverBuffer
+ /* Following code caused problems: perhaps lpData was deleted by driver
+ delete [] sysexDriverBuffer1[port]->lpData;
+ sysexDriverBuffer1[port]->lpData = NULL;
+ delete [] sysexDriverBuffer2[port]->lpData;
+ sysexDriverBuffer2[port]->lpData = NULL;
+ */
+
+ // deallocate space for Drivers sysex byte buffer
+ delete sysexDriverBuffer1[port];
+ delete sysexDriverBuffer2[port];
+ sysexDriverBuffer1[port] = NULL;
+ sysexDriverBuffer2[port] = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::releaseMutex
+//
+
+void MidiInPort_visual::releaseMutex(void) {
+/* int flag = */ ReleaseMutex(hMutex[getPort()]);
+/*
+ if (flag != 0) {
+ cerr << "Error relasing mutex in MIDI input; flag was: " << flag << endl;
+ }
+*/
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::setPortStatus
+//
+
+void MidiInPort_visual::setPortStatus(int aStatus) {
+ if (getPort() == -1) {
+ return;
+ }
+
+ if (aStatus) {
+ openQ[getPort()] = 1;
+ } else {
+ openQ[getPort()] = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::waitForMutex
+//
+
+void MidiInPort_visual::waitForMutex(void) {
+/*
+ DWORD mutexResult = WaitForSingleObject(hMutex[getPort()], 5000L);
+ if (mutexResult != WAIT_OBJECT_0) {
+ cerr << "Error waiting for mutex in MIDI input" << endl;
+ }
+*/
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////
+//
+// midiInputCallback -- the function the MIDI input driver calls when
+// it has a message from the Midi in cable ready
+//
+
+void CALLBACK midiInputCallback(HMIDIIN hMidiIn, UINT inputStatus,
+ DWORD instancePtr, DWORD midiMessage, DWORD timestamp) {
+ static MidiMessage newMessage;
+
+ switch (inputStatus) {
+ case MIM_MOREDATA:
+ // There is more data waiting at the device.
+ // If this case is exists, then that means that the MIDI
+ // device is too slow and some data was lost.
+ // Windows sends a MIM_MOREDATA event only if you specify
+ // the MIDI_IO_STATUS flag to midiInOpen().
+
+ // no break;
+ case MIM_DATA:
+
+ // One regular (non sysex) message has been completely
+ // received.
+
+ // ignore the Yamaha Active Sensing command and MIDI time clock
+ // at least for now.
+ if ((midiMessage & 0xff) == 0xfe || (midiMessage & 0xff) == 0xf8) {
+ break;
+ }
+
+ newMessage.time = timestamp;
+ newMessage.data = midiMessage;
+ ((MidiInPort_visual*)instancePtr)->insert(newMessage);
+ if (((MidiInPort_visual*)instancePtr)->getTrace()) {
+ cout << "[" << hex << (int)newMessage.command() << dec
+ << ":" << (int)newMessage.p1() << ","
+ << (int)newMessage.p2() << "]";
+ cout.flush();
+ }
+ break;
+
+ case MIM_LONGDATA:
+ {
+ // A sysex or part of a sysex message is coming in.
+ // The timestamp variable contains a pointer to a
+ // MIDIHDR pointer
+
+ MIDIHDR* midiheader = (MIDIHDR*)midiMessage;
+ int dataCount = midiheader->dwBytesRecorded;
+ char* data = midiheader->lpData;
+ int port = ((MidiInPort_visual*)instancePtr)->getPort();
+ if (port == -1) {
+ break;
+ }
+ int* sysexStatus = ((MidiInPort_visual*)instancePtr)->sysexStatus;
+// MIDIHDR** sysexDriverBuffer = ((MidiInPort_visual*)instancePtr)->
+// sysexDriverBuffer;
+ HMIDIIN devicex = ((MidiInPort_visual*)instancePtr)->device[port];
+
+ if (dataCount == 0) {
+ // can't handle a zero-length sysex
+ break;
+ }
+
+ // step 1: determine if this is the first part of the sysex
+ // message or a continuation
+ int continuation = 0;
+ if (data[0] == (char)0xf0) {
+ continuation = 0;
+ if (sysexStatus[port] != -1) {
+ cout << "Error: there is another sysex command being "
+ "received on port " << port << endl;
+ exit(1);
+ }
+ } else {
+ if (sysexStatus[port] == -1) {
+ cout << "Error: no sysex command is being "
+ "received on port " << port << endl;
+ if (data[0] < 128) {
+ cout << "First byte is: " << dec << (int)data[0] << endl;
+ } else {
+ cout << "First byte is: " << hex << (int)data[0] << endl;
+ }
+ if (data[1] < 128) {
+ cout << "Second byte is: " << dec << (int)data[1] << endl;
+ } else {
+ cout << "Second byte is: " << hex << (int)data[1] << endl;
+ }
+
+ exit(1);
+ }
+ continuation = 1;
+ }
+
+ // step 2: if continuing, add the data to the preallocated
+ // sysex buffer, otherwise, get a new buffer location
+ int buffer = -1;
+ if (continuation) {
+ buffer = sysexStatus[port];
+ if (buffer < 0 || buffer > 127) {
+ cout << "Sysex buffer was out of range: " << buffer << endl;
+ }
+ for (int i=0; i<dataCount; i++) {
+ unsigned char datum = data[i];
+ ((MidiInPort_visual*)instancePtr)->
+ sysexBuffers[port][buffer].append(datum);
+ if (datum == 0xf7) {
+ for (int k=i; k<dataCount; k++) {
+ data[k-i] = data[k];
+ }
+ midiheader->dwBytesRecorded = dataCount - i - 1;
+
+ goto insert_sysex_message;
+ }
+ }
+ } else { // if not a continuation of a sysex event
+ buffer = ((MidiInPort_visual*)instancePtr)->sysexWriteBuffer[port];
+ ((MidiInPort_visual*)instancePtr)->sysexWriteBuffer[port]++;
+ if (buffer == 127) {
+ ((MidiInPort_visual*)instancePtr)->sysexWriteBuffer[port] = 0;
+ }
+
+ ((MidiInPort_visual*)instancePtr)->
+ sysexBuffers[port][buffer].setSize(0);
+ for (int j=0; j<dataCount; j++) {
+ unsigned char datum = data[j];
+ ((MidiInPort_visual*)instancePtr)->
+ sysexBuffers[port][buffer].append(datum);
+ if (datum == 0xf7) {
+ for (int k=j; k<dataCount; k++) {
+ data[k-j] = data[k];
+ }
+
+ goto insert_sysex_message;
+ }
+ }
+
+ }
+
+ // recycle the MIDI input buffer for the driver
+ {
+ midiInPrepareHeader(devicex, midiheader, sizeof(MIDIHDR));
+ int dstatus = midiInAddBuffer(devicex, midiheader, sizeof(MIDIHDR));
+ if (dstatus != MMSYSERR_NOERROR) {
+ cout << "Error when calling midiInAddBuffer" << endl;
+ exit(1);
+ }
+ }
+
+ break;
+
+ insert_sysex_message:
+
+ // recycle the MIDI input buffer for the driver
+ {
+ midiInPrepareHeader(devicex, midiheader, sizeof(MIDIHDR));
+ int estatus = midiInAddBuffer(devicex, midiheader, sizeof(MIDIHDR));
+ if (estatus != MMSYSERR_NOERROR) {
+ cout << "Error when calling midiInAddBuffer" << endl;
+ exit(1);
+ }
+ }
+
+ // now that a sysex message is finished, send a midimessage
+ // out to the instancePtr MIDI buffer telling the user
+ // that a sysex message has come in.
+
+ // newMessage.time = timestamp; use last time stamp that came
+ // in because the timestamp variable is used for storing
+ // the pointer of the sysex data.
+
+ newMessage.time = timestamp;
+ newMessage.p0() = 0xf0;
+ newMessage.p1() = buffer;
+ newMessage.p2() = 0;
+ newMessage.p3() = 0;
+
+ ((MidiInPort_visual*)instancePtr)->insert(newMessage);
+ if (((MidiInPort_visual*)instancePtr)->getTrace()) {
+ cout << "[" << hex << (int)newMessage.command() << dec
+ << ":" << (int)newMessage.p1() << ","
+ << (int)newMessage.p2() << "]";
+ cout.flush();
+ }
+
+ } // end of local variable range
+ break;
+
+ case MIM_ERROR:
+ // An invalid regular MIDI message was received.
+
+ break;
+
+ case MIM_LONGERROR:
+ {
+ // An invalid sysex MIDI message was received.
+
+ // if a sysex message was continuing from a previous part,
+ // then kill that message.
+
+ int port = ((MidiInPort_visual*)instancePtr)->getPort();
+ if (port == -1) {
+ break;
+ }
+ int buffer = ((MidiInPort_visual*)instancePtr)->sysexStatus[port];
+ if (buffer != -1) {
+ ((MidiInPort_visual*)instancePtr)->
+ sysexBuffers[port][buffer].setSize(0);
+ ((MidiInPort_visual*)instancePtr)->sysexStatus[port] = -1;
+ }
+
+ HMIDIIN devicex = ((MidiInPort_visual*)instancePtr)->device[port];
+ MIDIHDR* midiheader = (MIDIHDR*)midiMessage;
+
+ // recycle the MIDI input buffer for the driver
+ midiInPrepareHeader(devicex, midiheader, sizeof(MIDIHDR));
+ int status = midiInAddBuffer(devicex, midiheader, sizeof(MIDIHDR));
+ if (status != MMSYSERR_NOERROR) {
+ cout << "Error when calling midiInAddBuffer" << endl;
+ exit(1);
+ }
+
+
+ break;
+ }
+ default: ;
+ // case MIM_OPEN: // MIDI device is opening
+ // case MIM_CLOSE: // MIDI device is closing
+ }
+}
+
+
+
+#endif // VISUAL
+
+
+// md5sum: db55d9f375b86f54c0c8340547c5701f - MidiInPort_visual.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInput.cpp b/src/midiio/src/MidiInput.cpp
new file mode 100644
index 0000000..93fce87
--- /dev/null
+++ b/src/midiio/src/MidiInput.cpp
@@ -0,0 +1,224 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 18 December 1997
+// Last Modified: Sun Jan 25 15:31:49 GMT-0800 1998
+// Last Modified: Thu Apr 27 17:56:03 PDT 2000 (added scale function)
+// Filename: ...sig/code/control/MidiInput/MidiInput.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiInput.cpp
+// Syntax: C++
+//
+// Description: A higher-level MIDI input interface than the
+// MidiInPort class. Can be used to allow multiple
+// objects to share a single MIDI input stream, or
+// to fake a MIDI input connection.
+//
+
+#include "MidiInput.h"
+#include <stdlib.h>
+#include <iostream>
+
+
+//////////////////////////////
+//
+// MidiInput::MidiInput -- opens the specified MIDI input device and
+// sets the size of the input buffer.
+//
+
+MidiInput::MidiInput(void) : MidiInPort() {
+ orphanBuffer = NULL;
+}
+
+
+MidiInput::MidiInput(int aPort, int autoOpen) : MidiInPort(aPort, autoOpen) {
+ orphanBuffer = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::~MidiInput
+//
+
+MidiInput::~MidiInput() {
+ if (orphanBuffer != NULL) {
+ delete orphanBuffer;
+ orphanBuffer = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::getBufferSize
+//
+
+int MidiInput::getBufferSize(void) {
+ if (isOrphan()) {
+ return orphanBuffer->getSize();
+ } else {
+ return MidiInPort::getBufferSize();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::getCount
+//
+
+int MidiInput::getCount(void) {
+ if (isOrphan()) {
+ return orphanBuffer->getCount();
+ } else {
+ return MidiInPort::getCount();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::extract
+//
+
+MidiMessage MidiInput::extract(void) {
+ if (isOrphan()) {
+ return orphanBuffer->extract();
+ } else {
+ return MidiInPort::extract();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// fscale -- converts a value in the range from 0 to 127
+// into a number in a new range. For example the value
+// 64 scaled to the range from 0 to 2 would be 1.
+//
+
+double MidiInput::fscale(int value, double min, double max) {
+ return value >= 127 ? max : (value/127.0*(max-min)+min);
+}
+
+
+
+//////////////////////////////
+//
+// fscale14 -- converts a value in the range from 0 to 2^15-1
+// into a number in a new range.
+//
+
+double MidiInput::fscale14(int value, double min, double max) {
+ return value >= 16383 ? max : (value/16383.0*(max-min)+min);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::insert
+//
+
+void MidiInput::insert(const MidiMessage& aMessage) {
+ if (isOrphan()) {
+ orphanBuffer->insert(aMessage);
+ } else {
+ MidiInPort::insert(aMessage);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::isOrphan
+//
+
+int MidiInput::isOrphan(void) const {
+ if (orphanBuffer == NULL) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::makeOrphanBuffer
+// default value: aSize = 1024
+//
+
+void MidiInput::makeOrphanBuffer(int aSize) {
+ if (!isOrphan()) {
+ if (orphanBuffer == NULL) {
+ delete orphanBuffer;
+ orphanBuffer = NULL;
+ }
+ orphanBuffer = new CircularBuffer<MidiMessage>(aSize);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::removeOrphanBuffer
+//
+
+void MidiInput::removeOrphanBuffer(void) {
+ if (isOrphan()) {
+ delete orphanBuffer;
+ orphanBuffer = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// scale -- converts a value in the range from 0 to 127
+// into a number in a new range. For example the value
+// 64 scaled to the range from 0 to 2 would be 1.
+//
+
+int MidiInput::scale(int value, int min, int max) {
+ return value >= 127 ? max : (int)(value/127.0*(max-min+1)+min);
+}
+
+
+
+//////////////////////////////
+//
+// scale14 -- converts a value in the range from 0 to 2^15-1
+// into a number in a new range.
+//
+
+int MidiInput::scale14(int value, int min, int max) {
+ return value >= 16383 ? max : (int)(value/16383.0*(max-min+1)+min);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::setBufferSize
+//
+
+void MidiInput::setBufferSize(int aSize) {
+ if (isOrphan()) {
+ orphanBuffer->setSize(aSize);
+ } else {
+ MidiInPort::setBufferSize(aSize);
+ }
+}
+
+
+
+// md5sum: 826d403708263eaf0089b4742179c58c - MidiInput.cpp =css= 20030102
diff --git a/src/midiio/src/MidiMessage.cpp b/src/midiio/src/MidiMessage.cpp
new file mode 100644
index 0000000..5f3df19
--- /dev/null
+++ b/src/midiio/src/MidiMessage.cpp
@@ -0,0 +1,406 @@
+//
+// Copyright 1997-1998 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 19 December 1997
+// Last Modified: Fri Jan 23 00:26:12 GMT-0800 1998
+// Last Modified: Sun Sep 20 12:17:26 PDT 1998
+// Last Modified: Mon Oct 15 14:29:12 PDT 2001 (added is_note functions)
+// Filename: ...sig/src/sigControl/MidiMessage.cpp
+// Web Address: http://sig.sapp.org/src/sigControl/MidiMessage.cpp
+// Syntax: C++
+//
+// Description: A structure for handling MIDI input messages.
+// This class stores a time stamp plus up to
+// four MIDI message bytes. System Exclusive messages
+// are stored in a separate array in the MidiInPort
+// class, and their storage index is passed to the
+// user through a MIDI message for later extraction
+// of the full sysex message.
+//
+
+#include "MidiMessage.h"
+
+
+//////////////////////////////
+//
+// MidiMessage::MidiMessage
+//
+
+MidiMessage::MidiMessage(void) {
+ // no initialization. Note that the default contents are undefined.
+}
+
+
+// default value aTime = 0
+MidiMessage::MidiMessage(int aCommand, int aP1, int aP2, int aTime) {
+ time = aTime;
+ command() = (uchar)aCommand;
+ p1() = (uchar)aP1;
+ p2() = (uchar)aP2;
+}
+
+
+MidiMessage::MidiMessage(const MidiMessage& aMessage) {
+ time = aMessage.time;
+ data = aMessage.data;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::~MidiMessage -- Destructor.
+//
+
+MidiMessage::~MidiMessage() {
+ // do nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::command -- returns the MIDI command byte
+//
+
+uchar& MidiMessage::command(void) {
+ return p0();
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::operator= -- defines how objects are to be copied
+//
+
+MidiMessage& MidiMessage::operator=(const MidiMessage& aMessage) {
+ time = aMessage.time;
+ data = aMessage.data;
+ return *this;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::operator[] -- access to byte data
+// can only access index 0 to 3, other number will be
+// chopped.
+//
+
+uchar& MidiMessage::operator[](int index) {
+ return *(((uchar*)&data)+(index & 0x3));
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::p0 -- returns the command byte of the
+// midi message. Same as the command() function.
+//
+
+uchar& MidiMessage::p0(void) {
+ return *(((uchar*)&data)+0);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::p1 -- returns the first parameter of the
+// midi message. Valid if the command requires a parameter.
+//
+
+uchar& MidiMessage::p1(void) {
+ return *(((uchar*)&data)+1);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::p2 -- returns the second parameter of the
+// midi message. Valid if the command requires two parameters.
+//
+
+uchar& MidiMessage::p2(void) {
+ return *(((uchar*)&data)+2);
+}
+
+
+//////////////////////////////
+//
+// MidiMessage::p3 -- returns the third parameter of the
+// midi message. Valid if the command requires three parameters
+// (but none of the MIDI command do).
+//
+
+uchar& MidiMessage::p3(void) {
+ return *(((uchar*)&data)+3);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage:getArgCount --
+//
+
+int MidiMessage::getArgCount(void) const {
+ return getParameterCount();
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getParameterCount -- returns the number
+// of valid parameters for the assiciated MIDI command
+// stored in p0. Returns -1 if MIDI command is invalid,
+// or the number of valid parameters is unknown.
+//
+
+int MidiMessage::getParameterCount(void) const {
+ int output = -1;
+ switch (*(((uchar*)&data)+0) & 0xf0) {
+ case 0x80: // note-off
+ case 0x90: // note-on
+ case 0xa0: // aftertouch
+ case 0xb0: // continuous controller
+ case 0xe0: // pitch wheel
+ output = 2;
+ break;
+ case 0xc0: // patch change
+ case 0xd0: // channel pressure
+ output = 1;
+ break;
+ case 0xf0:
+ switch (*(((uchar*)&data)+0)) {
+ // System Common Messages
+ case 0xf0: return -1; // variable for sysex
+ case 0xf1: return 1; // MIDI Time Code Quarter Frame
+ case 0xf2: return 2; // Song Position Pointer
+ case 0xf3: return 1; // Song Select
+ case 0xf4: return 0; // Undefined
+ case 0xf5: return 0; // Undefined
+ case 0xf6: return 0; // Tune Request
+ case 0xf7: return 0; // End of System exclusive
+ // System Real-Time Messages
+ case 0xf8: return 0; // Timing Clock
+ case 0xf9: return 0; // Undefined
+ case 0xfa: return 0; // Start
+ case 0xfb: return 0; // Continue
+ case 0xfc: return 0; // Stop
+ case 0xfd: return 0; // Undefined
+ case 0xfe: return 0; // Active Sensing
+ case 0xff: return 0; // System Reset
+ }
+ return -1;
+ break;
+ default: // don't know or invalid command
+ output = -1;
+ break;
+ }
+
+ return output;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getCommand -- same as command().
+//
+
+uchar MidiMessage::getCommand(void) const {
+ return getP0();
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getP0 -- same as p0().
+//
+
+uchar MidiMessage::getP0(void) const {
+ return *(((uchar*)&data)+0);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getP1 -- same as p1().
+//
+
+uchar MidiMessage::getP1(void) const {
+ return *(((uchar*)&data)+1);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getP2 -- same as p2().
+//
+
+uchar MidiMessage::getP2(void) const {
+ return *(((uchar*)&data)+2);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getP3 -- same as p3().
+//
+
+uchar MidiMessage::getP3(void) const {
+ return *(((uchar*)&data)+3);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setCommand -- same as command().
+//
+
+void MidiMessage::setCommand(uchar aCommand) {
+ command() = aCommand;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setData -- sets the message bytes
+// default values: aP1 = 0, aP2 = 0, aP3 = 0.
+//
+
+void MidiMessage::setData(uchar aCommand, uchar aP1, uchar aP2, uchar aP3) {
+ setCommand(aCommand);
+ setP1(aP1);
+ setP2(aP2);
+ setP3(aP3);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setP0 -- same as p0().
+//
+
+void MidiMessage::setP0(uchar aP0) {
+ p0() = aP0;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setP1 -- same as p1().
+//
+
+void MidiMessage::setP1(uchar aP1) {
+ p1() = aP1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setP2 -- same as p2().
+//
+
+void MidiMessage::setP2(uchar aP2) {
+ p2() = aP2;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setP3 -- same as p3().
+//
+
+void MidiMessage::setP3(uchar aP3) {
+ p3() = aP3;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::is_note -- Returns true if the MIDI command is 0x80 or 0x90.
+//
+
+int MidiMessage::is_note(void) {
+ if ((p0() & 0xf0) == 0x90) { // note-on or note-off
+ return 1;
+ } else if ((p0() & 0xf0) == 0x80) { // note-off
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::is_note_on -- Returns true if the MIDI command is a note
+// on message (0x90 series with p2() > 0).
+//
+
+int MidiMessage::is_note_on(void) {
+ if (((p0() & 0xf0) == 0x90) && p2() > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::is_note_off -- Returns true if the MIDI command is a note
+// off message (0x80 series or 0x90 series with p2() == 0).
+//
+
+int MidiMessage::is_note_off(void) {
+ if ((p0() & 0xf0) == 0x80) {
+ return 1;
+ } else if (((p0() & 0xf0) == 0x90) && (p2() == 0)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////
+//
+// operator<< MidiMessage
+//
+
+std::ostream& operator<<(std::ostream& out, MidiMessage& aMessage) {
+ out << "(" << aMessage.time << ") "
+ << std::hex << (int)aMessage.getP0() << ": ";
+ for (int i=1; i<=aMessage.getArgCount(); i++) {
+ out << std::dec << (int)aMessage[i] << ' ';
+ }
+
+ return out;
+}
+
+
+
+// md5sum: 487f0fddeb8db20d81f9c039e2a460c9 - MidiMessage.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutPort_alsa.cpp b/src/midiio/src/MidiOutPort_alsa.cpp
new file mode 100644
index 0000000..07f4e5d
--- /dev/null
+++ b/src/midiio/src/MidiOutPort_alsa.cpp
@@ -0,0 +1,469 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed May 10 16:16:21 PDT 2000
+// Last Modified: Sun May 14 20:44:12 PDT 2000
+// Filename: ...sig/code/control/MidiOutPort/alsa/MidiOutPort_alsa.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiOutPort_alsa.cpp
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Linux using
+// ALSA sound drivers. Privately inherited by the
+// MidiOutPort class via the MidiOutPort_alsa class.
+//
+
+#if defined(LINUX) && defined(ALSA)
+
+#include "MidiOutPort_alsa.h"
+#include <iostream>
+#include <stdlib.h>
+
+// initialized static variables
+int MidiOutPort_alsa::numDevices = 0;
+int MidiOutPort_alsa::objectCount = 0;
+int* MidiOutPort_alsa::portObjectCount = NULL;
+int MidiOutPort_alsa::channelOffset = 0;
+int* MidiOutPort_alsa::trace = NULL;
+std::ostream* MidiOutPort_alsa::tracedisplay = &std::cout;
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::MidiOutPort_alsa
+// default values: autoOpen = 1
+//
+
+#include <unistd.h>
+
+MidiOutPort_alsa::MidiOutPort_alsa(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiOutPort_alsa::MidiOutPort_alsa(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::~MidiOutPort_alsa --
+//
+
+MidiOutPort_alsa::~MidiOutPort_alsa() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cout << "Error: bad MidiOutPort object count!: " << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::close --
+//
+
+void MidiOutPort_alsa::close(void) {
+ Sequencer_alsa::closeOutput(getPort());
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::closeAll --
+//
+
+void MidiOutPort_alsa::closeAll(void) {
+ int i;
+ for (i=0; i<getNumPorts(); i++) {
+ Sequencer_alsa::closeOutput(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiOutPort_alsa::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiOutPort_alsa::getName(void) {
+ if (getPort() == -1) {
+ return "Null ALSA Midi Output";
+ }
+ return getOutputName(getPort());
+}
+
+
+const char* MidiOutPort_alsa::getName(int i) {
+ return Sequencer_alsa::getOutputName(i);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getNumPorts -- returns the number of available
+// ports for MIDI output
+//
+
+int MidiOutPort_alsa::getNumPorts(void) {
+ return Sequencer_alsa::getNumOutputs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiOutPort_alsa::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiOutPort_alsa::getPortStatus(void) {
+ return is_open_out(getPort());
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getTrace -- returns true if trace is on or
+// false if off. If trace is on, then prints to standard output
+// the Midi message being sent.
+//
+
+int MidiOutPort_alsa::getTrace(void) {
+ if (getPort() == -1) return -1;
+
+ return trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::rawsend -- send the Midi command and its parameters
+//
+
+int MidiOutPort_alsa::rawsend(int command, int p1, int p2) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[3] = {(uchar)command, (uchar)p1, (uchar)p2};
+ status = write(getPort(), mdata, 3);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << ":"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << "X"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_alsa::rawsend(int command, int p1) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[2] = {(uchar)command, (uchar)p1};
+
+ status = write(getPort(), mdata, 2);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << ":"
+ << (int)mdata[1] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << "X"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_alsa::rawsend(int command) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[1] = {(uchar)command};
+
+ status = write(getPort(), mdata, 1);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_alsa::rawsend(uchar* array, int size) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ status = write(getPort(), array, size);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(array)";
+ std::cout.flush();
+ } else {
+ std::cout << "(XarrayX)";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::open -- returns true if MIDI output port was
+// opened.
+//
+
+int MidiOutPort_alsa::open(void) {
+ if (getPort() == -1) {
+ return 2;
+ } else {
+ return Sequencer_alsa::openOutput(getPort());
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::setChannelOffset -- sets the MIDI channel offset,
+// either 0 or 1.
+//
+
+void MidiOutPort_alsa::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::setPort --
+//
+
+void MidiOutPort_alsa::setPort(int aPort) {
+ if (aPort == -1) return;
+
+ if (aPort < 0 || aPort >= getNumPorts()) {
+ std::cout << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << std::endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::setTrace -- if false, then won't print
+// Midi messages to standard output.
+//
+
+int MidiOutPort_alsa::setTrace(int aState) {
+ if (getPort() == -1) return -1;
+
+ int oldtrace = trace[getPort()];
+ if (aState == 0) {
+ trace[getPort()] = 0;
+ } else {
+ trace[getPort()] = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::sysex -- send a system exclusive message.
+// The message must start with a 0xf0 byte and end with
+// a 0xf7 byte.
+//
+
+int MidiOutPort_alsa::sysex(uchar* array, int size) {
+ if (getPort() == -1) {
+ return 2;
+ }
+
+ if (size == 0 || array[0] != 0xf0 || array[size-1] != 0xf7) {
+ std::cout << "Error: invalid sysex message" << std::endl;
+ exit(1);
+ }
+
+ return rawsend(array,size);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::toggleTrace --
+//
+
+void MidiOutPort_alsa::toggleTrace(void) {
+ if (getPort() == -1) return;
+
+ trace[getPort()] = !trace[getPort()];
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_alsa::deinitialize(void) {
+ closeAll();
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = NULL;
+ if (trace != NULL) delete [] trace;
+ trace = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_alsa::initialize(void) {
+ // get the number of ports
+ numDevices = getNumOutputs();
+ if (getNumPorts() <= 0) {
+ std::cout << "Warning: no MIDI output devices" << std::endl;
+ portObjectCount = NULL;
+ trace = NULL;
+ } else {
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+ // allocate space for trace variable for each port:
+ if (trace != NULL) delete [] trace;
+ trace = new int[numDevices];
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ portObjectCount[i] = 0;
+ trace[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::setPortStatus --
+//
+
+void MidiOutPort_alsa::setPortStatus(int aStatus) {
+ // not used in Linux implementation
+}
+
+
+#endif /* LINUX and ALSA */
+
+
+
+// md5sum: 6f5d0ce75ae6e086ad949178e7deefcb - MidiOutPort_alsa.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutPort_linux.cpp b/src/midiio/src/MidiOutPort_linux.cpp
new file mode 100644
index 0000000..43bba90
--- /dev/null
+++ b/src/midiio/src/MidiOutPort_linux.cpp
@@ -0,0 +1,381 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 20:58:32 PDT 2000
+// Last Modified: Thu May 18 23:37:11 PDT 2000
+// Last Modified: Sat Nov 2 20:40:01 PST 2002 (added ALSA OSS def)
+// Filename: ...sig/code/control/MidiOutPort_linux/MidiOutPort_linux.cpp
+// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_linux.cpp
+// Syntax: C++
+//
+// Description: Linux MIDI output class which detects which
+// type of MIDI drivers are available: either
+// ALSA or OSS.
+//
+
+#ifdef LINUX
+#if defined(ALSA) && defined(OSS)
+
+#include "MidiOutPort_linux.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+
+// initialize static members
+int MidiOutPort_linux::objectCount = 0;
+int MidiOutPort_linux::current = UNKNOWN_MIDI_SELECT; // MIDI out selected
+int MidiOutPort_linux::alsaQ = 0; // boolean for if ALSA is present
+int MidiOutPort_linux::ossQ = 0; // boolean for if OSS is present
+
+MidiOutPort_oss *MidiOutPort_linux::oss_output = NULL;
+MidiOutPort_alsa *MidiOutPort_linux::alsa_output = NULL;
+MidiOutPort_unsupported *MidiOutPort_linux::unknown_output = NULL;
+
+
+MidiOutPort_linux::MidiOutPort_linux(void) {
+ if (objectCount == 0) {
+ determineDrivers();
+ } else if (objectCount < 0) {
+ cout << "Error: unusual MidiOutPort_linux object count" << endl;
+ exit(1);
+ }
+
+ objectCount++;
+}
+
+MidiOutPort_linux::MidiOutPort_linux(int aPort, int autoOpen = 1) {
+ determineDrivers();
+ setAndOpenPort(aPort);
+}
+
+MidiOutPort_linux::~MidiOutPort_linux() {
+ objectCount--;
+ if (objectCount == 0) {
+ if (oss_output != NULL) {
+ delete oss_output;
+ oss_output = NULL;
+ }
+
+ if (alsa_output != NULL) {
+ delete alsa_output;
+ alsa_output = NULL;
+ }
+
+ if (unknown_output != NULL) {
+ delete unknown_output;
+ unknown_output = NULL;
+ }
+ }
+
+ if (objectCount < 0) {
+ cout << "Error: unusual MidiOutPort_linux count when destructing" << endl;
+ exit(1);
+ }
+}
+
+
+void MidiOutPort_linux::close(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: oss_output->close(); break;
+ case ALSA_MIDI_SELECT: alsa_output->close(); break;
+ default: unknown_output->close(); break;
+ }
+}
+
+void MidiOutPort_linux::closeAll(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: oss_output->closeAll(); break;
+ case ALSA_MIDI_SELECT: alsa_output->closeAll(); break;
+ default: unknown_output->closeAll(); break;
+ }
+}
+
+int MidiOutPort_linux::getChannelOffset(void) const {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getChannelOffset(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getChannelOffset(); break;
+ default: return unknown_output->getChannelOffset(); break;
+ }
+}
+
+const char* MidiOutPort_linux::getName(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getName(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getName(); break;
+ default: return unknown_output->getName(); break;
+ }
+}
+
+const char* MidiOutPort_linux::getName(int i) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getName(i); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getName(i); break;
+ default: return unknown_output->getName(i); break;
+ }
+}
+
+int MidiOutPort_linux::getNumPorts(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getNumPorts(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getNumPorts(); break;
+ default: return unknown_output->getNumPorts(); break;
+ }
+}
+
+int MidiOutPort_linux::getPort(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getPort(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getPort(); break;
+ default: return unknown_output->getPort(); break;
+ }
+}
+
+int MidiOutPort_linux::getPortStatus(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getPortStatus(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getPortStatus(); break;
+ default: return unknown_output->getPortStatus(); break;
+ }
+}
+
+int MidiOutPort_linux::getTrace(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getTrace(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getTrace(); break;
+ default: return unknown_output->getTrace(); break;
+ }
+}
+
+int MidiOutPort_linux::open(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->open(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->open(); break;
+ default: return unknown_output->open(); break;
+ }
+}
+
+int MidiOutPort_linux::rawsend(int command, int p1, int p2) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->rawsend(command, p1, p2); break;
+ case ALSA_MIDI_SELECT: return alsa_output->rawsend(command, p1, p2); break;
+ default: return unknown_output->rawsend(command, p1, p2); break;
+ }
+}
+
+int MidiOutPort_linux::rawsend(int command, int p1) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->rawsend(command, p1); break;
+ case ALSA_MIDI_SELECT: return alsa_output->rawsend(command, p1); break;
+ default: return unknown_output->rawsend(command, p1); break;
+ }
+}
+
+int MidiOutPort_linux::rawsend(int command) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->rawsend(command); break;
+ case ALSA_MIDI_SELECT: return alsa_output->rawsend(command); break;
+ default: return unknown_output->rawsend(command); break;
+ }
+}
+
+int MidiOutPort_linux::rawsend(uchar* array, int size) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->rawsend(array, size); break;
+ case ALSA_MIDI_SELECT: return alsa_output->rawsend(array, size); break;
+ default: return unknown_output->rawsend(array, size); break;
+ }
+}
+
+void MidiOutPort_linux::setAndOpenPort(int aPort) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT:
+ oss_output->setPort(aPort);
+ oss_output->open();
+ break;
+ case ALSA_MIDI_SELECT:
+ alsa_output->setPort(aPort);
+ alsa_output->open();
+ break;
+ default:
+ unknown_output->setPort(aPort);
+ unknown_output->open();
+ break;
+ }
+}
+
+void MidiOutPort_linux::setChannelOffset(int aChannel) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: oss_output->setChannelOffset(aChannel); break;
+ case ALSA_MIDI_SELECT: alsa_output->setChannelOffset(aChannel); break;
+ default: unknown_output->setChannelOffset(aChannel); break;
+ }
+}
+
+void MidiOutPort_linux::setPort(int aPort) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: oss_output->setPort(aPort); break;
+ case ALSA_MIDI_SELECT:
+ alsa_output->setPort(aPort); break;
+ default: unknown_output->setPort(aPort); break;
+ }
+}
+
+int MidiOutPort_linux::setTrace(int aState) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->setTrace(aState); break;
+ case ALSA_MIDI_SELECT: return alsa_output->setTrace(aState); break;
+ default: return unknown_output->setTrace(aState); break;
+ }
+}
+
+int MidiOutPort_linux::sysex(uchar* array, int size) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->sysex(array, size); break;
+ case ALSA_MIDI_SELECT: return alsa_output->sysex(array, size); break;
+ default: return unknown_output->sysex(array, size); break;
+ }
+}
+
+void MidiOutPort_linux::toggleTrace(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: oss_output->toggleTrace(); break;
+ case ALSA_MIDI_SELECT: alsa_output->toggleTrace(); break;
+ default: unknown_output->toggleTrace(); break;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_linux::getSelect -- return the type of MIDI which
+// is being used to send MIDI output.
+//
+
+int MidiOutPort_linux::getSelect(void) {
+ return current;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_linux::selectOSS -- select the OSS MIDI output
+// returns 1 if OSS is available, otherwise returns 0.
+//
+
+int MidiOutPort_linux::selectOSS(void) {
+ if (ossQ) {
+ current = OSS_MIDI_SELECT;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_linux::selectALSA -- select the ALSA MIDI output
+// returns 1 if ALSA is available, otherwise returns 0.
+//
+
+int MidiOutPort_linux::selectALSA(void) {
+ if (alsaQ) {
+ current = ALSA_MIDI_SELECT;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_linux::selectUnknown -- select the Unknown MIDI output
+// returns 1 always.
+//
+
+int MidiOutPort_linux::selectUnknown(void) {
+ current = UNKNOWN_MIDI_SELECT;
+ return 1;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private Functions
+//
+
+#include <unistd.h>
+
+//////////////////////////////
+//
+// MidiOutPort_linux::determineDrivers -- see if OSS/ALSA are
+// available. If /dev/sequencer is present, assume that OSS is
+// available. If /dev/snd/sdq is present, assume that ALSA is
+// available.
+//
+
+void MidiOutPort_linux::determineDrivers(void) {
+ struct stat filestats;
+ int status;
+ status = stat("/dev/sequencer", &filestats);
+
+ if (status != 0) {
+ ossQ = 0;
+ } else {
+ ossQ = 1;
+ }
+
+ status = stat("/dev/snd/seq", &filestats);
+
+ if (status != 0) {
+ alsaQ = 0;
+ } else {
+ alsaQ = 1;
+ }
+
+
+ current = UNKNOWN_MIDI_SELECT;
+
+ if (ossQ) {
+ current = OSS_MIDI_SELECT;
+ }
+
+ if (alsaQ) {
+ current = ALSA_MIDI_SELECT;
+ }
+
+ // create MIDI output types which are available:
+
+ if (oss_output != NULL) {
+ delete oss_output;
+ oss_output = NULL;
+ }
+ if (alsa_output != NULL) {
+ delete alsa_output;
+ alsa_output = NULL;
+ }
+ if (unknown_output != NULL) {
+ delete unknown_output;
+ unknown_output = NULL;
+ }
+
+ if (ossQ) {
+ oss_output = new MidiOutPort_oss;
+ }
+ if (alsaQ) {
+ alsa_output = new MidiOutPort_alsa;
+ }
+ unknown_output = new MidiOutPort_unsupported;
+}
+
+
+#endif /* ALSA and OSS */
+#endif /* LINUX */
+
+// md5sum: be1ccf667122f1c9cf56a95b2ffb8e79 - MidiOutPort_linux.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutPort_oss.cpp b/src/midiio/src/MidiOutPort_oss.cpp
new file mode 100644
index 0000000..74f17c4
--- /dev/null
+++ b/src/midiio/src/MidiOutPort_oss.cpp
@@ -0,0 +1,462 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Dec 18 19:22:20 PST 1998
+// Last Modified: Fri Jan 8 04:26:16 PST 1999
+// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _linux to _oss)
+// Filename: ...sig/code/control/MidiOutPort/linux/MidiOutPort_oss.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiOutPort_oss.cpp
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Linux using
+// OSS sound drivers. Privately inherited by the
+// MidiOutPort class.
+//
+
+#ifdef LINUX
+
+#include "MidiOutPort_oss.h"
+#include <iostream>
+#include <stdlib.h>
+
+// initialized static variables
+int MidiOutPort_oss::numDevices = 0;
+int MidiOutPort_oss::objectCount = 0;
+int* MidiOutPort_oss::portObjectCount = NULL;
+int MidiOutPort_oss::channelOffset = 0;
+int* MidiOutPort_oss::trace = NULL;
+std::ostream* MidiOutPort_oss::tracedisplay = &std::cout;
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::MidiOutPort_oss
+// default values: autoOpen = 1
+//
+
+
+MidiOutPort_oss::MidiOutPort_oss(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiOutPort_oss::MidiOutPort_oss(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::~MidiOutPort_oss
+//
+
+MidiOutPort_oss::~MidiOutPort_oss() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cerr << "Error: bad MidiOutPort object count!: " << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::close
+//
+
+void MidiOutPort_oss::close(void) {
+ // don't close anything, because the
+ // Linux driver keeps all of the ports open while the
+ // midi driver (/dev/sequencer) is running.
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::closeAll
+//
+
+void MidiOutPort_oss::closeAll(void) {
+ // the Linux MIDI driver will close the /dev/sequencer device
+ // which will close all MIDI output ports at the same time.
+ Sequencer_oss::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiOutPort_oss::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiOutPort_oss::getName(void) {
+ if (getPort() == -1) {
+ return "Null OSS MIDI Output";
+ }
+ return getOutputName(getPort());
+}
+
+
+const char* MidiOutPort_oss::getName(int i) {
+ return Sequencer_oss::getOutputName(i);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getNumPorts -- returns the number of available
+// ports for MIDI output
+//
+
+int MidiOutPort_oss::getNumPorts(void) {
+ return Sequencer_oss::getNumOutputs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiOutPort_oss::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiOutPort_oss::getPortStatus(void) {
+ // Linux MIDI devices are all open at the same time,
+ // so if one is open, then they all are.
+ return is_open();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getTrace -- returns true if trace is on or
+// false if off. If trace is on, then prints to standard output
+// the Midi message being sent.
+//
+
+int MidiOutPort_oss::getTrace(void) {
+ if (getPort() == -1) return -1;
+
+ return trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::rawsend -- send the Midi command and its parameters
+//
+
+int MidiOutPort_oss::rawsend(int command, int p1, int p2) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[3] = {(uchar)command, (uchar)p1, (uchar)p2};
+ status = write(getPort(), mdata, 3);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << ":"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << "X"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_oss::rawsend(int command, int p1) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[2] = {(uchar)command, (uchar)p1};
+
+ status = write(getPort(), mdata, 2);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << ":"
+ << (int)mdata[1] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << "X"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_oss::rawsend(int command) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[1] = {(uchar)command};
+
+ status = write(getPort(), mdata, 1);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_oss::rawsend(uchar* array, int size) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ status = write(getPort(), array, size);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(array)";
+ std::cout.flush();
+ } else {
+ std::cout << "(XarrayX)";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::open -- returns true if MIDI output port was
+// opened.
+//
+
+int MidiOutPort_oss::open(void) {
+ return Sequencer_oss::open();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::setChannelOffset -- sets the MIDI channel offset,
+// either 0 or 1.
+//
+
+void MidiOutPort_oss::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::setPort --
+//
+
+void MidiOutPort_oss::setPort(int aPort) {
+ if (aPort < -1 || aPort >= getNumPorts()) {
+ std::cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << std::endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::setTrace -- if false, then won't print
+// Midi messages to standard output.
+//
+
+int MidiOutPort_oss::setTrace(int aState) {
+ if (getPort() == -1) return -1;
+
+ int oldtrace = trace[getPort()];
+ if (aState == 0) {
+ trace[getPort()] = 0;
+ } else {
+ trace[getPort()] = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::sysex -- send a system exclusive message.
+// The message must start with a 0xf0 byte and end with
+// a 0xf7 byte.
+//
+
+int MidiOutPort_oss::sysex(uchar* array, int size) {
+ if (size == 0 || array[0] != 0xf0) {
+ std::cout << "Error: invalid sysex message" << std::endl;
+ exit(1);
+ }
+
+ return rawsend(array,size);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::toggleTrace
+//
+
+void MidiOutPort_oss::toggleTrace(void) {
+ if (getPort() == -1) return;
+
+ trace[getPort()] = !trace[getPort()];
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_oss::deinitialize(void) {
+ closeAll();
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = NULL;
+ if (trace != NULL) delete [] trace;
+ trace = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_oss::initialize(void) {
+ // get the number of ports
+ numDevices = getNumOutputs();
+ if (getNumPorts() <= 0) {
+ std::cerr << "Warning: no MIDI output devices" << std::endl;
+ portObjectCount = NULL;
+ trace = NULL;
+ } else {
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+ // allocate space for trace variable for each port:
+ if (trace != NULL) delete [] trace;
+ trace = new int[numDevices];
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ portObjectCount[i] = 0;
+ trace[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::setPortStatus
+//
+
+void MidiOutPort_oss::setPortStatus(int aStatus) {
+ // not used in Linux implementation
+}
+
+
+#endif // LINUX
+
+
+
+// md5sum: c09dbe18ce8a0ff6ff11030d43a98c4a - MidiOutPort_oss.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutPort_unsupported.cpp b/src/midiio/src/MidiOutPort_unsupported.cpp
new file mode 100644
index 0000000..f4b8c28
--- /dev/null
+++ b/src/midiio/src/MidiOutPort_unsupported.cpp
@@ -0,0 +1,402 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Mon Jan 12 21:40:35 GMT-0800 1998
+// Last Modified: Mon Jan 12 21:40:39 GMT-0800 1998
+// Filename: ...sig/code/control/MidiOutPort/unsupported/MidiOutPort_unsupported.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiOutPort_unsupported.cpp
+// Syntax: C++
+//
+// Description: Operating-System specific interface for basic MIDI output
+// capabilities in an unknown operating system. Privately
+// inherited by the MidiOutPort class. Used for compiling
+// and running MIDI programs on a computer with no
+// MIDI output.
+//
+
+#include "MidiOutPort_unsupported.h"
+
+#include <iostream>
+#include <stdlib.h>
+#include <string.h>
+#include <sstream>
+
+// initialized static variables
+int MidiOutPort_unsupported::numDevices = 0;
+int MidiOutPort_unsupported::objectCount = 0;
+int* MidiOutPort_unsupported::openQ = NULL;
+int* MidiOutPort_unsupported::portObjectCount = NULL;
+int MidiOutPort_unsupported::channelOffset = 0;
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::MidiOutPort_unsupported
+// default values: autoOpen = 1
+//
+
+
+MidiOutPort_unsupported::MidiOutPort_unsupported(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiOutPort_unsupported::MidiOutPort_unsupported(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::~MidiOutPort_unsupported
+//
+
+MidiOutPort_unsupported::~MidiOutPort_unsupported() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cerr << "Error: bad MidiOutPort object count!: " << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::close
+//
+
+void MidiOutPort_unsupported::close(void) {
+ if (getPortStatus() == 1) {
+ setPortStatus(0);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::closeAll
+//
+
+void MidiOutPort_unsupported::closeAll(void) {
+ for (int i=0; i<getNumPorts(); i++) {
+ if (openQ[i] == 1) {
+ openQ[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiOutPort_unsupported::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiOutPort_unsupported::getName(void) const {
+ static char* name = NULL;
+ std::stringstream temp;
+ temp << "Inactive MIDI output test port #";
+ temp << getPort();
+ if (name != NULL) delete [] name;
+ name = new char[temp.str().length()+1];
+ strcpy(name, temp.str().c_str());
+ return name;
+}
+
+const char* MidiOutPort_unsupported::getName(int i) const {
+ static char* name = NULL;
+ std::stringstream temp;
+ temp << "Inactive MIDI output test port #";
+ temp << i;
+ if (name != NULL) delete [] name;
+ name = new char[temp.str().length()+1];
+ strcpy(name, temp.str().c_str());
+ return name;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getNumPorts -- returns the number of available
+// ports for MIDI output
+//
+
+int MidiOutPort_unsupported::getNumPorts(void) const {
+ return numDevices;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiOutPort_unsupported::getPort(void) const {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiOutPort_unsupported::getPortStatus(void) const {
+ if (openQ[getPort()] == 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getTrace -- returns true if trace is on or
+// false if off. If trace is on, then prints to standard output
+// the Midi message being sent.
+//
+
+int MidiOutPort_unsupported::getTrace(void) const {
+ return trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::rawsend -- send the Midi command and its parameters
+//
+
+int MidiOutPort_unsupported::rawsend(int command, int p1, int p2) {
+ if (getTrace()) {
+ std::cout << "{" << std::hex << command << std::dec << ":" << (p1 & 0xff)
+ << "," << (p2 & 0xff) << "}";
+ std::cout.flush();
+ }
+
+ return 1;
+}
+
+
+int MidiOutPort_unsupported::rawsend(int command, int p1) {
+ return 1;
+}
+
+
+int MidiOutPort_unsupported::rawsend(int command) {
+ return 1;
+}
+
+
+int MidiOutPort_unsupported::rawsend(uchar* array, int size) {
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::open -- returns true if MIDI output port was
+// opened.
+//
+
+int MidiOutPort_unsupported::open(void) {
+ if (getPortStatus() == 0) {
+ openQ[getPort()] = 1;
+ }
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::setChannelOffset -- sets the MIDI channel offset, either 0 or 1.
+//
+
+void MidiOutPort_unsupported::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::setPort --
+//
+
+void MidiOutPort_unsupported::setPort(int aPort) {
+ if (aPort < 0 || aPort >= getNumPorts()) {
+ std::cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << std::endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ portObjectCount[port]++;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::setTrace -- if false, then won't print
+// Midi messages to standard output.
+//
+
+int MidiOutPort_unsupported::setTrace(int aState) {
+ int oldtrace = trace;
+ if (aState == 0) {
+ trace = 0;
+ } else {
+ trace = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::sysex --
+//
+
+int MidiOutPort_unsupported::sysex(uchar* array, int size) {
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::toggleTrace --
+//
+
+void MidiOutPort_unsupported::toggleTrace(void) {
+ trace = !trace;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_unsupported::deinitialize(void) {
+ closeAll();
+ if (openQ != NULL) delete [] openQ;
+ openQ = NULL;
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_unsupported::initialize(void) {
+ // get the number of ports
+ numDevices = 16;
+ if (getNumPorts() <= 0) {
+ std::cerr << "Error: no MIDI output devices" << std::endl;
+ exit(1);
+ }
+
+
+ // allocate space for openQ, the port open/close status
+ if (openQ != NULL) delete [] openQ;
+ openQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ openQ[i] = 0;
+ portObjectCount[i] = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::setPortStatus(int aStatus) {
+//
+
+void MidiOutPort_unsupported::setPortStatus(int aStatus) {
+ if (aStatus) {
+ openQ[getPort()] = 1;
+ } else {
+ openQ[getPort()] = 0;
+ }
+}
+
+
+
+
+// md5sum: eff3d6cd2cab4c2def6ca60ef0ca197f - MidiOutPort_unsupported.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutPort_visual.cpp b/src/midiio/src/MidiOutPort_visual.cpp
new file mode 100644
index 0000000..d080817
--- /dev/null
+++ b/src/midiio/src/MidiOutPort_visual.cpp
@@ -0,0 +1,532 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Dec 28 15:18:46 GMT-0800 1997
+// Last Modified: Mon Jan 12 15:42:44 GMT-0800 1998
+// Last Modified: Tue Jun 29 13:10:30 PDT 1999 (verified sysex sending)
+// Last Modified: Tue Jun 4 22:10:16 PDT 2002 (getNumPorts fix for static use)
+// Filename: ...sig/code/control/MidiOutPort/visual/MidiOutPort_visual.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiOutPort_visual.cpp
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Windows 95/NT/98
+// using winmm.lib. Privately inherited by the
+// MidiOutPort class.
+//
+
+
+#ifdef VISUAL
+
+#include <iostream.h>
+#include "MidiOutPort_visual.h"
+
+typedef unsigned long ulong;
+typedef unsigned char uchar;
+
+
+// initialized static variables
+int MidiOutPort_visual::numDevices = 0;
+int MidiOutPort_visual::objectCount = 0;
+int* MidiOutPort_visual::openQ = NULL;
+int* MidiOutPort_visual::portObjectCount = NULL;
+HMIDIOUT* MidiOutPort_visual::device = NULL;
+int MidiOutPort_visual::channelOffset = 0;
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::MidiOutPort_visual
+// default values: autoOpen = 1
+//
+
+
+MidiOutPort_visual::MidiOutPort_visual(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiOutPort_visual::MidiOutPort_visual(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::~MidiOutPort_visual
+//
+
+MidiOutPort_visual::~MidiOutPort_visual() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ cerr << "Error: bad MidiOutPort object count!: " << objectCount << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::close
+//
+
+void MidiOutPort_visual::close(void) {
+ if (getPort() == -1) {
+ return;
+ }
+
+ if (getPortStatus() == 1 && device[getPort()] != NULL) {
+
+ // The following function, midiOutClose, is not what I like.
+ // It will send note offs to any note which it thinks is
+ // on when the port is closed. Uncomment the line if
+ // you want this feature.
+ // midiOutReset(device[getPort()]);
+
+ midiOutClose(device[getPort()]);
+ setPortStatus(0);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::closeAll
+//
+
+void MidiOutPort_visual::closeAll(void) {
+ for (int i=0; i<getNumPorts(); i++) {
+ if (openQ[i] == 1 && device[i] != NULL) {
+ midiOutReset(device[i]);
+ midiOutClose(device[i]);
+ openQ[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiOutPort_visual::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiOutPort_visual::getName(void) {
+ static MIDIOUTCAPS outputCapabilities;
+
+ if (getPort() == -1) {
+ return "Null MIDI Output";
+ }
+
+ if (openQ[getPort()]) { // port already open
+ midiOutGetDevCaps(getPort(), &outputCapabilities, sizeof(MIDIOUTCAPS));
+ } else { // port is currently closed
+ if(open()) {;
+ midiOutGetDevCaps(getPort(), &outputCapabilities, sizeof(MIDIOUTCAPS));
+ close();
+ } else {
+ return "";
+ }
+ }
+ return outputCapabilities.szPname;
+}
+
+
+const char* MidiOutPort_visual::getName(int i) {
+ static MIDIOUTCAPS outputCapabilities;
+
+ midiOutGetDevCaps(i, &outputCapabilities, sizeof(MIDIOUTCAPS));
+
+ return outputCapabilities.szPname;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getNumPorts -- returns the number of available
+// ports for MIDI output
+//
+
+int MidiOutPort_visual::getNumPorts(void) {
+ if (numDevices <= 0) {
+ return midiOutGetNumDevs();
+ }
+ return numDevices;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiOutPort_visual::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getPortStatus -- 0 if closed, 1 if open
+// 2 if null connection
+//
+
+int MidiOutPort_visual::getPortStatus(void) {
+ if (getPort() == -1) {
+ return 2;
+ }
+
+ if (openQ[getPort()] == 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getTrace -- returns true if trace is on or
+// false if off. If trace is on, then prints to standard output
+// the Midi message being sent.
+//
+
+int MidiOutPort_visual::getTrace(void) {
+ return trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::rawsend -- send the Midi command and its parameters
+//
+
+int MidiOutPort_visual::rawsend(int command, int p1, int p2) {
+ union { ulong word; uchar data[4]; } u;
+ u.data[0] = (uchar)command;
+ u.data[1] = (uchar)(p1 & 0x7f); // parameter limited to range 0-127;
+ u.data[2] = (uchar)(p2 & 0x7f); // parameter limited to range 0-127;
+ u.data[3] = 0;
+
+ if (getPort() == -1) {
+ return 2;
+ }
+
+ int flag = midiOutShortMsg(device[getPort()], u.word);
+
+ if (getTrace()) {
+ if (flag == MMSYSERR_NOERROR) {
+ cout << "(" << hex << (int)u.data[0] << dec << ":"
+ << (int)u.data[1] << "," << (int)u.data[2] << ")";
+ cout.flush();
+ } else {
+ cout << "(" << hex << (int)u.data[0] << dec << "X"
+ << (int)u.data[1] << "," << (int)u.data[2] << ")";
+ cout.flush();
+ }
+ }
+
+ return flag;
+}
+
+
+int MidiOutPort_visual::rawsend(int command, int p1) {
+ return rawsend(command, p1, 0);
+}
+
+
+int MidiOutPort_visual::rawsend(int command) {
+ return rawsend(command, 0, 0);
+}
+
+
+int MidiOutPort_visual::rawsend(uchar* array, int size) {
+ // Note: this function will work in Windows 95 and Windows NT.
+ // This function will not work in Windows 3.x because a
+ // different memory model is necessary.
+
+ if (size > 64000 || size < 1) {
+ cerr << "Warning: cannot write a MIDI stream larger than 64kB" << endl;
+ return 0;
+ }
+
+ MIDIHDR midiheader; // structure for sending an array of MIDI bytes
+
+ midiheader.lpData = (char *)array;
+ midiheader.dwBufferLength = size;
+ // midiheader.dwBytesRecorded = size; // example program doesn't set
+ midiheader.dwFlags = 0; // flags must be set to 0
+
+ if (getPort() == -1) {
+ return -1;
+ }
+
+ int status = midiOutPrepareHeader(device[getPort()], &midiheader,
+ sizeof(MIDIHDR));
+
+ if (status != MMSYSERR_NOERROR) {
+ return 0;
+ }
+
+ status = midiOutLongMsg(device[getPort()], &midiheader, sizeof(MIDIHDR));
+
+ if (status != MMSYSERR_NOERROR) {
+ return 0;
+ }
+
+ while (MIDIERR_STILLPLAYING == midiOutUnprepareHeader(device[getPort()],
+ &midiheader, sizeof(MIDIHDR))) {
+ Sleep(1); // sleep for 1 millisecond
+ }
+
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::open -- returns true if MIDI output port was
+// opened.
+//
+
+int MidiOutPort_visual::open(void) {
+ if (getPort() == -1) {
+ return 2;
+ }
+
+ if (getPortStatus() == 0) {
+ int flag;
+ flag = midiOutOpen(&device[getPort()], getPort(), 0, 0, CALLBACK_NULL);
+ if (flag == MMSYSERR_NOERROR) {
+ openQ[getPort()] = 1;
+ return 1;
+ } else { // faied to open
+ openQ[getPort()] = 0;
+ device[getPort()] = NULL;
+ return 0;
+ }
+ } else { // already open
+ return 1;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::setChannelOffset -- sets the MIDI channel offset,
+// either 0 or 1.
+//
+
+void MidiOutPort_visual::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ cout << "Error: Channel offset can be only 0 or 1." << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::setPort
+//
+
+void MidiOutPort_visual::setPort(int aPort) {
+ if (aPort < 0 || aPort >= getNumPorts()) {
+ cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ portObjectCount[port]++;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::setTrace -- if false, then won't print
+// Midi messages to standard output.
+//
+
+int MidiOutPort_visual::setTrace(int aState) {
+ int oldtrace = trace;
+ if (aState == 0) {
+ trace = 0;
+ } else {
+ trace = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::sysex -- send a system exclusive message.
+// The first byte of the message must be a 0xf0 byte.
+//
+
+int MidiOutPort_visual::sysex(uchar* array, int size) {
+ if (size == 0 || array[0] != 0xf0) {
+ cout << "Error: invalid system exclusive message,"
+ " first byte must be 0xf0" << endl;
+ exit(1);
+ }
+
+ return rawsend(array, size);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::toggleTrace
+//
+
+void MidiOutPort_visual::toggleTrace(void) {
+ trace = !trace;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_visual::deinitialize(void) {
+ closeAll();
+ if (device != NULL) delete [] device;
+ device = NULL;
+ if (openQ != NULL) delete [] openQ;
+ openQ = NULL;
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_visual::initialize(void) {
+ // get the number of ports
+ numDevices = midiOutGetNumDevs();
+ if (getNumPorts() <= 0) {
+ cerr << "Error: no MIDI output devices" << endl;
+ exit(1);
+ }
+
+ // allocate space for Windoze MIDI output structures
+ if (device != NULL) {
+ cerr << "Error: device array should be NULL when calling "
+ << "initialize() in MidiOutPort." << endl;
+ exit(1);
+ }
+ device = new HMIDIOUT[numDevices];
+
+ // allocate space for openQ, the port open/close status
+ if (openQ != NULL) delete [] openQ;
+ openQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ device[i] = NULL;
+ openQ[i] = 0;
+ portObjectCount[i] = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::setPortStatus
+//
+
+void MidiOutPort_visual::setPortStatus(int aStatus) {
+ if (getPort() == -1) {
+ return;
+ }
+
+ if (aStatus) {
+ openQ[getPort()] = 1;
+ } else {
+ openQ[getPort()] = 0;
+ }
+}
+
+
+#endif // VISUAL
+
+
+
+
+// md5sum: 8cb60bfb5dc9ea42808ffa4540e0fc52 - MidiOutPort_visual.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutput.cpp b/src/midiio/src/MidiOutput.cpp
new file mode 100644
index 0000000..d78460f
--- /dev/null
+++ b/src/midiio/src/MidiOutput.cpp
@@ -0,0 +1,1082 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 18 December 1997
+// Last Modified: Mon Jan 26 23:54:36 GMT-0800 1998
+// Last Modified: Tue Feb 2 08:30:28 PST 1999
+// Last Modified: Sun Jul 18 18:52:29 PDT 1999 (added RPN functions)
+// Last Modified: Sun Dec 9 15:01:33 PST 2001 (switched con/des code)
+// Filename: ...sig/code/control/MidiOutput/MidiOutput.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiOutput.cpp
+// Syntax: C++
+//
+// Description: The MIDI output interface for MIDI synthesizers/equipment
+// which has many convienience functions defined for
+// various types of MIDI output.
+//
+
+#include "MidiOutput.h"
+#include <iostream>
+#include <iomanip>
+
+#define RECORD_ASCII (0)
+#define RECORD_BINARY (1)
+#define RECORD_MIDI_FILE (2)
+
+
+// declaration of static variables
+SigTimer MidiOutput::timer;
+Array<int>* MidiOutput::rpn_lsb_status = NULL;
+Array<int>* MidiOutput::rpn_msb_status = NULL;
+int MidiOutput::objectCount = 0;
+
+
+//////////////////////////////
+//
+// MidiOutput::MidiOutput --
+//
+
+
+MidiOutput::MidiOutput(void) : MidiOutPort() {
+ outputRecordQ = 0;
+
+ if (objectCount == 0) {
+ initializeRPN();
+ }
+ objectCount++;
+}
+
+
+
+MidiOutput::MidiOutput(int aPort, int autoOpen) : MidiOutPort(aPort, autoOpen) {
+ outputRecordQ = 0;
+
+ if (objectCount == 0) {
+ initializeRPN();
+ }
+ objectCount++;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::~MidiOutput
+//
+
+MidiOutput::~MidiOutput() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitializeRPN();
+ } else if (objectCount < 0) {
+ std::cout << "Error in MidiOutput decontruction" << std::endl;
+ }
+
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::cont -- send a controller command MIDI message.
+//
+// channel = the Midi channel ofset from 0 [0..15]
+// controller = the continuous controller number [0..127]
+// data = the value of the specified controller [0..127]
+//
+
+int MidiOutput::cont(int channel, int controller, int data) {
+ return send(0xb0 | (channel & 0x0f), controller, data);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::off -- sends a Note Off MIDI message (0x80).
+//
+// channel = MIDI channel to send note on. range is [0..15]
+// keynum = MIDI key number to play (middle C = 60, C# = 61, etc.) [0..127]
+// velocity = release velocity of the note, 127 = quickest possible
+//
+// Note: The more common method of turning off a note is to use the
+// play() function (midi command 0x90) but send an attack velocity of 0.
+//
+
+int MidiOutput::off(int channel, int keynum, int releaseVelocity) {
+ return send(0x80 | (channel & 0x0f), keynum, releaseVelocity);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::pc -- send a patch change MIDI message. changes the timbre
+// on the specified channel.
+//
+// channel = MIDI channel to which to send the patch change [0..15]
+// timbre = the voice to select on the specified channel [0..127]
+//
+
+int MidiOutput::pc(int channel, int timbre) {
+ return send(0xc0 | (channel & 0x0f), timbre);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::play -- sends a Note On/Off MIDI message.
+//
+// channel = MIDI channel to send note on. range is [0..15]
+// keynum = MIDI key number to play (middle C = 60, C# = 61, etc.) [0..127]
+// velocity = attack velocity of the note, 0 = 0ff, 127 = loudest possible
+//
+
+int MidiOutput::play(int channel, int keynum, int velocity) {
+ return send(0x90 | (channel & 0x0f), keynum, velocity);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::pw -- Pitch Wheel: send a MIDI pitch bend.
+// Parameters are:
+// 1. channel -- MIDI channel offset from 0.
+// 2. mostByte -- most significant 7 bits (coarse tuning)
+// 3. leastByte -- least significant 7 bits (fine tuning)
+//
+
+int MidiOutput::pw(int channel, int mostByte, int leastByte) {
+ return send(0xe0 | (channel & 0x0f), leastByte, mostByte);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::pw -- Pitch Wheel: 14 bit number given as input
+// range for 14 bit number is 0 to 16383.
+//
+
+int MidiOutput::pw(int channel, int tuningData) {
+ uchar greaterBits = (uchar)((tuningData >> 7) & 0x7f);
+ uchar lesserBits = (uchar)(tuningData & 0x7f);
+ return pw(channel, greaterBits, lesserBits);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::pw -- Pitch Wheel: range between -1 to 1 given as input.
+// Range is then converted to a 14 bit number.
+// +1 = highest value of pitch wheel
+// 0 = rest position of pitch wheel
+// -1 = lowest value of pitch wheel
+//
+
+int MidiOutput::pw(int channel, double tuningData) {
+ if (tuningData < -1.0 || tuningData > 1.0) {
+ std::cerr << "Error: pitch wheel data is out of range: " << tuningData << std::endl;
+ exit(1);
+ }
+
+ int output = (int)((tuningData+1.0)/2.0*16383 + 0.5);
+ return pw(channel, output);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::recordStart
+//
+
+void MidiOutput::recordStart(char *filename, int format) {
+ if (outputRecordQ) { // already recording, so close old file
+ recordStop();
+ }
+
+ outputRecordFile.open(filename, std::ios::out);
+ if (!outputRecordFile) { // open file failed
+ std::cerr << "Error: cannot open file " << filename << std::endl;
+ outputRecordQ = 0;
+ } else {
+ outputRecordQ = 1;
+ }
+
+ if (outputRecordQ) {
+ switch (format) {
+ case RECORD_ASCII: // ascii
+ outputRecordType = RECORD_ASCII;
+ outputRecordFile <<"; delta time/MIDI output at delta time" << std::endl;
+ break;
+ case RECORD_BINARY: // binary
+ outputRecordType = RECORD_BINARY;
+ // record the magic number for binary format
+ outputRecordFile << (uchar)0xf8 << (uchar)0xf8
+ << (uchar)0xf8 << (uchar)0xf8;
+ break;
+ case RECORD_MIDI_FILE: // standard MIDI file, type 0
+ default:
+ outputRecordType = RECORD_MIDI_FILE;
+ // header stuff to be written here
+ break;
+ }
+ }
+
+ lastFlushTime = timer.getTime();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::recordStop
+//
+
+void MidiOutput::recordStop(void) {
+ if (outputRecordQ) {
+ outputRecordQ = 0;
+ outputRecordFile.close();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::reset -- sends the MIDI command 0xFF which
+// should force the MIDI devices on the other side of the
+// MIDI cable into their power-on reset condition, clear running
+// status, turn off any sounding notes, set Local Control on, and
+// otherwise clean up the state of things.
+//
+
+void MidiOutput::reset(void) {
+ send(0xff, 0, 0);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::send -- send a byte to the MIDI port but record it
+// first.
+//
+
+int MidiOutput::send(int command, int p1, int p2) {
+ if (outputRecordQ) {
+ switch (outputRecordType) {
+ case 0: // ascii
+ writeOutputAscii(command, p1, p2);
+ break;
+ case 1: // binary
+ writeOutputBinary(command, p1, p2);
+ break;
+ case 2: // standard MIDI file type 0
+ writeOutputMidifile(command, p1, p2);
+ break;
+ }
+ lastFlushTime = timer.getTime(); // only keep track if recording
+ }
+ return rawsend(command, p1, p2);
+}
+
+
+int MidiOutput::send(int command, int p1) {
+ if (outputRecordQ) {
+ switch (outputRecordType) {
+ case 0: // ascii
+ writeOutputAscii(command, p1, -1);
+ break;
+ case 1: // binary
+ writeOutputBinary(command, p1, -1);
+ break;
+ case 2: // standard MIDI file type 0
+ writeOutputMidifile(command, p1, -1);
+ break;
+ }
+ lastFlushTime = timer.getTime(); // only keep track if recording
+ }
+ return rawsend(command, p1);
+}
+
+
+int MidiOutput::send(int command) {
+ if (outputRecordQ) {
+ switch (outputRecordType) {
+ case 0: // ascii
+ writeOutputAscii(command, -1, -1);
+ break;
+ case 1: // binary
+ writeOutputBinary(command, -1, -1);
+ break;
+ case 2: // standard MIDI file type 0
+ writeOutputMidifile(command, -1, -1);
+ break;
+ }
+ lastFlushTime = timer.getTime(); // only keep track if recording
+ }
+ return rawsend(command);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::silence -- send a note off to all notes on all channels.
+// default value: aChannel = -1
+//
+
+void MidiOutput::silence(int aChannel) {
+ int keyno;
+ if (aChannel == -1) {
+ for (int channel=0; channel<16; channel++) {
+ for (keyno=0; keyno<128; keyno++) {
+ play(channel, keyno, 0);
+ }
+ }
+ } else {
+ for (keyno=0; keyno<128; keyno++) {
+ play(aChannel, keyno, 0);
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::sustain -- set the MIDI sustain continuous controller on or off.
+// Equivalent to the command cont(channel, 0x40, status).
+//
+
+void MidiOutput::sustain(int channel, int status) {
+ if (status) { // turn on sustain
+ cont(channel, 0x40, 127);
+ } else { // turn off sustain
+ cont(channel, 0x40, 0);
+ }
+}
+
+
+
+///////////////////////////////
+//
+// MidiOutput::sysex -- sends a system exclusive MIDI message.
+// you must supply the 0xf0 at the start of the array
+// and the 0xf7 at the end of the array.
+//
+
+int MidiOutput::sysex(char* data, int length) {
+ return rawsend((uchar*)data, length);
+}
+
+
+int MidiOutput::sysex(uchar* data, int length) {
+ return rawsend(data, length);
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// RPN functions
+//
+
+
+//////////////////////////////
+//
+// NRPN -- sends a Non-registered parameter number where:
+// parameter #1: channel (0-15)
+// parameter #2: NRPN MSB indicator (controller #99 data)
+// parameter #3: NRPN LSB indicator (controller #98 data)
+// parameter #4: NRPN MSB data (controller #6 data)
+// [parameter #5: NRPN LSB data (controller #38 data)]
+// or:
+// parameter #1: channel (0-15)
+// parameter #2: NRPN MSB indicator (controller #99 data)
+// parameter #3: NRPN LSB indicator (controller #98 data)
+// parameter #4: NRPN Floating point in range (-1..1) (ccont#6 and #38 data)
+//
+//
+// NRPN (Non-registered parameter number) -- General MIDI and
+// Extended MIDI mess. It becomes the receiving synthesizer's
+// responsibility to determine the meaning of continuous
+// controller (ccont) #6 from data sent with cconts #98,99 (for
+// NRPNS) and cconts #100,101 (for RPNS). NRPN parameters
+// are not reset when the ccont#121 is sent to reset controllers.
+//
+// NRPN's are "non-standard" meaning that any synthesizer could
+// do whatever they want with a given NRPN; However, the
+// GS and XG specifications are given in the table further below.
+//
+// The data for NRPNs are transfered to synthesizer with
+// data slider ccont #6(MSB) and ccont #38(LSB). Also data increment
+// ccont#96 (data increment) and ccont#97 (data decrement) are in
+// relation to the RPN or NRPN in effect. Increment and Decrement
+// are not recommend to use with RPN's because of confusion in the
+// MIDI industry over which 7-bit data (#6 or #38) to increment.
+//
+// Once you have selected an NRPN on a given channel, the
+// channel will apply subsequent Data Entry to the
+// selected parameter. After making the necessary settings
+// you should set NRPN to NULL to reduce the risk of
+// operational errors. a NUL RPN will disable the previous
+// values of either RPN or NRPN data.
+//
+// The following NRPN values are supported in Yamaha's XG specification:
+// CCont #98 = LSB of NRPN parameter ID
+// CCont #99 = MSB of NRPN parameter ID
+//
+// NRPN
+// MSB LSB Data Range
+// #99 #98 Parameter (ccont#6=MSB, ccont#38=LSB)
+// === ===== ====================== ======================
+// 1 8 Vibrato Rate -64.. 0..+63 logical range or (-50..+50)
+// 0..64..127 MIDI data range ( 14..114)
+// 1 9 Vibrato Depth same ranges as above
+// 1 10 Vibrato Delay same ranges as above
+// 1 32 Filter Cutoff Freq. same ranges as above
+// 1 33 Filter Resonance same ranges as above
+// 1 99 EG Attack Time same ranges as above
+// 1 100 EG Decay Time same ranges as above
+// 1 102 EG Release Time same ranges as above
+// 20 xx Drum Filter Cutoff Freq same ranges as above
+// xx = drum MIDI key number
+// 21 xx Drum Filter Resonance same ranges as above
+// xx = drum MIDI key number
+// 22 xx Drum EG Attack Rage same ranges as above
+// xx = drum MIDI key number
+// 23 xx Drum EG Decay Rate same ranges as above
+// xx = drum MIDI key number
+// 24 xx Drum Pitch Coarse same ranges as above
+// xx = drum MIDI key number
+// 25 xx Drum Pitch Fine same ranges as above
+// xx = drum MIDI key number
+// 26 xx Drum Level 0..64..127 MIDI data range
+// xx = drum MIDI key number
+// 28 xx Drum Pan Random, Left..Center..Right
+// 0.......1.....64......127 MIDI data range
+// xx = drum MIDI key number
+// 29 xx Drum Reverb Send Level 0..64..127 MIDI data range
+// xx = drum MIDI key number
+// 30 xx Drum Chorus Send Level 0..64..127 MIDI data range
+// xx = drum MIDI key number
+// 31 xx Drum Variation Send Level 0..64..127 MIDI data range
+// xx = drum MIDI key number
+// 127 127 Null RPN (disables RPN/NRPN parameters from being altered).
+//
+//
+
+int MidiOutput::NRPN(int channel, int nrpn_msb, int nrpn_lsb,
+ int data_msb, int data_lsb) {
+ channel = channel & 0x0f;
+ nrpn_msb = nrpn_msb & 0x7f;
+ nrpn_lsb = nrpn_msb & 0x7f;
+ data_msb = nrpn_msb & 0x7f;
+ data_lsb = nrpn_msb & 0x7f;
+
+ int status = 1;
+
+ // check to see if the nrpn_msb and nrpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != nrpn_msb) {
+ status &= cont(channel, 99, nrpn_msb);
+ rpn_msb_status[getPort()][channel] = nrpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != nrpn_lsb) {
+ status &= cont(channel, 98, nrpn_lsb);
+ rpn_lsb_status[getPort()][channel] = nrpn_lsb;
+ }
+
+ // now that the NRPN state is set, send the NRPN data values
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (nrpn_msb != 127 && nrpn_lsb != 127) {
+ status &= cont(channel, 6, data_msb);
+ status &= cont(channel, 38, data_msb);
+ }
+
+ return status;
+}
+
+
+int MidiOutput::NRPN(int channel, int nrpn_msb, int nrpn_lsb, int data_msb) {
+ channel = channel & 0x0f;
+ nrpn_msb = nrpn_msb & 0x7f;
+ nrpn_lsb = nrpn_msb & 0x7f;
+ data_msb = nrpn_msb & 0x7f;
+
+ int status = 1;
+
+ // check to see if the nrpn_msb and nrpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != nrpn_msb) {
+ status &= cont(channel, 99, nrpn_msb);
+ rpn_msb_status[getPort()][channel] = nrpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != nrpn_lsb) {
+ status &= cont(channel, 98, nrpn_lsb);
+ rpn_lsb_status[getPort()][channel] = nrpn_lsb;
+ }
+
+ // now that the NRPN state is set, send the NRPN data value,
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (nrpn_msb != 127 && nrpn_lsb != 127) {
+ status &= cont(channel, 6, data_msb);
+ }
+
+ return status;
+}
+
+
+int MidiOutput::NRPN(int channel, int nrpn_msb, int nrpn_lsb, double data) {
+ channel = channel & 0x0f;
+ nrpn_msb = nrpn_msb & 0x7f;
+ nrpn_lsb = nrpn_msb & 0x7f;
+ if (data < -1.0) {
+ data = -1.0;
+ } else if (data > 1.0) {
+ data = 1.0;
+ }
+
+ int status = 1;
+
+ // check to see if the nrpn_msb and nrpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != nrpn_msb) {
+ status &= cont(channel, 99, nrpn_msb);
+ rpn_msb_status[getPort()][channel] = nrpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != nrpn_lsb) {
+ status &= cont(channel, 98, nrpn_lsb);
+ rpn_lsb_status[getPort()][channel] = nrpn_lsb;
+ }
+
+ // convert data into 14 bit number
+ int data14 = (int)((data+1.0)/2.0*16383 + 0.5);
+
+ // send the NRPN data values, two message of 7 bits each
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (nrpn_msb != 127 && nrpn_lsb != 127) {
+ status &= cont(channel, 6, data14 >> 7);
+ status &= cont(channel, 38, data14 & 0x7f);
+ }
+
+ return status;
+}
+
+
+//////////
+//
+// Convenience functions for use of NRPN function. Note that these
+// are "Non-Registered" Parameter Numbers which means that each
+// synthesizer manufacture can do whatever they want, so these
+// functions might not behave the way you expect them to do so.
+// Yamaha XG and Roland GS NRPN specifications are given below.
+//
+
+int MidiOutput::NRPN_null(int channel) {
+ return NRPN(channel, 127, 127, 0);
+}
+
+int MidiOutput::NRPN_vibratoRate(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 8, value+64);
+}
+
+int MidiOutput::NRPN_vibratoRate(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 8, value);
+}
+
+int MidiOutput::NRPN_vibratoDepth(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 9, value+64);
+}
+
+int MidiOutput::NRPN_vibratoDepth(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 9, value);
+}
+
+int MidiOutput::NRPN_vibratoDelay(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 32, value+64);
+}
+
+int MidiOutput::NRPN_vibratoDelay(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 32, value);
+}
+
+int MidiOutput::NRPN_filterCutoff(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 33, value+64);
+}
+
+int MidiOutput::NRPN_filterCutoff(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 33, value);
+}
+
+int MidiOutput::NRPN_attack(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 99, value+64);
+}
+
+int MidiOutput::NRPN_attack(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 99, value);
+}
+
+int MidiOutput::NRPN_decay(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 100, value+64);
+}
+
+int MidiOutput::NRPN_decay(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 100, value);
+}
+
+int MidiOutput::NRPN_release(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 102, value+64);
+}
+
+int MidiOutput::NRPN_release(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 102, value);
+}
+
+int MidiOutput::NRPN_drumFilterCutoff(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 20, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumFilterCutoff(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 20, drum, value);
+}
+
+int MidiOutput::NRPN_drumFilterResonance(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 21, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumFilterResonance(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 21, drum, value);
+}
+
+int MidiOutput::NRPN_drumAttack(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 22, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumAttack(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 22, drum, value);
+}
+
+int MidiOutput::NRPN_drumDecay(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 23, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumDecay(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 23, drum, value);
+}
+
+int MidiOutput::NRPN_drumPitch(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 24, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumPitch(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 24, drum, value);
+}
+
+int MidiOutput::NRPN_drumLevel(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 26, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumLevel(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 26, drum, value);
+}
+
+int MidiOutput::NRPN_drumPan(int drum, int value) {
+ return NRPN(9, 28, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumPan(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 28, drum, value);
+}
+
+int MidiOutput::NRPN_drumReverb(int drum, int value) {
+ // note offset from 0 not -64
+ return NRPN(9, 29, drum, value);
+}
+
+int MidiOutput::NRPN_drumReverb(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 29, drum, value);
+}
+
+int MidiOutput::NRPN_drumChorus(int drum, int value) {
+ // note offset from 0 not -64
+ return NRPN(9, 30, drum, value);
+}
+
+int MidiOutput::NRPN_drumChorus(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 30, drum, value);
+}
+
+int MidiOutput::NRPN_drumVariation(int drum, int value) {
+ // note offset from 0 not -64
+ return NRPN(9, 31, drum, value);
+}
+
+int MidiOutput::NRPN_drumVariation(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 31, drum, value);
+}
+
+//
+// Convenience functions for use of NRPN function.
+//
+//////////
+
+
+
+//////////////////////////////
+//
+// RPN -- sends a registered parameter number where:
+// parameter #1: channel (0-15)
+// parameter #2: RPN MSB indicator (controller #101 data)
+// parameter #3: RPN LSB indicator (controller #100 data)
+// parameter #4: RPN MSB data (controller #6 data)
+// [parameter #5: RPN LSB data (controller #38 data)]
+// or:
+// parameter #1: channel (0-15)
+// parameter #2: NRPN MSB indicator (controller #99 data)
+// parameter #3: NRPN LSB indicator (controller #98 data)
+// parameter #4: NRPN Floating point in range (-1..1) (ccont#6 and #38 data)
+//
+//
+// RPN (registered parameter number) -- General MIDI and
+// Extended MIDI mess. It becomes the receiving synthesizer's
+// responsibility to determine the meaning of continuous
+// controller (ccont) #6 from data sent with cconts #100,101 (for
+// RPNS) and cconts #98,99 (for NRPNS).
+//
+// The data for RPNs are transfered to synthesizer with
+// data slider ccont #6(MSB) and ccont #38(LSB). Also data increment
+// ccont#96 (data increment) and ccont#97 (data decrement) are in
+// relation to the RPN or NRPN in effect. Increment and Decrement
+// are not recommend to use with RPN's because of confusion in the
+// MIDI industry over which 7-bit data (#6 or #38) to increment.
+//
+// Once you have selected an RPN on a given channel, the
+// channel will apply subsequent Data Entry to the
+// selected parameter. After making the necessary settings
+// you should set RPN's to NULL to reduce the risk of
+// operational errors. a NULL RPN will disable the previous
+// values of either RPN or NRPN data.
+//
+// The following RPN values are registered:
+// CCont #100 = LSB of RPN parameter ID
+// CCont #101 = MSB of RPN parameter ID
+//
+// RPN Data Range
+// MSB LSB Parameter (ccont#6=MSB, ccont#38=LSB)
+// === ===== ====================== ======================
+
+// 0 0 Pitchbend Sensitivity 0-127 (default 2) (LSB ignored)
+// (The number of +/- half steps in
+// pitch wheel range).
+// 0 1 Fine Tune -64.. 0..+63 logical range
+// 0..64..127 MIDI data range
+// 0 2 Coarse Tune same range as above.
+// 0 3 Change Tuning Program 0..127
+// 0 4 Change Tuning Bank 0..127
+//
+
+int MidiOutput::RPN(int channel, int rpn_msb, int rpn_lsb,
+ int data_msb, int data_lsb) {
+ channel = channel & 0x0f;
+ rpn_msb = rpn_msb & 0x7f;
+ rpn_lsb = rpn_msb & 0x7f;
+ data_msb = rpn_msb & 0x7f;
+ data_lsb = rpn_msb & 0x7f;
+
+ int status = 1;
+
+ // check to see if the rpn_msb and rpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != rpn_msb) {
+ status &= cont(channel, 101, rpn_msb);
+ rpn_msb_status[getPort()][channel] = rpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != rpn_lsb) {
+ status &= cont(channel, 100, rpn_lsb);
+ rpn_lsb_status[getPort()][channel] = rpn_lsb;
+ }
+
+ // now that the RPN state is set, send the RPN data values
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (rpn_msb != 127 && rpn_lsb != 127) {
+ status &= cont(channel, 6, data_msb);
+ status &= cont(channel, 38, data_msb);
+ }
+
+ return status;
+}
+
+
+int MidiOutput::RPN(int channel, int rpn_msb, int rpn_lsb, int data_msb) {
+ channel = channel & 0x0f;
+ rpn_msb = rpn_msb & 0x7f;
+ rpn_lsb = rpn_msb & 0x7f;
+ data_msb = rpn_msb & 0x7f;
+
+ int status = 1;
+
+ // check to see if the rpn_msb and rpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != rpn_msb) {
+ status &= cont(channel, 101, rpn_msb);
+ rpn_msb_status[getPort()][channel] = rpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != rpn_lsb) {
+ status &= cont(channel, 100, rpn_lsb);
+ rpn_lsb_status[getPort()][channel] = rpn_lsb;
+ }
+
+ // now that the RPN state is set, send the RPN data value,
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (rpn_msb != 127 && rpn_lsb != 127) {
+ status &= cont(channel, 6, data_msb);
+ }
+
+ return status;
+}
+
+
+int MidiOutput::RPN(int channel, int rpn_msb, int rpn_lsb, double data) {
+ channel = channel & 0x0f;
+ rpn_msb = rpn_msb & 0x7f;
+ rpn_lsb = rpn_msb & 0x7f;
+ if (data < -1.0) {
+ data = -1.0;
+ } else if (data > 1.0) {
+ data = 1.0;
+ }
+
+ int status = 1;
+
+ // check to see if the rpn_msb and rpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != rpn_msb) {
+ status &= cont(channel, 101, rpn_msb);
+ rpn_msb_status[getPort()][channel] = rpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != rpn_lsb) {
+ status &= cont(channel, 100, rpn_lsb);
+ rpn_lsb_status[getPort()][channel] = rpn_lsb;
+ }
+
+ // convert data into 14 bit number
+ int data14 = (int)((data+1.0)/2.0*16383 + 0.5);
+
+ // send the RPN data values, two message of 7 bits each
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (rpn_msb != 127 && rpn_lsb != 127) {
+ status &= cont(channel, 6, data14 >> 7);
+ status &= cont(channel, 38, data14 & 0x7f);
+ }
+
+ return status;
+}
+
+
+//////////
+//
+// Convenience functions for use of RPN function.
+//
+
+int MidiOutput::RPN_null(void) {
+ int status = 1;
+ for (int i=0; i<16; i++) {
+ status &= RPN_null(i);
+ }
+ return status;
+}
+
+int MidiOutput::RPN_null(int channel) {
+ return RPN(channel, 127, 127, 0);
+}
+
+int MidiOutput::pbRange(int channel, int steps) {
+ // default value for pitch bend sensitivity is 2 semitones.
+ return RPN(channel, 0, 0, steps);
+}
+
+int MidiOutput::tuneFine(int channel, int cents) {
+ // data from -64 to + 63
+ return RPN(channel, 0, 1, cents+64);
+}
+
+int MidiOutput::fineTune(int channel, int cents) {
+ return tuneFine(channel, cents);
+}
+
+int MidiOutput::tuneCoarse(int channel, int steps) {
+ // data from -64 to + 63
+ return RPN(channel, 0, 1, steps+64);
+}
+
+int MidiOutput::coarseTune(int channel, int steps) {
+ return tuneCoarse(channel, steps);
+}
+
+int MidiOutput::tuningProgram(int channel, int program) {
+ return RPN(channel, 0, 3, program);
+}
+
+int MidiOutput::tuningBank(int channel, int bank) {
+ return RPN(channel, 0, 4, bank);
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+
+//////////////////////////////
+//
+// MidiOutput::initializeRPN -- set up the RPN status arrays
+// ignores initiaization request if already initialized.
+//
+
+void MidiOutput::initializeRPN(void) {
+ int i, channel;
+
+ if (rpn_lsb_status == NULL) {
+ rpn_lsb_status = new Array<int>[getNumPorts()];
+ for (i=0; i<getNumPorts(); i++) {
+ rpn_lsb_status[i].setSize(16);
+ rpn_lsb_status[i].allowGrowth(0);
+ for (channel=0; channel<16; channel++) {
+ rpn_lsb_status[i][channel] = 127;
+ }
+ }
+ }
+
+ if (rpn_msb_status == NULL) {
+ rpn_msb_status = new Array<int>[getNumPorts()];
+ for (i=0; i<getNumPorts(); i++) {
+ rpn_msb_status[i].setSize(16);
+ rpn_msb_status[i].allowGrowth(0);
+ for (channel=0; channel<16; channel++) {
+ rpn_msb_status[i][channel] = 127;
+ }
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::deinitializeRPN -- destroy the RPN status arrays
+// do nothing if the arrays are not initialized
+//
+
+void MidiOutput::deinitializeRPN(void) {
+ if (rpn_msb_status != NULL) {
+ delete [] rpn_msb_status;
+ rpn_msb_status = NULL;
+ }
+
+ if (rpn_msb_status != NULL) {
+ delete [] rpn_msb_status;
+ rpn_msb_status = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::writeOutputAscii
+//
+
+void MidiOutput::writeOutputAscii(int command, int p1, int p2) {
+ outputRecordFile << std::dec;
+ outputRecordFile.width(6);
+ outputRecordFile << (timer.getTime()-lastFlushTime) <<'\t';
+ outputRecordFile << "0x" << std::hex;
+ outputRecordFile.width(2);
+ outputRecordFile << command << ' ';
+ outputRecordFile << std::dec;
+ outputRecordFile.width(3);
+ outputRecordFile << p1 << ' ';
+ outputRecordFile << std::dec;
+ outputRecordFile.width(3);
+ outputRecordFile<< p2;
+ outputRecordFile << std::endl;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::writeOutputBinary
+//
+
+void MidiOutput::writeOutputBinary(int command, int p1, int p2) {
+ // don't store 0xf8 command since it will be used to mark the end of the
+ if (command == 0xf8) return;
+
+ // write the delta time (four bytes)
+ outputRecordFile.writeBigEndian((ulong)(timer.getTime() - lastFlushTime));
+
+ // write midi data
+ // don't store 0xf8 command since it will be used to mark the end of the
+ // delta time data.
+ outputRecordFile << (uchar)p1;
+ outputRecordFile << (uchar)p2;
+ outputRecordFile << (uchar)0xf8;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::writeOutputMidifile
+//
+
+void MidiOutput::writeOutputMidifile(int command, int p1, int p2) {
+ // not yet implemented
+}
+
+
+
+// md5sum: 1c518e5130ac9ba0d79c4e9ce7fa41cf - MidiOutput.cpp =css= 20030102
diff --git a/src/midiio/src/MidiPort.cpp b/src/midiio/src/MidiPort.cpp
new file mode 100644
index 0000000..1a03dac
--- /dev/null
+++ b/src/midiio/src/MidiPort.cpp
@@ -0,0 +1,189 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Fri Jan 23 10:24:35 GMT-0800 1998
+// Filename: .../sig/code/control/MidiPort/MidiPort.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiPort.cpp
+// Syntax: C++
+//
+// Description: A unified object that handles basic MIDI input and output.
+// Derived from the MidiInPort and MidiOutPort classes.
+//
+
+#include "MidiPort.h"
+
+
+//////////////////////////////
+//
+// MidiPort::MidiPort
+//
+
+MidiPort::MidiPort(void) : MidiOutPort(), MidiInPort() {
+ // nothing
+}
+
+
+MidiPort::MidiPort(int outputPort, int inputPort) :
+ MidiOutPort(outputPort), MidiInPort(inputPort) {
+ // nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::~MidiPort
+//
+
+MidiPort::~MidiPort() {
+ // nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getChannelInOffset -- return the MIDI channel offset of
+// the MIDI input.
+//
+
+int MidiPort::getChannelInOffset(void) const {
+ return MidiInPort::getChannelOffset();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getChannelOutOffset -- return the MIDI channel offset of
+// the MIDI output.
+//
+
+int MidiPort::getChannelOutOffset (void) const {
+ return MidiOutPort::getChannelOffset();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getInputPort
+//
+
+int MidiPort::getInputPort(void) {
+ return MidiInPort::getPort();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getInputTrace
+//
+
+int MidiPort::getInputTrace(void) {
+ return MidiInPort::getTrace();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getOutputPort
+//
+
+int MidiPort::getOutputPort(void) {
+ return MidiOutPort::getPort();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getOutputTrace
+//
+
+int MidiPort::getOutputTrace(void) {
+ return MidiOutPort::getTrace();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::setChannelOffset -- sets the MIDI channel offset
+//
+
+void MidiPort::setChannelOffset(int anOffset) {
+ MidiInPort::setChannelOffset(anOffset);
+ MidiOutPort::setChannelOffset(anOffset);
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::setInputPort
+//
+
+void MidiPort::setInputPort(int aPort) {
+ MidiInPort::setPort(aPort);
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::setInputTrace
+//
+
+int MidiPort::setInputTrace(int aState) {
+ return MidiInPort::setTrace(aState);
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::setOutputPort
+//
+
+void MidiPort::setOutputPort(int aPort) {
+ MidiOutPort::setPort(aPort);
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::setOutputTrace
+//
+
+int MidiPort::setOutputTrace(int aState) {
+ return MidiOutPort::setTrace(aState);
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::toggleInputTrace
+//
+
+void MidiPort::toggleInputTrace(void) {
+ MidiInPort::toggleTrace();
+}
+
+
+//////////////////////////////
+//
+// MidiPort::toggleOutputTrace
+//
+
+void MidiPort::toggleOutputTrace(void) {
+ MidiOutPort::toggleTrace();
+}
+
+
+
+// md5sum: c2583f3ed21e238ba6b298915cb728aa - MidiPort.cpp =css= 20030102
diff --git a/src/midiio/src/Options.cpp b/src/midiio/src/Options.cpp
new file mode 100644
index 0000000..0341fe3
--- /dev/null
+++ b/src/midiio/src/Options.cpp
@@ -0,0 +1,887 @@
+//
+// Copyright 1998-2000 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Apr 5 13:07:18 PDT 1998
+// Last Modified: Sat Mar 27 18:17:06 PST 1999
+// Last Modified: Thu Apr 13 14:02:52 PDT 2000 (added 2nd define function)
+// Last Modified: Fri May 5 17:52:01 PDT 2000 (added --options suppression)
+// Last Modified: Tue May 1 01:25:58 PDT 2001 (fixed getArgumentCount())
+// Filename: ...sig/maint/code/sigBase/Options.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/Options.cpp
+// Documentation: http://sig.sapp.org/doc/classes/Options
+// Syntax: C++
+//
+// Description: Handles command-line options in a graceful manner.
+//
+
+int optionListCompare(const void* a, const void* b);
+
+#include "Options.h"
+#include "Options_private.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <iostream>
+
+
+//////////////////////////////
+//
+// Options::Options --
+//
+
+Options::Options(void) {
+ optionFlag = '-';
+ gargc = -1;
+ gargv = NULL;
+ argument.setSize(0);
+ argument.allowGrowth();
+ optionRegister.setSize(0);
+ optionRegister.allowGrowth();
+ optionList.setSize(0);
+ optionList.allowGrowth();
+ processedQ = 0;
+ sortedQ = 0;
+ commandString = NULL;
+ options_error_check = 1;
+ suppressQ = 0;
+ optionsArgument = 0;
+}
+
+
+Options::Options(int argc, char** argv) {
+ optionFlag = '-';
+ gargc = -1;
+ gargv = NULL;
+ argument.setSize(0);
+ argument.allowGrowth();
+ optionRegister.setSize(0);
+ optionRegister.allowGrowth();
+ optionList.setSize(0);
+ optionList.allowGrowth();
+ processedQ = 0;
+ sortedQ = 0;
+ commandString = NULL;
+ options_error_check = 1;
+ suppressQ = 0;
+ optionsArgument = 0;
+
+ setOptions(argc, argv);
+}
+
+
+
+//////////////////////////////
+//
+// Options::~Options --
+//
+
+Options::~Options() {
+ reset();
+}
+
+
+
+//////////////////////////////
+//
+// Options::argc -- returns the argument count as from main().
+//
+
+int Options::argc(void) const {
+ return gargc;
+}
+
+
+
+//////////////////////////////
+//
+// Options::argv -- returns the arguments strings as from main().
+//
+
+char** Options::argv(void) const {
+ return gargv;
+}
+
+
+
+//////////////////////////////
+//
+// Options::define -- define an option entry in the option register
+//
+
+void Options::define(const char* aDefinition) {
+ sortedQ = 0; // have to sort option list later
+ option_register* definitionEntry;
+ option_list* optionListEntry;
+
+
+ // error if the definition string doesn't contain an equals sign.
+ if (strchr(aDefinition, '=') == NULL) {
+ std::cout << "Error: no \"=\" in option definition: " << aDefinition << std::endl;
+ exit(1);
+ }
+
+ // get the length of the definition string
+ int len = strlen(aDefinition);
+
+ // put space before and after the equals sign so that strtok works
+ char* definitionString;
+ definitionString = new char[len + 3];
+ int i = 0;
+ while (aDefinition[i] != '=' && i < len) {
+ definitionString[i] = aDefinition[i];
+ i++;
+ }
+ definitionString[i] = ' ';
+ i++;
+ definitionString[i] = '=';
+ i++;
+ definitionString[i] = ' ';
+ for (int k=i; k<len+2; k++) {
+ definitionString[k+1] = aDefinition[k-1];
+ }
+ len += 2;
+
+ // determine the registry index for the definition
+ int definitionIndex = optionRegister.getSize();
+
+
+ // set up space for a definition entry
+ definitionEntry = new option_register(aDefinition, OPTION_UNKNOWN_TYPE,
+ "", NULL);
+
+
+ char *tempstr; // temporary storage for strtok use on defaultString
+ tempstr = new char[len + 1];
+ strncpy(tempstr, definitionString, len);
+
+ char *optionName; // option name to add to list
+
+ // get the first option name
+ optionName = strtok(tempstr, " \t\n|");
+ if (optionName[0] == '=') {
+ std::cout << "Error: must specify an option name in definition: "
+ << aDefinition << std::endl;
+ exit(1);
+ }
+ // store an entry for each option name alias
+ const char* tempsearch;
+ while (optionName != NULL && optionName[0] != '=') {
+ tempsearch = getDefinition(optionName);
+ if (tempsearch != NULL) {
+ std::cerr << "option name \"" << optionName
+ << "\" from definition: " << aDefinition << std::endl;
+ std::cerr << "is already defined in definition: "
+ << tempsearch << std::endl;
+ exit(1);
+ }
+ optionListEntry = new option_list(optionName, definitionIndex);
+ optionList.append(optionListEntry);
+ optionName = strtok(NULL, " \t\n|");
+ }
+ if (optionName == NULL) {
+ std::cout << "Error: unknown error in definition: " << aDefinition << std::endl;
+ exit(1);
+ }
+
+ // now process the option type and any default value.
+ i = 0;
+
+ // find the equals sign
+ while (definitionString[i] != '=' && i < len) {
+ i++;
+ }
+ i++;
+ // skip over any white space
+ while (isspace(definitionString[i]) && i < len) {
+ i++;
+ }
+
+ // this character must be the option type
+ char optionType = (char)tolower(definitionString[i]);
+ definitionEntry->setType(optionType);
+ i++;
+
+
+ // check to make sure that the type is correct.
+ if (optionType != OPTION_STRING_TYPE &&
+ optionType != OPTION_INT_TYPE &&
+ optionType != OPTION_FLOAT_TYPE &&
+ optionType != OPTION_DOUBLE_TYPE &&
+ optionType != OPTION_BOOLEAN_TYPE &&
+ optionType != OPTION_CHAR_TYPE ) {
+ std::cout << "Error: unknown option type \'" << optionType
+ << "\' in defintion: " << aDefinition << std::endl;
+ exit(1);
+ }
+
+ // skip any white space after option type.
+ while (isspace(definitionString[i]) && i < len) {
+ i++;
+ }
+
+
+ // there can only be two characters now: '\0' or ':'
+ if (i >= len || definitionString[i] == '\0') {
+ goto option_finish;
+ } else if (i<len && definitionString[i] == ':') {
+ i++;
+ } else {
+ std::cout << "Unknown error in definition: " << aDefinition << std::endl;
+ exit(1);
+ }
+
+
+ // now proces the default string. store it in a temp storage for copying
+
+ // skip any white space after option type.
+ while (i < len && isspace(definitionString[i])) {
+ i++;
+ }
+ if (i >= len || definitionString[i] == '\0') {
+ goto option_finish;
+ }
+
+
+ // now at beginnng of default option string which continues
+ // until the end of the definition string.
+ definitionEntry->setDefault(&definitionString[i]);
+
+option_finish:
+
+ optionRegister.append(definitionEntry);
+
+
+ delete [] definitionString;
+ delete [] tempstr;
+
+}
+
+
+void Options::define(const char* aDefinition, const char* description) {
+ define(aDefinition);
+
+ // now find some place to store the description...
+}
+
+
+
+//////////////////////////////
+//
+// Options::getArg -- returns the specified argument.
+// argurment 0 is the command name.
+//
+
+char* Options::getArg(int index) {
+ if (index < 0 || index >= argument.getSize()) {
+ std::cout << "Error: argument " << index << " does not exist." << std::endl;
+ exit(1);
+ }
+ return argument[index];
+}
+
+
+
+//////////////////////////////
+//
+// Options::getArgument -- same as getArg
+//
+
+char* Options::getArgument(int index) {
+ return getArg(index);
+}
+
+
+
+//////////////////////////////
+//
+// Options::getArgCount -- number of arguments on command line.
+// does not count the options or the command name.
+//
+
+int Options::getArgCount(void) {
+ return argument.getSize() - 1;
+}
+
+
+
+//////////////////////////////
+//
+// Options::getArgumentCount -- Same as getArgCount().
+//
+
+int Options::getArgumentCount(void) {
+ return getArgCount();
+}
+
+
+
+//////////////////////////////
+//
+// Options::getBoolean -- returns true if the option was
+// used on the command line.
+//
+
+int Options::getBoolean(const char* optionName) {
+ int index = getRegIndex(optionName);
+ if (index < 0) {
+ return 0;
+ }
+ if (optionRegister[index]->getModifiedQ() == 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::getCommand -- returns argv[0]
+//
+
+const char* Options::getCommand(void) {
+ if (argument.getSize() == 0) {
+ return "";
+ } else {
+ return argument[0];
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::getCommandLine -- returns a string which contains the
+// command-line call to the program.
+//
+
+const char* Options::getCommandLine(void) {
+ if (commandString != NULL) {
+ return commandString;
+ }
+
+ int length = 0;
+ int i;
+ for (i=0; i<gargc; i++) {
+ length += strlen(gargv[i]) + 1;
+ }
+ length--; // remove the last space
+ commandString = new char[length + 1];
+ strcpy(commandString, gargv[0]);
+ for (i=1; i<gargc; i++) {
+ strcat(commandString, " ");
+ strcat(commandString, gargv[i]);
+ }
+
+ return commandString;
+}
+
+
+
+
+//////////////////////////////
+//
+// Options::getDefinition -- returns the definition
+// for the specified option name. Returns NULL
+// if there is no entry for the option name.
+// It is assumed that the option list is unsorted.
+// spaces count in the input option name.
+//
+
+const char* Options::getDefinition(const char* optionName) {
+ int i;
+ for (i=0; i<optionList.getSize(); i++) {
+ if (strcmp(optionName, optionList[i]->getName()) == 0) {
+ return optionRegister[optionList[i]->getIndex()]->getDefinition();
+ }
+ }
+ return (const char*)NULL;
+}
+
+
+
+//////////////////////////////
+//
+// Options::getDouble -- returns the double float associated
+// with the given option. Returns 0 if there is no
+// number associated with the option.
+//
+
+double Options::getDouble(const char* optionName) {
+ return strtod(getString(optionName), (char**)NULL);
+}
+
+
+
+//////////////////////////////
+//
+// Options::getFlag --
+//
+
+char Options::getFlag(void) {
+ return optionFlag;
+}
+
+
+
+//////////////////////////////
+//
+// Options::getFloat -- returns the floating point number
+// associated with the given option.
+//
+
+float Options::getFloat(const char* optionName) {
+ return (float)getDouble(optionName);
+}
+
+
+
+//////////////////////////////
+//
+// Options::getInt -- returns the integer argument. Can handle
+// hexadecimal, decimal, and octal written in standard
+// C syntax.
+//
+
+int Options::getInt(const char* optionName) {
+ return (int)strtol(getString(optionName), (char**)NULL, 0);
+}
+
+int Options::getInteger(const char* optionName) {
+ return getInt(optionName);
+}
+
+
+
+//////////////////////////////
+//
+// Options::getString --
+//
+
+const char* Options::getString(const char* optionName) {
+ int index = getRegIndex(optionName);
+ if (index < 0) {
+ return "UNKNOWN OPTION";
+ } else {
+ return optionRegister[index]->getOption();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::optionsArg -- returns true if the --options is present
+// on the command line, otherwise returns false.
+//
+
+int Options::optionsArg(void) {
+ return optionsArgument;
+}
+
+
+
+//////////////////////////////
+//
+// Options::print --
+//
+
+void Options::print(void) {
+ for (int i=0; i<optionRegister.getSize(); i++) {
+ std::cout << optionRegister[i]->getDefinition() << std::endl;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::reset --
+//
+
+void Options::reset(void) {
+ int i;
+ for (i=0; i<optionRegister.getSize(); i++) {
+ delete optionRegister[i];
+ }
+ optionRegister.setSize(0);
+ for (i=0; i<optionList.getSize(); i++) {
+ delete optionList[i];
+ }
+ optionList.setSize(0);
+ for (i=0; i<argument.getSize(); i++) {
+ delete [] argument[i];
+ }
+ argument.setSize(0);
+
+ if (commandString != NULL) {
+ delete [] commandString;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::setFlag -- set the character used to indicate an
+// option. For unix this is usually '-', in MS-DOS,
+// this is usually '/'; But the syntax of the Options
+// class is for Unix-style options.
+//
+
+void Options::setFlag(char aFlag) {
+ optionFlag = aFlag;
+}
+
+
+
+
+//////////////////////////////
+//
+// setModified --
+//
+
+void Options::setModified(const char* optionName, const char* aString) {
+ int index = getRegIndex(optionName);
+ if (index < 0) {
+ return;
+ }
+
+ optionRegister[getRegIndex(optionName)]->setModified(aString);
+}
+
+
+
+
+//////////////////////////////
+//
+// setOptions --
+//
+
+void Options::setOptions(int argc, char** argv) {
+ processedQ = 0;
+
+ gargc = argc;
+ gargv = argv;
+}
+
+
+
+//////////////////////////////
+//
+// Options:getType -- returns the type of the option
+//
+
+char Options::getType(const char* optionName) {
+ int index = getRegIndex(optionName);
+ if (index < 0) {
+ return -1;
+ } else {
+ return optionRegister[getRegIndex(optionName)]->getType();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::process -- same as verify
+// default values: error_check = 1, suppress = 0;
+//
+
+void Options::process(int argc, char** argv, int error_check, int suppress) {
+ setOptions(argc, argv);
+ verify(error_check, suppress);
+}
+
+
+void Options::process(int error_check, int suppress) {
+ verify(error_check, suppress);
+}
+
+
+
+//////////////////////////////
+//
+// Options::verify --
+// default value: error_check = 1, suppress = 0;
+//
+
+void Options::verify(int error_check, int suppress) {
+ options_error_check = error_check;
+ int gargp = 1;
+ int optionend = 0;
+
+ if (suppress) {
+ suppressQ = 1;
+ } else {
+ suppressQ = 0;
+ }
+
+ // if calling verify again, must remove previous argument list.
+ if (argument.getSize() != 0) {
+ for (int j=0; j<argument.getSize(); j++) {
+ delete argument[j];
+ }
+ argument.setSize(0);
+ }
+
+ char* tempargument;
+ tempargument = new char[strlen(gargv[0])+1];
+ strcpy(tempargument, gargv[0]);
+ argument.append(tempargument);
+
+ int oldgargp;
+ int position = 0;
+ int running = 0;
+ while (gargp < gargc && optionend == 0) {
+ if (optionQ(gargv[gargp], gargp)) {
+ oldgargp = gargp;
+ gargp = storeOption(gargp, position, running);
+ if (gargp != oldgargp) {
+ running = 0;
+ position = 0;
+ }
+ } else {
+ if ( strlen(gargv[gargp]) == 2 && gargv[gargp][0] == getFlag() &&
+ gargv[gargp][2] == getFlag() ) {
+ optionend = 1;
+ gargp++;
+ break;
+ } else { // this is an argument
+ tempargument = new char[strlen(gargv[gargp])+1];
+ strcpy(tempargument, gargv[gargp]);
+ argument.append(tempargument);
+ gargp++;
+ }
+ }
+ }
+
+ while (gargp < gargc) {
+ tempargument = new char[strlen(gargv[gargp])+1];
+ strcpy(tempargument, gargv[gargp]);
+ argument.append(tempargument);
+ gargp++;
+ }
+
+}
+
+
+void Options::verify(int argc, char** argv, int error_check, int suppress) {
+ setOptions(argc, argv);
+ verify(error_check, suppress);
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+
+//////////////////////////////
+//
+// getRegIndex -- returns the index of the option associated
+// with this name.
+//
+
+int Options::getRegIndex(const char* optionName) {
+ if (suppressQ && strcmp("options", optionName) == 0) {
+ return -1;
+ }
+
+ if (sortedQ == 0) {
+ sortOptionNames();
+ }
+ option_list key(optionName, -1);
+ option_list* keyp = &key;
+ void* searchresult;
+ searchresult = bsearch(&keyp, optionList.getBase(),
+ optionList.getSize(), sizeof(option_list*), optionListCompare);
+ if (searchresult != NULL) {
+ return (*((option_list**)searchresult))->getIndex();
+ } else if (strcmp("options", optionName) == 0) {
+ print();
+ exit(1);
+ }
+
+ if (options_error_check) {
+ std::cout << "Error: unknown option \"" << optionName << "\"." << std::endl;
+ print();
+ exit(1);
+ }
+
+ return -1;
+}
+
+
+
+//////////////////////////////
+//
+// optionQ -- returns true if the string is an option
+// "--" is not an option, also '-' is not an option.
+// aString is assumed to not be NULL.
+//
+
+int Options::optionQ(const char* aString, int& argp) {
+ if (aString[0] == getFlag()) {
+ if (aString[1] == '\0') {
+ argp++;
+ return 0;
+ } else if (aString[1] == getFlag()) {
+ if (aString[2] == '\0') {
+ argp++;
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ return 1;
+ }
+ } else {
+ return 0;
+ }
+}
+
+
+
+
+//////////////////////////////
+//
+// sortOptionNames --
+//
+
+void Options::sortOptionNames(void) {
+ qsort(optionList.getBase(), optionList.getSize(),
+ sizeof(option_list*), optionListCompare);
+ sortedQ = 1;
+}
+
+
+
+//////////////////////////////
+//
+// storeOption --
+//
+
+#define OPTION_FORM_SHORT 0
+#define OPTION_FORM_LONG 1
+#define OPTION_FORM_CONTINUE 2
+
+int Options::storeOption(int gargp, int& position, int& running) {
+ int optionForm;
+ char tempname[1024];
+ char optionType = '\0';
+
+ if (running) {
+ optionForm = OPTION_FORM_CONTINUE;
+ } else if (gargv[gargp][1] == getFlag()) {
+ optionForm = OPTION_FORM_LONG;
+ } else {
+ optionForm = OPTION_FORM_SHORT;
+ }
+
+ switch (optionForm) {
+ case OPTION_FORM_CONTINUE:
+ position++;
+ tempname[0] = gargv[gargp][position];
+ tempname[1] = '\0';
+ optionType = getType(tempname);
+ if (optionType != OPTION_BOOLEAN_TYPE) {
+ running = 0;
+ position++;
+ }
+ break;
+ case OPTION_FORM_SHORT:
+ position = 1;
+ tempname[0] = gargv[gargp][position];
+ tempname[1] = '\0';
+ optionType = getType(tempname);
+ if (optionType != OPTION_BOOLEAN_TYPE) {
+ position++;
+ }
+ break;
+ case OPTION_FORM_LONG:
+ position = 2;
+ while (gargv[gargp][position] != '=' &&
+ gargv[gargp][position] != '\0') {
+ tempname[position-2] = gargv[gargp][position];
+ position++;
+ }
+ tempname[position-2] = '\0';
+ optionType = getType(tempname);
+ if (optionType == -1) { // suppressed --options option
+ optionsArgument = 1;
+ break;
+ }
+ if (gargv[gargp][position] == '=') {
+ if (optionType == OPTION_BOOLEAN_TYPE) {
+ std::cout << "Error: boolean variable cannot have any options: "
+ << tempname << std::endl;
+ exit(1);
+ }
+ position++;
+ }
+ break;
+ }
+
+ if (optionType == -1) { // suppressed --options option
+ optionsArgument = 1;
+ gargp++;
+ position = 0;
+ return gargp;
+ }
+
+ if (gargv[gargp][position] == '\0' &&
+ optionType != OPTION_BOOLEAN_TYPE) {
+ gargp++;
+ position = 0;
+ }
+
+ if (optionForm != OPTION_FORM_LONG && optionType == OPTION_BOOLEAN_TYPE &&
+ gargv[gargp][position+1] != '\0') {
+ running = 1;
+ } else if (optionType == OPTION_BOOLEAN_TYPE &&
+ gargv[gargp][position+1] == '\0') {
+ running = 0;
+ }
+
+ if (gargp >= gargc) {
+ std::cout << "Error: last option requires a parameter" << std::endl;
+ exit(1);
+ }
+ setModified(tempname, &gargv[gargp][position]);
+
+ if (!running) {
+ gargp++;
+ }
+ return gargp;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// helping function
+//
+
+//////////////////////////////
+//
+// optionListCompare -- for sorting the option list
+//
+
+int optionListCompare(const void* a, const void* b) {
+//cerr << " comparing: " << (*((option_list**)a))->getName()
+// << " i=" << (*((option_list**)a))->getIndex()
+// << " :to: "
+// << (*((option_list**)b))->getName()
+// << " i=" << (*((option_list**)b))->getIndex() << std::endl;
+ return strcmp((*((option_list**)a))->getName(),
+ (*((option_list**)b))->getName());
+}
+
+
+
+// md5sum: 63584ffabc92170fdb9ef5caedb5a3f6 - Options.cpp =css= 20030102
diff --git a/src/midiio/src/Options_private.cpp b/src/midiio/src/Options_private.cpp
new file mode 100644
index 0000000..5a875a8
--- /dev/null
+++ b/src/midiio/src/Options_private.cpp
@@ -0,0 +1,358 @@
+//
+// Copyright 1998-1999 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Apr 5 13:07:18 PDT 1998
+// Last Modified: Sun Jan 10 05:43:24 PST 1999
+// Filename: ...sig/maint/code/sigBase/Options_private.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/Options_private.cpp
+// Syntax: C++
+//
+// Description: A private set of functions for use in the Options class.
+//
+
+#include "Options_private.h"
+#include <iostream>
+#include <stdlib.h>
+#include <string.h>
+
+
+//////////////////////////////
+//
+// option_register::option_register --
+//
+
+option_register::option_register(void) {
+ definition = NULL;
+ defaultOption = NULL;
+ modifiedOption = NULL;
+ type = 's';
+}
+
+
+option_register::option_register(const char* aDefinition, char aType,
+ const char* aDefaultOption, const char* aModifiedOption) {
+ definition = NULL;
+ defaultOption = NULL;
+ modifiedOption = NULL;
+
+ setType(aType);
+ setDefinition(aDefinition);
+ setDefault(aDefaultOption);
+ setModified(aModifiedOption);
+}
+
+
+
+//////////////////////////////
+//
+// option_register::~option_register --
+//
+
+option_register::~option_register() {
+ if (definition != NULL) {
+ delete [] definition;
+ }
+ definition = NULL;
+
+ if (defaultOption != NULL) {
+ delete [] defaultOption;
+ }
+ defaultOption = NULL;
+
+ if (modifiedOption != NULL) {
+ delete [] modifiedOption;
+ }
+ modifiedOption = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::clearModified -- sets the modified string to
+// NULL.
+//
+
+void option_register::clearModified(void) {
+ if (modifiedOption != NULL) {
+ delete [] modifiedOption;
+ }
+ modifiedOption = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getDefinition -- returns the initial definition
+// string used to define this entry.
+//
+
+const char* option_register::getDefinition(void) {
+ return definition;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getDefault -- returns the default string
+// to be returned. Will never return a NULL;
+//
+
+const char* option_register::getDefault(void) {
+ return defaultOption;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getModified -- return the modified
+// option string
+//
+
+const char* option_register::getModified(void) {
+ return modifiedOption;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getModifiedQ -- returns true if
+// modified string is not null, false otherwise.
+//
+
+int option_register::getModifiedQ(void) {
+ if (modifiedOption == NULL) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getType --
+//
+
+char option_register::getType(void) {
+ return type;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getOption -- return the modified option
+// or the default option if no modified option.
+//
+
+const char* option_register::getOption(void) {
+ if (getModifiedQ()) {
+ return getModified();
+ } else {
+ return getDefault();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// option_register::reset -- deallocate space for all
+// strings in object. (but default string is set to "")
+//
+
+void option_register::reset(void) {
+ if (definition != NULL) {
+ delete [] definition;
+ }
+ definition = NULL;
+
+ if (defaultOption != NULL) {
+ delete [] defaultOption;
+ }
+ defaultOption = NULL;
+ defaultOption = new char[1];
+ defaultOption[0] = '\0';
+
+ if (modifiedOption != NULL) {
+ delete [] modifiedOption;
+ }
+ modifiedOption = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::setDefault --
+//
+
+void option_register::setDefault(const char* aString) {
+ if (aString == NULL) {
+ std::cout << "Error: default string cannot be null" << std::endl;
+ exit(1);
+ }
+
+ if (defaultOption != NULL) {
+ delete [] defaultOption;
+ }
+ if (aString == NULL) {
+ defaultOption = NULL;
+ } else {
+ defaultOption = new char[strlen(aString) + 1];
+ strcpy(defaultOption, aString);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// option_register::setDefinition --
+//
+
+void option_register::setDefinition(const char* aString) {
+
+ if (definition != NULL) {
+ delete [] definition;
+ }
+ if (aString == NULL) {
+ definition = NULL;
+ } else {
+ definition = new char[strlen(aString) + 1];
+ strcpy(definition, aString);
+ }
+
+}
+
+
+
+//////////////////////////////
+//
+// option_register::setModified --
+//
+
+void option_register::setModified(const char* aString) {
+ if (modifiedOption != NULL) {
+ delete [] modifiedOption;
+ }
+ if (aString == NULL) {
+ modifiedOption = NULL;
+ } else {
+ modifiedOption = new char[strlen(aString) + 1];
+ strcpy(modifiedOption, aString);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// option_register::setType --
+//
+
+void option_register::setType(char aType) {
+ type = aType;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+/// option_list class definitions ///////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////
+//
+// option_list::option_list --
+//
+
+option_list::option_list(void) {
+ name = NULL;
+ index = -1;
+}
+
+
+
+//////////////////////////////
+//
+// option_list::option_list --
+//
+
+option_list::option_list(const char* optionName, int anIndex) {
+ name = NULL;
+ setIndex(anIndex);
+ setName(optionName);
+}
+
+
+
+//////////////////////////////
+//
+// option_list::~option_list --
+//
+
+option_list::~option_list() {
+ if (name != NULL) {
+ delete [] name;
+ }
+ name = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// option_list::getIndex --
+//
+
+int option_list::getIndex(void) {
+ return index;
+}
+
+
+
+//////////////////////////////
+//
+// option_list::getName --
+//
+
+const char* option_list::getName(void) {
+ return name;
+}
+
+
+
+//////////////////////////////
+//
+// option_list::setName --
+//
+
+void option_list::setName(const char* aString) {
+ if (name != NULL) {
+ delete [] name;
+ }
+ name = new char[strlen(aString) + 1];
+ strcpy(name, aString);
+}
+
+
+
+//////////////////////////////
+//
+// option_list::setIndex --
+//
+
+void option_list::setIndex(int anIndex) {
+ index = anIndex;
+}
+
+
+
+// md5sum: be3cc8ad0380820a9ea96739dc989657 - Options_private.cpp =css= 20030102
diff --git a/src/midiio/src/Sequencer_alsa.cpp b/src/midiio/src/Sequencer_alsa.cpp
new file mode 100644
index 0000000..4c80e22
--- /dev/null
+++ b/src/midiio/src/Sequencer_alsa.cpp
@@ -0,0 +1,643 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Thu May 11 21:10:02 PDT 2000
+// Last Modified: Sat Oct 13 14:51:43 PDT 2001 (updated for ALSA 0.9 interface)
+// Filename: ...sig/maint/code/control/Sequencer_alsa.cpp
+// Web Address: http://sig.sapp.org/src/sig/Sequencer_alsa.cpp
+// Syntax: C++
+//
+// Description: Basic MIDI input/output functionality for the
+// Linux ALSA raw midi devices. This class
+// is inherited by the classes MidiInPort_alsa and
+// MidiOutPort_alsa.
+//
+
+#if defined(LINUX) && defined(ALSA)
+
+#include "Collection.h"
+#include <alsa/asoundlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <iostream>
+#include <stdio.h>
+#include <dirent.h> /* for reading filename for MIDI info */
+#include "Sequencer_alsa.h"
+
+typedef unsigned char uchar;
+
+// define static variables:
+int Sequencer_alsa::class_count = 0;
+int Sequencer_alsa::initialized = 0;
+
+// static variables for MIDI I/O information database
+int Sequencer_alsa::indevcount = 0;
+int Sequencer_alsa::outdevcount = 0;
+
+Collection<snd_rawmidi_t*> Sequencer_alsa::rawmidi_in;
+Collection<snd_rawmidi_t*> Sequencer_alsa::rawmidi_out;
+Collection<int> Sequencer_alsa::midiincard;
+Collection<int> Sequencer_alsa::midioutcard;
+Collection<int> Sequencer_alsa::midiindevice;
+Collection<int> Sequencer_alsa::midioutdevice;
+Collection<char*> Sequencer_alsa::midiinname;
+Collection<char*> Sequencer_alsa::midioutname;
+
+
+
+///////////////////////////////
+//
+// Sequencer_alsa::Sequencer_alsa --
+// default value: autoOpen = 1;
+//
+
+Sequencer_alsa::Sequencer_alsa(int autoOpen) {
+ if (class_count < 0) {
+ std::cerr << "Unusual class instantiation count: " << class_count << std::endl;
+ exit(1);
+ } else if (class_count == 0) {
+ buildInfoDatabase();
+ }
+
+ // will not autoOpen
+
+ class_count++;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::~Sequencer_alsa --
+//
+
+Sequencer_alsa::~Sequencer_alsa() {
+
+ if (class_count == 1) {
+ close();
+ removeInfoDatabase();
+ } else if (class_count <= 0) {
+ std::cerr << "Unusual class instantiation count: " << class_count << std::endl;
+ exit(1);
+ }
+
+ class_count--;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::close -- close the sequencer device. The device
+// automatically closes once the program ends.
+//
+
+void Sequencer_alsa::close(void) {
+ int i;
+
+ for (i=0; i<getNumInputs(); i++) {
+ if (rawmidi_in[i] != NULL) {
+ snd_rawmidi_close(rawmidi_in[i]);
+ rawmidi_in[i] = NULL;
+ }
+ }
+
+ for (i=0; i<getNumOutputs(); i++) {
+ if (rawmidi_out[i] != NULL) {
+ snd_rawmidi_close(rawmidi_out[i]);
+ rawmidi_out[i] = NULL;
+ }
+ }
+
+}
+
+
+void Sequencer_alsa::closeInput(int index) {
+ if (index < 0 || index >= rawmidi_in.getSize()) {
+ return;
+ }
+
+ if (rawmidi_in[index] != NULL) {
+ snd_rawmidi_close(rawmidi_in[index]);
+ rawmidi_in[index] = NULL;
+ }
+}
+
+
+void Sequencer_alsa::closeOutput(int index) {
+ if (index < 0 || index >= rawmidi_out.getSize()) {
+ return;
+ }
+
+ if (rawmidi_out[index] != NULL) {
+ snd_rawmidi_close(rawmidi_out[index]);
+ rawmidi_out[index] = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::displayInputs -- display a list of the
+// available MIDI input devices.
+// default values: out = std::cout, initial = "\t"
+//
+
+void Sequencer_alsa::displayInputs(std::ostream& out, char* initial) {
+ for (int i=0; i<getNumInputs(); i++) {
+ out << initial << i << ": " << getInputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::displayOutputs -- display a list of the
+// available MIDI output devices.
+// default values: out = std::cout, initial = "\t"
+//
+
+void Sequencer_alsa::displayOutputs(std::ostream& out, char* initial) {
+ for (int i=0; i<getNumOutputs(); i++) {
+ out << initial << i << ": " << getOutputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getInputName -- returns a string to the name of
+// the specified input device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_alsa::getInputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return midiinname[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getNumInputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_alsa::getNumInputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return indevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getNumOutputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_alsa::getNumOutputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return outdevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getOutputName -- returns a string to the name of
+// the specified output device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_alsa::getOutputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return midioutname[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::is_open -- returns true if the
+// sequencer device is open, false otherwise.
+//
+
+int Sequencer_alsa::is_open(int mode, int index) {
+ if (mode == 0) {
+ // midi output
+ if (rawmidi_out[index] != NULL) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ if (rawmidi_in[index] != NULL) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+
+int Sequencer_alsa::is_open_in(int index) {
+ return is_open(1, index);
+}
+
+
+int Sequencer_alsa::is_open_out(int index) {
+ return is_open(0, index);
+}
+
+
+
+/////////////////////////////
+//
+// Sequencer_alsa::open -- returns true if the device
+// was successfully opended (or already opened)
+//
+
+int Sequencer_alsa::open(int direction, int index) {
+ if (direction == 0) {
+ return openOutput(index);
+ } else {
+ return openInput(index);
+ }
+}
+
+
+int Sequencer_alsa::openInput(int index) {
+ if (rawmidi_in[index] != NULL) {
+ return 1;
+ }
+ int status;
+ char devname[128] = {0};
+ sprintf(devname, "hw:%d,%d", midiincard[index], midiindevice[index]);
+ status = snd_rawmidi_open(&rawmidi_in[index], NULL, devname, 0);
+ if (status == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+int Sequencer_alsa::openOutput(int index) {
+ if (rawmidi_out[index] != NULL) {
+ return 1;
+ }
+ int status;
+ char devname[128] = {0};
+ sprintf(devname, "hw:%d,%d", midioutcard[index], midioutdevice[index]);
+ status = snd_rawmidi_open(NULL, &rawmidi_out[index], devname, 0);
+ if (status == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::read -- reads MIDI bytes and also stores the
+// device from which the byte was read from. Timing is not
+// saved from the device. If needed, then it would have to
+// be saved in this function, or just return the raw packet
+// data (use rawread function).
+//
+
+void Sequencer_alsa::read(int dev, uchar* buf, int count) {
+ if (is_open_in(dev)) {
+ snd_rawmidi_read(rawmidi_in[dev], buf, count);
+ } else {
+ std::cout << "Warning: MIDI input " << dev << " is not open for reading"
+ << std::endl;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::rebuildInfoDatabase -- rebuild the internal
+// database that keeps track of the MIDI input and output devices.
+//
+
+void Sequencer_alsa::rebuildInfoDatabase(void) {
+ removeInfoDatabase();
+ buildInfoDatabase();
+}
+
+
+
+///////////////////////////////
+//
+// Sequencer_alsa::write -- Send a byte out the specified MIDI
+// port which can be either an internal or an external synthesizer.
+//
+
+int Sequencer_alsa::write(int aDevice, int aByte) {
+ uchar byte[1];
+ byte[0] = (uchar)aByte;
+ return write(aDevice, byte, 1);
+}
+
+
+int Sequencer_alsa::write(int aDevice, uchar* bytes, int count) {
+ if (is_open_out(aDevice)) {
+ int status = snd_rawmidi_write(rawmidi_out[aDevice], bytes, count);
+ return status == count ? 1 : 0;
+ } else {
+ std::cout << "Warning: MIDI output " << aDevice << " is not open for writing"
+ << std::endl;
+ return 0;
+ }
+
+ return 0;
+}
+
+
+int Sequencer_alsa::write(int aDevice, char* bytes, int count) {
+ return write(aDevice, (uchar*)bytes, count);
+}
+
+
+int Sequencer_alsa::write(int aDevice, int* bytes, int count) {
+ uchar *newBytes;
+ newBytes = new uchar[count];
+ for (int i=0; i<count; i++) {
+ newBytes[i] = (uchar)bytes[i];
+ }
+ int status = write(aDevice, newBytes, count);
+ delete [] newBytes;
+ return status;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+//////////////////////////////
+//
+// Sequencer_alsa::buildInfoDatabase -- determines the number
+// of MIDI input and output devices available from
+// /dev/snd/midiC%dD%d, and determines their names.
+//
+
+void Sequencer_alsa::buildInfoDatabase(void) {
+ if (initialized) {
+ return;
+ }
+
+ initialized = 1;
+
+ if (indevcount != 0 || outdevcount != 0) {
+ std::cout << "Error: Sequencer_alsa is already running" << std::endl;
+ std::cout << "Indevcout = " << indevcount << " and "
+ << " outdevcount = " << outdevcount << std::endl;
+ exit(1);
+ }
+
+ indevcount = 0;
+ outdevcount = 0;
+
+ midiincard.setSize(0);
+ midiincard.allowGrowth();
+ midioutcard.setSize(0);
+ midioutcard.allowGrowth();
+
+ midiindevice.setSize(0);
+ midiindevice.allowGrowth();
+ midioutdevice.setSize(0);
+ midioutdevice.allowGrowth();
+
+ midiinname.setSize(0);
+ midiinname.allowGrowth();
+ midioutname.setSize(0);
+ midioutname.allowGrowth();
+
+ rawmidi_in.setSize(256);
+ rawmidi_out.setSize(256);
+
+ // read number of MIDI inputs/output available
+ Collection<int> cards;
+ Collection<int> devices;
+ getPossibleMidiStreams(cards, devices);
+ char devname[128] = {0};
+
+ // check for MIDI input streams
+ int i;
+ for (i=0; i<cards.getSize(); i++) {
+ sprintf(devname, "hw:%d,%d", cards[i], devices[i]);
+ if (snd_rawmidi_open(&rawmidi_in[indevcount], NULL, devname, 0) == 0){
+ midiincard.append(cards[i]);
+ midiindevice.append(devices[i]);
+ snd_rawmidi_close(rawmidi_in[indevcount]);
+ rawmidi_in[indevcount] = NULL;
+ indevcount++;
+ }
+ }
+ for (i=0; i<rawmidi_in.getSize(); i++) {
+ rawmidi_in[i] = NULL;
+ }
+
+ // check for MIDI output streams
+ for (i=0; i<cards.getSize(); i++) {
+ sprintf(devname, "hw:%d,%d", cards[i], devices[i]);
+ if (snd_rawmidi_open(NULL, &rawmidi_out[outdevcount], devname, 0) == 0) {
+ midioutcard.append(cards[i]);
+ midioutdevice.append(devices[i]);
+ snd_rawmidi_close(rawmidi_out[outdevcount]);
+ rawmidi_out[indevcount] = NULL;
+ outdevcount++;
+ }
+ }
+ for (i=0; i<rawmidi_out.getSize(); i++) {
+ rawmidi_out[i] = NULL;
+ }
+
+ char buffer[256] = {0};
+ char* temp;
+ for (i=0; i<indevcount; i++) {
+ sprintf(buffer, "MIDI input %d: card %d, device %d", i,
+ midiincard[i], midiindevice[i]);
+ temp = new char[strlen(buffer) + 1];
+ strcpy(temp, buffer);
+ midiinname.append(temp);
+ }
+
+ for (i=0; i<outdevcount; i++) {
+ sprintf(buffer, "MIDI output %d: card %d, device %d", i,
+ midioutcard[i], midioutdevice[i]);
+ temp = new char[strlen(buffer) + 1];
+ strcpy(temp, buffer);
+ midioutname.append(temp);
+ }
+
+ midiincard.allowGrowth(0);
+ midioutcard.allowGrowth(0);
+ midiindevice.allowGrowth(0);
+ midioutdevice.allowGrowth(0);
+ midiinname.allowGrowth(0);
+ midioutname.allowGrowth(0);
+ rawmidi_in.allowGrowth(0);
+ rawmidi_out.allowGrowth(0);
+
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getInDeviceValue --
+//
+
+int Sequencer_alsa::getInDeviceValue(int aDevice) const {
+ return midiindevice[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getInCardValue --
+//
+
+int Sequencer_alsa::getInCardValue(int aDevice) const {
+ return midiincard[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getOutDeviceValue --
+//
+
+int Sequencer_alsa::getOutDeviceValue(int aDevice) const {
+ return midioutdevice[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getOutCardValue --
+//
+
+int Sequencer_alsa::getOutCardValue(int aDevice) const {
+ return midioutcard[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::removeInfoDatabase --
+//
+
+void Sequencer_alsa::removeInfoDatabase(void) {
+ if (rawmidi_in.getSize() != 0) {
+ close();
+ }
+
+ if (rawmidi_out.getSize() != 0) {
+ close();
+ }
+
+ rawmidi_in.setSize(0);
+ rawmidi_out.setSize(0);
+ midiincard.setSize(0);
+ midioutcard.setSize(0);
+ midiindevice.setSize(0);
+ midioutdevice.setSize(0);
+
+ int i;
+ for (i=0; i<midiinname.getSize(); i++) {
+ if (midiinname[i] != NULL) {
+ delete [] midiinname[i];
+ }
+ }
+
+ for (i=0; i<midioutname.getSize(); i++) {
+ if (midioutname[i] != NULL) {
+ delete [] midioutname[i];
+ }
+ }
+
+ indevcount = 0;
+ outdevcount = 0;
+ initialized = 0;
+}
+
+
+
+//////////////////////////////
+//
+// getPossibleMidiStreams -- read the directory /dev/snd for files
+// that match the pattern midiC%dD%d, and extract the card/device
+// numbers from these filenames.
+//
+
+void Sequencer_alsa::getPossibleMidiStreams(Collection<int>& cards,
+ Collection<int>& devices) {
+
+ cards.setSize(0);
+ devices.setSize(0);
+ cards.allowGrowth(1);
+ devices.allowGrowth(1);
+
+ DIR* dir = opendir("/dev/snd");
+ if (dir == NULL) {
+// std::cout << "Error determining ALSA MIDI info: no directory called /dev/snd"
+// << std::endl;
+// exit(1);
+ }
+
+ // read each file in the directory and store information if it is a MIDI dev
+ else {
+ int card;
+ int device;
+ struct dirent *dinfo;
+ dinfo = readdir(dir);
+ int count;
+ while (dinfo != NULL) {
+ if (strncmp(dinfo->d_name, "midi", 4) == 0) {
+ count = sscanf(dinfo->d_name, "midiC%dD%d", &card, &device);
+ if (count == 2) {
+ cards.append(card);
+ devices.append(device);
+ }
+ }
+ dinfo = readdir(dir);
+ }
+
+ closedir(dir);
+ cards.allowGrowth(0);
+ devices.allowGrowth(0);
+ }
+}
+
+
+#endif /* LINUX and ALSA */
+
+// md5sum: 8ccf0e750be06aeea90cdc8a7cc4499c - Sequencer_alsa.cpp =css= 20030102
diff --git a/src/midiio/src/Sequencer_alsa05.cpp b/src/midiio/src/Sequencer_alsa05.cpp
new file mode 100644
index 0000000..ad4ef2d
--- /dev/null
+++ b/src/midiio/src/Sequencer_alsa05.cpp
@@ -0,0 +1,518 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Thu May 11 21:10:02 PDT 2000
+// Last Modified: Wed Oct 3 22:18:27 PDT 2001 (frozen to ALSA 0.5)
+// Filename: ...sig/maint/code/control/Sequencer_alsa05.cpp
+// Web Address: http://sig.sapp.org/src/sig/Sequencer_alsa05.cpp
+// Syntax: C++
+//
+// Description: Basic MIDI input/output functionality for the
+// Linux ALSA raw midi devices. This class
+// is inherited by the classes MidiInPort_alsa05 and
+// MidiOutPort_alsa05.
+//
+
+#if defined(LINUX) && defined(ALSA05)
+
+#include "Collection.h"
+#include <sys/asoundlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <iostream.h>
+#include <stdio.h>
+#include "Sequencer_alsa05.h"
+
+typedef unsigned char uchar;
+
+// define static variables:
+int Sequencer_alsa05::class_count = 0;
+int Sequencer_alsa05::initialized = 0;
+
+// static variables for MIDI I/O information database
+int Sequencer_alsa05::indevcount = 0;
+int Sequencer_alsa05::outdevcount = 0;
+
+Collection<snd_rawmidi_t*> Sequencer_alsa05::rawmidi_in;
+Collection<snd_rawmidi_t*> Sequencer_alsa05::rawmidi_out;
+Collection<int> Sequencer_alsa05::midiincard;
+Collection<int> Sequencer_alsa05::midioutcard;
+Collection<int> Sequencer_alsa05::midiindevice;
+Collection<int> Sequencer_alsa05::midioutdevice;
+Collection<char*> Sequencer_alsa05::midiinname;
+Collection<char*> Sequencer_alsa05::midioutname;
+
+
+
+///////////////////////////////
+//
+// Sequencer_alsa05::Sequencer_alsa05 --
+// default value: autoOpen = 1;
+//
+
+Sequencer_alsa05::Sequencer_alsa05(int autoOpen) {
+ if (class_count < 0) {
+ cerr << "Unusual class instatiation count: " << class_count << endl;
+ exit(1);
+ } else if (class_count == 0) {
+ buildInfoDatabase();
+ }
+
+ if (autoOpen) {
+ open();
+ }
+
+ class_count++;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::~Sequencer_alsa05 --
+//
+
+Sequencer_alsa05::~Sequencer_alsa05() {
+
+ if (class_count == 1) {
+ close();
+ removeInfoDatabase();
+ } else if (class_count <= 0) {
+ cerr << "Unusual class instatiation count: " << class_count << endl;
+ exit(1);
+ }
+
+ class_count--;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::close -- close the sequencer device. The device
+// automatically closes once the program ends.
+//
+
+void Sequencer_alsa05::close(void) {
+ int i;
+
+ for (i=0; i<getNumInputs(); i++) {
+ if (rawmidi_in[i] != NULL) {
+ snd_rawmidi_close(rawmidi_in[i]);
+ rawmidi_in[i] = NULL;
+ }
+ }
+
+ for (i=0; i<getNumOutputs(); i++) {
+ if (rawmidi_out[i] != NULL) {
+ snd_rawmidi_close(rawmidi_out[i]);
+ rawmidi_out[i] = NULL;
+ }
+ }
+
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::displayInputs -- display a list of the
+// available MIDI input devices.
+// default values: out = cout, initial = "\t"
+//
+
+void Sequencer_alsa05::displayInputs(ostream& out, char* initial) {
+ for (int i=0; i<getNumInputs(); i++) {
+ out << initial << i << ": " << getInputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::displayOutputs -- display a list of the
+// available MIDI output devices.
+// default values: out = cout, initial = "\t"
+//
+
+void Sequencer_alsa05::displayOutputs(ostream& out, char* initial) {
+ for (int i=0; i<getNumOutputs(); i++) {
+ out << initial << i << ": " << getOutputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getInputName -- returns a string to the name of
+// the specified input device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_alsa05::getInputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return midiinname[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getNumInputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_alsa05::getNumInputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return indevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getNumOutputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_alsa05::getNumOutputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return outdevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getOutputName -- returns a string to the name of
+// the specified output device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_alsa05::getOutputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return midioutname[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::is_open -- returns true if the
+// sequencer device is open, false otherwise.
+//
+
+int Sequencer_alsa05::is_open(int mode, int index) {
+ if (mode == 0) {
+ // midi output
+ if (rawmidi_out[index] != NULL) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ if (rawmidi_in[index] != NULL) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+
+int Sequencer_alsa05::is_open_in(int index) {
+ return is_open(1, index);
+}
+
+
+int Sequencer_alsa05::is_open_out(int index) {
+ return is_open(0, index);
+}
+
+
+
+/////////////////////////////
+//
+// Sequencer_alsa05::open -- returns true if the device
+// was successfully opended (or already opened)
+//
+
+int Sequencer_alsa05::open(void) {
+ if (rawmidi_out.getSize() != 0 || rawmidi_in.getSize() != 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::read -- reads MIDI bytes and also stores the
+// device from which the byte was read from. Timing is not
+// saved from the device. If needed, then it would have to
+// be saved in this function, or just return the raw packet
+// data (use rawread function).
+//
+
+void Sequencer_alsa05::read(int dev, uchar* buf, int count) {
+ snd_rawmidi_read(rawmidi_in[dev], buf, count);
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::rebuildInfoDatabase -- rebuild the internal
+// database that keeps track of the MIDI input and output devices.
+//
+
+void Sequencer_alsa05::rebuildInfoDatabase(void) {
+ removeInfoDatabase();
+ buildInfoDatabase();
+}
+
+
+
+///////////////////////////////
+//
+// Sequencer_alsa05::write -- Send a byte out the specified MIDI
+// port which can be either an internal or an external synthesizer.
+//
+
+int Sequencer_alsa05::write(int aDevice, int aByte) {
+ uchar byte[1];
+ byte[0] = (uchar)aByte;
+ return write(aDevice, byte, 1);
+}
+
+
+int Sequencer_alsa05::write(int aDevice, uchar* bytes, int count) {
+ int status = snd_rawmidi_write(rawmidi_out[aDevice], bytes, count);
+ return status == count ? 1 : 0;
+}
+
+
+int Sequencer_alsa05::write(int aDevice, char* bytes, int count) {
+ return write(aDevice, (uchar*)bytes, count);
+}
+
+
+int Sequencer_alsa05::write(int aDevice, int* bytes, int count) {
+ uchar *newBytes;
+ newBytes = new uchar[count];
+ for (int i=0; i<count; i++) {
+ newBytes[i] = (uchar)bytes[i];
+ }
+ int status = write(aDevice, newBytes, count);
+ delete [] newBytes;
+ return status;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+//////////////////////////////
+//
+// Sequencer_alsa05::buildInfoDatabase -- determines the number
+// of MIDI input and output devices available from
+// /dev/snd/midiXX, and determines their names.
+//
+
+void Sequencer_alsa05::buildInfoDatabase(void) {
+ if (initialized) {
+ return;
+ }
+
+ initialized = 1;
+
+ if (indevcount != 0 || outdevcount != 0) {
+ cout << "Error: Sequencer_alsa05 is already running" << endl;
+ cout << "Indevcout = " << indevcount << " and "
+ << " outdevcount = " << outdevcount << endl;
+ exit(1);
+ }
+
+ indevcount = 0;
+ outdevcount = 0;
+
+ midiincard.setSize(0);
+ midiincard.allowGrowth();
+ midioutcard.setSize(0);
+ midioutcard.allowGrowth();
+
+ midiindevice.setSize(0);
+ midiindevice.allowGrowth();
+ midioutdevice.setSize(0);
+ midioutdevice.allowGrowth();
+
+ midiinname.setSize(0);
+ midiinname.allowGrowth();
+ midioutname.setSize(0);
+ midioutname.allowGrowth();
+
+ rawmidi_in.setSize(256);
+ rawmidi_out.setSize(256);
+
+ // read number of MIDI inputs/output available
+ int card;
+ int device;
+
+ for (card=0; card<16; card++) {
+ for (device=0; device<16; device++) {
+ if (snd_rawmidi_open(&rawmidi_in[indevcount], card, device,
+ O_RDONLY | O_APPEND | O_NONBLOCK) == 0){
+ midiincard.append(card);
+ midiindevice.append(device);
+ indevcount++;
+ }
+ }
+ }
+ rawmidi_in.setSize(indevcount);
+
+ for (card=0; card<16; card++) {
+ for (device=0; device<16; device++) {
+ if (snd_rawmidi_open(&rawmidi_out[outdevcount], card,
+ device, O_WRONLY | O_APPEND | O_NONBLOCK) == 0) {
+ midioutcard.append(card);
+ midioutdevice.append(device);
+ outdevcount++;
+ }
+ }
+ }
+ rawmidi_out.setSize(indevcount);
+
+ int i;
+ char buffer[256] = {0};
+ char* temp;
+ for (i=0; i<indevcount; i++) {
+ sprintf(buffer, "MIDI input %d", i);
+ temp = new char[strlen(buffer) + 1];
+ strcpy(temp, buffer);
+ midiinname.append(temp);
+ }
+
+ for (i=0; i<outdevcount; i++) {
+ sprintf(buffer, "MIDI output %d", i);
+ temp = new char[strlen(buffer) + 1];
+ strcpy(temp, buffer);
+ midioutname.append(temp);
+ }
+
+ midiincard.allowGrowth(0);
+ midioutcard.allowGrowth(0);
+ midiindevice.allowGrowth(0);
+ midioutdevice.allowGrowth(0);
+ midiinname.allowGrowth(0);
+ midioutname.allowGrowth(0);
+ rawmidi_in.allowGrowth(0);
+ rawmidi_out.allowGrowth(0);
+
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getInDeviceValue --
+//
+
+int Sequencer_alsa05::getInDeviceValue(int aDevice) const {
+ return midiindevice[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getInCardValue --
+//
+
+int Sequencer_alsa05::getInCardValue(int aDevice) const {
+ return midiincard[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getOutDeviceValue --
+//
+
+int Sequencer_alsa05::getOutDeviceValue(int aDevice) const {
+ return midioutdevice[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getOutCardValue --
+//
+
+int Sequencer_alsa05::getOutCardValue(int aDevice) const {
+ return midioutcard[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::removeInfoDatabase --
+//
+
+void Sequencer_alsa05::removeInfoDatabase(void) {
+ if (rawmidi_in.getSize() != 0) {
+ close();
+ }
+
+ if (rawmidi_out.getSize() != 0) {
+ close();
+ }
+
+ rawmidi_in.setSize(0);
+ rawmidi_out.setSize(0);
+ midiincard.setSize(0);
+ midioutcard.setSize(0);
+ midiindevice.setSize(0);
+ midioutdevice.setSize(0);
+
+ int i;
+ for (i=0; i<midiinname.getSize(); i++) {
+ if (midiinname[i] != NULL) {
+ delete [] midiinname[i];
+ }
+ }
+
+ for (i=0; i<midioutname.getSize(); i++) {
+ if (midioutname[i] != NULL) {
+ delete [] midioutname[i];
+ }
+ }
+
+ indevcount = 0;
+ outdevcount = 0;
+ initialized = 0;
+}
+
+
+#endif /* LINUX and ALSA05 */
+
+
+// md5sum: b47021f0b71b2bc1555755584777c9a8 - Sequencer_alsa05.cpp =css= 20030102
diff --git a/src/midiio/src/Sequencer_oss.cpp b/src/midiio/src/Sequencer_oss.cpp
new file mode 100644
index 0000000..db9258e
--- /dev/null
+++ b/src/midiio/src/Sequencer_oss.cpp
@@ -0,0 +1,809 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Jan 3 21:02:02 PST 1999
+// Last Modified: Fri Jan 8 04:50:05 PST 1999
+// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _linux to _oss)
+// Filename: ...sig/maint/code/control/MidiOutPort/Sequencer_oss.cpp
+// Web Address: http://sig.sapp.org/src/sig/Sequencer_oss.cpp
+// Syntax: C++
+//
+// Description: Basic MIDI input/output functionality for the
+// Linux OSS midi device /dev/sequencer. This class
+// is inherited by the classes MidiInPort_oss and
+// MidiOutPort_oss.
+//
+
+#ifdef LINUX
+
+#include <stdlib.h>
+
+
+#include <linux/soundcard.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <iostream>
+#include "Sequencer_oss.h"
+
+
+// define static variables:
+const char* Sequencer_oss::sequencer = "/dev/sequencer";
+int Sequencer_oss::sequencer_fd = -1;
+int Sequencer_oss::class_count = 0;
+int Sequencer_oss::initialized = 0;
+uchar Sequencer_oss::midi_write_packet[4] = {SEQ_MIDIPUTC, 0, 0, 0};
+uchar Sequencer_oss::midi_read_packet[4];
+
+
+// static variables for MIDI I/O information database
+int Sequencer_oss::indevcount = 0;
+int Sequencer_oss::outdevcount = 0;
+
+int* Sequencer_oss::indevnum = NULL;
+int* Sequencer_oss::outdevnum = NULL;
+
+int* Sequencer_oss::indevtype = NULL;
+int* Sequencer_oss::outdevtype = NULL;
+
+char** Sequencer_oss::indevnames = NULL;
+char** Sequencer_oss::outdevnames = NULL;
+
+
+
+///////////////////////////////
+//
+// Sequencer_oss::Sequencer_oss --
+// default value: autoOpen = 1;
+//
+
+Sequencer_oss::Sequencer_oss(int autoOpen) {
+ if (autoOpen) {
+ open();
+ }
+
+ if (class_count < 0) {
+ std::cerr << "Unusual class instatiation count: " << class_count << std::endl;
+ exit(1);
+ } else if (class_count == 0) {
+ buildInfoDatabase();
+ }
+
+ class_count++;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::~Sequencer_oss --
+//
+
+Sequencer_oss::~Sequencer_oss() {
+ class_count--;
+
+ if (class_count == 0) {
+ close();
+ removeInfoDatabase();
+ } else if (class_count < 0) {
+ std::cerr << "Unusual class instatiation count: " << class_count << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::close -- close the sequencer device. The device
+// automatically closes once the program ends, but you can close it
+// so that other programs can use it.
+//
+
+void Sequencer_oss::close(void) {
+ ::close(getFd());
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::displayInputs -- display a list of the
+// available MIDI input devices.
+// default values: out = cout, initial = "\t"
+//
+
+void Sequencer_oss::displayInputs(std::ostream& out, char* initial) {
+ for (int i=0; i<getNumInputs(); i++) {
+ out << initial << i << ": " << getInputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::displayOutputs -- display a list of the
+// available MIDI output devices.
+// default values: out = cout, initial = "\t"
+//
+
+void Sequencer_oss::displayOutputs(std::ostream& out, char* initial) {
+ for (int i=0; i<getNumOutputs(); i++) {
+ out << initial << i << ": " << getOutputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getInputName -- returns a string to the name of
+// the specified input device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_oss::getInputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ if (aDevice >= getNumInputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max in ("
+ << getNumInputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return indevnames[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getNumInputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_oss::getNumInputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return indevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getNumOutputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_oss::getNumOutputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return outdevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getOutputName -- returns a string to the name of
+// the specified output device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_oss::getOutputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ if (aDevice >= getNumOutputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max out ("
+ << getNumOutputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return outdevnames[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::is_open -- returns true if the
+// sequencer device is open, false otherwise.
+//
+
+int Sequencer_oss::is_open(void) {
+ if (getFd() > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+/////////////////////////////
+//
+// Sequencer_oss::open -- returns true if the device
+// was successfully opended (or already opened)
+//
+
+int Sequencer_oss::open(void) {
+ if (getFd() <= 0) {
+ setFd(::open(sequencer, O_RDWR, 0));
+ }
+
+ return is_open();
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::read -- reads MIDI bytes and also stores the
+// device from which the byte was read from. Timing is not
+// saved from the device. If needed, then it would have to
+// be saved in this function, or just return the raw packet
+// data (use rawread function).
+//
+
+void Sequencer_oss::read(uchar* buf, uchar* dev, int count) {
+ int i = 0;
+ while (i < count) {
+ ::read(getFd(), midi_read_packet, sizeof(midi_read_packet));
+ if (midi_read_packet[1] == SEQ_MIDIPUTC) {
+ buf[i] = midi_read_packet[1];
+ dev[i] = midi_read_packet[2];
+ i++;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::rawread -- read Input MIDI packets.
+// each packet contains 4 bytes.
+//
+
+void Sequencer_oss::rawread(uchar* buf, int packetCount) {
+ ::read(getFd(), buf, packetCount * 4);
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::rebuildInfoDatabase -- rebuild the internal
+// database that keeps track of the MIDI input and output devices.
+//
+
+void Sequencer_oss::rebuildInfoDatabase(void) {
+ removeInfoDatabase();
+ buildInfoDatabase();
+}
+
+
+
+///////////////////////////////
+//
+// Sequencer_oss::write -- Send a byte out the specified MIDI
+// port which can be either an internal or an external synthesizer.
+//
+
+int Sequencer_oss::write(int device, int aByte) {
+ int status = 0;
+
+ switch (getOutputType(device)) {
+ case MIDI_EXTERNAL:
+ midi_write_packet[1] = (uchar) (0xff & aByte);
+ midi_write_packet[2] = getOutDeviceValue(device);
+ status = ::write(getFd(), midi_write_packet,sizeof(midi_write_packet));
+ break;
+ case MIDI_INTERNAL:
+ status = writeInternal(getOutDeviceValue(device), aByte);
+ break;
+ }
+
+ if (status > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+
+int Sequencer_oss::write(int device, uchar* bytes, int count) {
+ int status = 1;
+ for (int i=0; i<count; i++) {
+ status &= write(device, bytes[i]);
+ }
+ return status;
+}
+
+
+int Sequencer_oss::write(int device, char* bytes, int count) {
+ return write(device, (uchar*)bytes, count);
+}
+
+
+int Sequencer_oss::write(int device, int* bytes, int count) {
+ int status = 1;
+ for (int i=0; i<count; i++) {
+ status &= write(device, bytes[i]);
+ }
+ return status;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+//////////////////////////////
+//
+// Sequencer_oss::buildInfoDatabase -- determines the number
+// of MIDI input and output devices available from
+// /dev/sequencer, and determines their names.
+//
+
+void Sequencer_oss::buildInfoDatabase(void) {
+ int status;
+ initialized = 1;
+
+ int startup = sequencer_fd == -1 ? 0 : 1;
+ if (startup == 0) {
+ // setup the file descriptor for /dev/sequencer
+ sequencer_fd = ::open(sequencer, O_RDWR);
+ if (sequencer_fd < 0) {
+// std::cout << "Error: cannot open " << sequencer << std::endl;
+// exit(1);
+ }
+ else {
+ // read number of inputs available (external MIDI devices only)
+ status = ioctl(getFd(), SNDCTL_SEQ_NRMIDIS, &indevcount);
+ if (status!= 0) {
+ std::cerr << "Error determining the number of MIDI inputs" << std::endl;
+ exit(1);
+ }
+
+ // read number of output available
+ int extmidi = indevcount;
+ int intmidi;
+ status = ioctl(getFd(), SNDCTL_SEQ_NRSYNTHS, &intmidi);
+ if (status!= 0) {
+ std::cerr << "Error determining the number of MIDI inputs" << std::endl;
+ exit(1);
+ }
+ outdevcount = extmidi + intmidi;
+
+ // allocate space for names and device number arrays
+ if (indevnum != NULL || outdevnum != NULL || indevnames != NULL ||
+ outdevnames != NULL || indevtype != NULL || outdevtype != NULL) {
+ std::cerr << "Error: buildInfoDatabase called twice." << std::endl;
+ exit(1);
+ }
+
+ indevnum = new int[indevcount];
+ outdevnum = new int[outdevcount];
+
+ indevtype = new int[indevcount];
+ outdevtype = new int[outdevcount];
+
+ indevnames = new char*[indevcount];
+ outdevnames = new char*[outdevcount];
+
+
+ // fill in the device translation table and fill in the device names
+ int i;
+ struct midi_info midiinfo;
+ for (i=0; i<indevcount; i++) {
+ midiinfo.device = i;
+ status = ioctl(getFd(), SNDCTL_MIDI_INFO, &midiinfo);
+ if (status != 0) {
+ std::cerr << "Error while reading MIDI device " << i << std::endl;
+ exit(1);
+ }
+
+ indevnum[i] = midiinfo.device;
+ outdevnum[i] = midiinfo.device;
+ indevtype[i] = MIDI_EXTERNAL;
+ outdevtype[i] = MIDI_EXTERNAL;
+ indevnames[i] = new char[strlen(midiinfo.name) + 1 + 10];
+ outdevnames[i] = new char[strlen(midiinfo.name) + 1 + 11];
+ strcpy(indevnames[i], midiinfo.name);
+ strcpy(outdevnames[i], midiinfo.name);
+ strcat(indevnames[i], " (MIDI In)");
+ strcat(outdevnames[i], " (MIDI Out)");
+ }
+
+ char tempstring[1024] = {0};
+ struct synth_info synthinfo;
+ for (i=0; i<intmidi; i++) {
+ synthinfo.device = i;
+ status = ioctl(getFd(), SNDCTL_SYNTH_INFO, &synthinfo);
+ if (status != 0) {
+ std::cerr << "Error while reading MIDI device " << i << std::endl;
+ exit(1);
+ }
+ outdevnum[extmidi+i] = i;
+ outdevtype[extmidi + i] = MIDI_INTERNAL;
+
+ strcpy(tempstring, synthinfo.name);
+ switch (synthinfo.synth_type) {
+ case SYNTH_TYPE_FM: // 0
+ strcat(tempstring, " (FM");
+ switch (synthinfo.synth_subtype) {
+ case FM_TYPE_ADLIB: // 0
+ strcat(tempstring, " Adlib");
+ break;
+ case FM_TYPE_OPL3: // 1
+ strcat(tempstring, " OPL3");
+ break;
+ }
+ strcat(tempstring, ")");
+ break;
+ case SYNTH_TYPE_SAMPLE: // 1
+ strcat(tempstring, " (Wavetable)");
+ break;
+ case SYNTH_TYPE_MIDI: // 2
+ strcat(tempstring, " (MIDI Interface");
+ switch (synthinfo.synth_subtype) {
+ case SYNTH_TYPE_MIDI: // 0x401
+ strcat(tempstring, " MPU401");
+ break;
+ }
+ strcat(tempstring, ")");
+ break;
+ }
+ outdevnames[i+extmidi] = new char[strlen(tempstring) + 1];
+ strcpy(outdevnames[i+extmidi], tempstring);
+ }
+
+
+ if (startup == 0) {
+ ::close(sequencer_fd);
+ }
+ }
+ }
+}
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getFd -- returns the file descriptor of the
+// sequencer device.
+//
+
+int Sequencer_oss::getFd(void) {
+ return sequencer_fd;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getInDeviceValue --
+//
+
+int Sequencer_oss::getInDeviceValue(int aDevice) const {
+ if (aDevice >= getNumInputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max in ("
+ << getNumInputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return indevnum[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getInputType -- returns 1 = external MIDI,
+// 2 = internal MIDI
+//
+
+int Sequencer_oss::getInputType(int aDevice) const {
+ if (aDevice >= getNumInputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max in ("
+ << getNumInputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return indevtype[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getOutDeviceValue --
+//
+
+int Sequencer_oss::getOutDeviceValue(int aDevice) const {
+ if (aDevice >= getNumOutputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max out ("
+ << getNumOutputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return outdevnum[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getOutputType -- returns 1 = external MIDI,
+// 2 = internal MIDI
+//
+
+int Sequencer_oss::getOutputType(int aDevice) const {
+ if (aDevice >= getNumOutputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max out ("
+ << getNumOutputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return outdevtype[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::removeInfoDatabase --
+//
+
+void Sequencer_oss::removeInfoDatabase(void) {
+ initialized = 0;
+
+ if (indevnum != NULL) delete [] indevnum;
+ if (outdevnum != NULL) delete [] outdevnum;
+ if (indevtype != NULL) delete [] indevtype;
+ if (outdevtype != NULL) delete [] outdevtype;
+
+ int i;
+ if (indevnames != NULL) {
+ for (i=0; i<indevcount; i++) {
+ if (indevnames[i] != NULL) delete [] indevnames[i];
+ }
+ delete [] indevnames;
+ }
+
+ if (outdevnames != NULL) {
+ for (i=0; i<outdevcount; i++) {
+ if (outdevnames[i] != NULL) delete [] outdevnames[i];
+ }
+ delete [] outdevnames;
+ }
+
+ indevnum = NULL;
+ outdevnum = NULL;
+ indevtype = NULL;
+ outdevtype = NULL;
+ indevnames = NULL;
+ outdevnames = NULL;
+
+ indevcount = 0;
+ outdevcount = 0;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::setFd --
+//
+
+void Sequencer_oss::setFd(int anFd) {
+ sequencer_fd = anFd;
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions dealing with the stupid internal sythesizer messages
+// which have to be processed as complete messages as opposed to
+// external MIDI devices which are processed on the driver level as
+// discrete bytes.
+//
+
+// static variables related to the processing of message for internal MIDI:
+uchar Sequencer_oss::synth_write_message[8];
+uchar Sequencer_oss::synth_message_buffer[1024] = {0};
+int Sequencer_oss::synth_message_buffer_count = 0;
+int Sequencer_oss::synth_message_bytes_expected = 0;
+int Sequencer_oss::synth_message_curr_device = -1;
+
+
+//////////////////////////////
+//
+// Sequencer_oss::writeInternal -- the device number is the
+// driver's device number *NOT* this class's device numbering
+// system. MIDI bytes are stored in a buffer until a complete
+// message is received, then a synth message is generated.
+// While a complete message is being received, the device number
+// cannot change. The first byte of a message must be a MIDI
+// command (i.e., no running status).
+//
+
+int Sequencer_oss::writeInternal(int aDevice, int aByte) {
+ int status = 0;
+
+ if (synth_message_bytes_expected == 0) {
+ // a new message is coming in.
+ synth_message_curr_device = aDevice;
+ if (aByte < 128) {
+ std::cerr << "Error: MIDI output byte: " << aByte
+ << " is not a command byte." << std::endl;
+ exit(1);
+ } else {
+ synth_message_buffer[0] = aByte;
+ synth_message_buffer_count = 1;
+ }
+
+ switch (aByte & 0xf0) {
+ case 0x80: synth_message_bytes_expected = 3; break;
+ case 0x90: synth_message_bytes_expected = 3; break;
+ case 0xA0: synth_message_bytes_expected = 3; break;
+ case 0xB0: synth_message_bytes_expected = 3; break;
+ case 0xC0: synth_message_bytes_expected = 2; break;
+ case 0xD0: synth_message_bytes_expected = 2; break;
+ case 0xE0: synth_message_bytes_expected = 3; break;
+ case 0xF0: std::cerr << "Can't handle 0xE0 yet" << std::endl; exit(1);
+ default: std::cerr << "Unknown error" << std::endl; exit(1);
+ }
+ }
+
+ // otherwise expecting at least one more byte for the MIDI message
+ else {
+ if (synth_message_curr_device != aDevice) {
+ std::cerr << "Error: device number changed during message" << std::endl;
+ exit(1);
+ }
+ if (aByte > 127) {
+ std::cerr << "Error: expecting MIDI data but got MIDI command: "
+ << aByte << std::endl;
+ exit(1);
+ }
+
+ synth_message_buffer[synth_message_buffer_count++] = aByte;
+ }
+
+ // check to see if the message is complete:
+ if (synth_message_bytes_expected == synth_message_buffer_count) {
+ status = transmitMessageToInternalSynth();
+ synth_message_bytes_expected = 0;
+ synth_message_buffer_count = 0;
+ }
+
+ return status;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::transmitMessageToInternalSynth -- send the stored
+// MIDI message to the internal synthesizer.
+//
+
+int Sequencer_oss::transmitMessageToInternalSynth(void) {
+ int status;
+ switch (synth_message_buffer[0] & 0xf0) {
+ case 0x80: // Note-off
+ case 0x90: // Note-on
+ case 0xA0: // Aftertouch
+ status = transmitVoiceMessage();
+ break;
+ case 0xB0: // Control change
+ case 0xC0: // Patch change
+ case 0xD0: // Channel pressure
+ case 0xE0: // Pitch wheel
+ status = transmitCommonMessage();
+ break;
+ case 0xF0:
+ std::cerr << "Cannot handle 0xf0 commands yet" << std::endl;
+ exit(1);
+ break;
+ default:
+ std::cerr << "Error: unknown MIDI command" << std::endl;
+ exit(1);
+ }
+
+ return status;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::transmitVoiceMessage -- send a voice-type MIDI
+// message to an internal synthesizer.
+//
+
+int Sequencer_oss::transmitVoiceMessage(void) {
+ synth_write_message[0] = EV_CHN_VOICE;
+ synth_write_message[1] = synth_message_curr_device;
+ synth_write_message[2] = synth_message_buffer[0] & 0xf0;
+ synth_write_message[3] = synth_message_buffer[0] & 0x0f;
+ synth_write_message[4] = synth_message_buffer[1];
+ synth_write_message[5] = synth_message_buffer[2];
+ synth_write_message[6] = 0;
+ synth_write_message[7] = 0;
+
+ int status;
+ status = ::write(getFd(), synth_write_message, sizeof(synth_write_message));
+
+ if (status > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::transmitCommonMessage -- send a common-type MIDI
+// message to an internal synthesizer.
+//
+
+int Sequencer_oss::transmitCommonMessage(void) {
+ synth_write_message[0] = EV_CHN_COMMON;
+ synth_write_message[1] = synth_message_curr_device;
+ synth_write_message[2] = synth_message_buffer[0] & 0xf0;
+ synth_write_message[3] = synth_message_buffer[0] & 0x0f;
+
+ switch (synth_write_message[2]) {
+ case 0xB0: // Control change
+ synth_write_message[4] = synth_message_buffer[1];
+ synth_write_message[5] = 0;
+ synth_write_message[6] = synth_message_buffer[2];
+ synth_write_message[7] = 0;
+ break;
+ case 0xC0: // Patch change
+ case 0xD0: // Channel pressure
+ synth_write_message[4] = synth_message_buffer[1];
+ synth_write_message[5] = 0;
+ synth_write_message[6] = 0;
+ synth_write_message[7] = 0;
+ break;
+ case 0xE0: // Pitch wheel
+ synth_write_message[4] = 0;
+ synth_write_message[5] = 0;
+ synth_write_message[6] = synth_message_buffer[1];
+ synth_write_message[7] = synth_message_buffer[2];
+ break;
+ default:
+ std::cerr << "Unknown Common MIDI message" << std::endl;
+ exit(1);
+ }
+
+ int status;
+ status = ::write(getFd(), synth_write_message, sizeof(synth_write_message));
+
+ if (status > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+#endif // LINUX
+// md5sum: bc7b96041137b22f3d3c35376b5912c6 - Sequencer_oss.cpp =css= 20030102
diff --git a/src/midiio/src/SigTimer.cpp b/src/midiio/src/SigTimer.cpp
new file mode 100644
index 0000000..5786098
--- /dev/null
+++ b/src/midiio/src/SigTimer.cpp
@@ -0,0 +1,498 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Thanks to: Erik Neuenschwander <erikn@leland.stanford.edu>
+// for Windows 95 assembly code for Pentium clock cycles.
+// Ozgur Izmirli <ozgur@ccrma.stanford.edu>
+// for concept of periodic timer.
+// Creation Date: Mon Oct 13 11:34:57 GMT-0800 1997
+// Last Modified: Tue Feb 10 21:05:19 GMT-0800 1998
+// Last Modified: Sat Sep 19 15:56:48 PDT 1998
+// Last Modified: Mon Feb 22 04:44:25 PST 1999
+// Last Modified: Sun Nov 28 12:39:39 PST 1999 (added adjustPeriod())
+// Filename: .../sig/code/control/SigTimer/SigTimer.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/SigTimer.cpp
+// Syntax: C++
+//
+// Description: This class can only be used on Motorola Pentinum 75 Mhz
+// chips or better because the timing information is
+// extracted from the clock cycle count from a register
+// on the CPU itself. This class will estimate the
+// speed of the computer, but it would be better if there
+// was a way of finding out the speed from some function.
+// This class is used primarily for timing of MIDI input
+// and output at a millisecond resolution.
+//
+
+
+#include "SigTimer.h"
+#include <iostream>
+#include <stdlib.h>
+
+
+// get Sleep or usleep function definition for measureCpu function:
+#ifdef VISUAL
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #undef WIN32_LEAN_AND_MEAN
+#else
+ #include <unistd.h>
+#endif
+
+
+// declare static variables
+int64bits SigTimer::globalOffset = 0;
+int SigTimer::cpuSpeed = 0; // in cycles per second
+
+
+
+//////////////////////////////
+//
+// SigTimer::SigTimer
+//
+
+SigTimer::SigTimer(void) {
+ if (globalOffset == 0) { // coordinate offset between timers
+ globalOffset = clockCycles();
+ }
+ if (cpuSpeed <= 0) { // initialize CPU speed value
+ cpuSpeed = measureCpuSpeed(1);
+ if (cpuSpeed <= 0) {
+ cpuSpeed = 100000000;
+ }
+ }
+
+ offset = globalOffset; // initialize the start time of timer
+ ticksPerSecond = 1000; // default of 1000 ticks per second
+ period = 1000.0; // default period of once per second
+}
+
+
+SigTimer::SigTimer(int aSpeed) {
+ if (globalOffset == 0) {
+ globalOffset = clockCycles();
+ }
+ cpuSpeed = aSpeed;
+
+ offset = globalOffset;
+ ticksPerSecond = 1000;
+ period = 1000.0; // default period of once per second
+}
+
+
+SigTimer::SigTimer(SigTimer& aTimer) {
+ offset = aTimer.offset;
+ ticksPerSecond = aTimer.ticksPerSecond;
+ period = aTimer.period;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::~SigTimer
+//
+
+SigTimer::~SigTimer() {
+ // do nothing
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::adjustPeriod -- adjust the period of the timer.
+//
+
+void SigTimer::adjustPeriod(double periodDelta) {
+ offset -= (int64bits)(getCpuSpeed() * getPeriod() * periodDelta /
+ getTicksPerSecond());
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::clockCycles -- returns the number of clock cycles since last reboot
+// HARDWARE DEPENDENT -- currently for Pentiums only.
+// static function.
+//
+
+
+int64bits SigTimer::clockCycles() {
+#ifndef VISUAL
+ int64bits output;
+
+ // For Pentiums, you can get the number of clock cycles elapsed
+ // since the last reboot with the following assembler code:
+ __asm__ volatile (".byte 0x0f, 0x31" : "=A" (output));
+
+#else
+ int64bits output;
+ unsigned long high_end, low_end;
+ __asm {
+ __asm _emit 0x0f __asm _emit 0x31
+ mov high_end, edx
+ mov low_end, eax
+ }
+ output = high_end;
+ output = output << 32;
+ output += low_end;
+#endif
+
+ return output;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::expired -- returns the integral number of periods
+// That have passed since the last update or reset.
+// See getPeriodCount which returns a floating point
+// count of the period position.
+//
+
+
+int SigTimer::expired(void) const {
+ return (int)(getTime()/period);
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getCpuSpeed -- returns the CPU speed of the computer.
+// (static function)
+//
+
+int SigTimer::getCpuSpeed(void) {
+ return cpuSpeed;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getPeriod -- returns the timing period of the timer,
+// if the timer is being used as a periodic timer.
+//
+
+double SigTimer::getPeriod(void) const {
+ return period;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getPeriodCount -- returns the current period count
+// of the timer as a double. Similar in behavior to expired
+// function but lists the current fraction of a period.
+//
+
+double SigTimer::getPeriodCount(void) const {
+ return (double)getTime()/period;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getTempo -- returns the current tempo in terms
+// of beats (ticks) per minute.
+//
+
+double SigTimer::getTempo(void) const {
+ return getTicksPerSecond() * 60.0 / getPeriod();
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getTicksPerSecond -- return the number of ticks per
+// second.
+//
+
+int SigTimer::getTicksPerSecond(void) const {
+ return ticksPerSecond;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getTime -- returns time in milliseconds by default.
+// time can be altered to be in some other unit of time
+// by using the setTicksPerSecond function.
+// (Default is 1000 ticks per second.)
+//
+
+int SigTimer::getTime(void) const {
+ return (int)((clockCycles()-offset)/getFactor());
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getTimeInSeconds
+//
+
+double SigTimer::getTimeInSeconds(void) const {
+ return ((clockCycles()-offset)/(double)cpuSpeed);
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getTimeInTicks
+//
+
+int SigTimer::getTimeInTicks(void) const {
+ return (int)((clockCycles()-offset)/getFactor());
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::measureCpuSpeed -- returns the number of clock cycles in
+// one second. Accuracy to about +/- 5%.
+// default value: quantize = 0.
+//
+
+int SigTimer::measureCpuSpeed(int quantize) {
+ int64bits a, b;
+ a = clockCycles();
+ #ifdef VISUAL
+ Sleep(1000/4);
+ #else
+ usleep(1000000/4);
+ #endif
+ b = clockCycles();
+
+ int output = (int)(4*(b-a-140100-450000));
+
+ if (quantize) {
+ // quantize to a known computer CPU speed
+ if (output < 78000000) {
+ output = 75000000;
+ } else if (output < 95000000) {
+ output = 90000000;
+ } else if (output < 110000000) {
+ output = 100000000;
+ } else if (output < 140000000) {
+ output = 133000000;
+ } else if (output < 155000000) {
+ output = 150000000;
+ } else if (output < 180000000) {
+ output = 166000000;
+ } else if (output < 215000000) {
+ output = 200000000;
+ } else if (output < 250000000) {
+ output = 233000000;
+ } else if (output < 280000000) {
+ output = 266000000;
+ } else if (output < 325000000) {
+ output = 300000000;
+ } else if (output < 375000000) {
+ output = 350000000;
+ } else if (output < 425000000) {
+ output = 400000000;
+ } else {
+ output = output;
+ }
+ } // end if quantize
+
+ return output;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::reset -- set the timer to 0.
+//
+
+void SigTimer::reset(void) {
+ offset = clockCycles();
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::setCpuSpeed -- You can also vary the CPU speed here to cause the
+// getTime function to output different units of time, but the
+// setTicksPerSecond is a more appropriate place to do such a thing.
+//
+
+void SigTimer::setCpuSpeed(int aSpeed) {
+ if (aSpeed <= 0) {
+ std::cerr << "Error: Cannot set the cpu speed to be negative: "
+ << aSpeed << std::endl;
+ exit(1);
+ }
+ cpuSpeed = aSpeed;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::setPeriod -- sets the period length of the timer.
+// input value cannot be less than 1.0.
+//
+
+void SigTimer::setPeriod(double aPeriod) {
+ if (aPeriod < 1.0) {
+ std::cerr << "Error: period too small: " << aPeriod << std::endl;
+ exit(1);
+ }
+ period = aPeriod;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::setPeriodCount -- adjusts the offset time according
+// to the current period to match the specified period count.
+//
+
+void SigTimer::setPeriodCount(double aCount) {
+ offset = (int64bits)(clockCycles() - aCount * getPeriod() *
+ getCpuSpeed() / getTicksPerSecond());
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::setTempo -- sets the period length in terms of
+// beats per minute.
+//
+
+void SigTimer::setTempo(double beatsPerMinute) {
+ if (beatsPerMinute < 1.0) {
+ std::cerr << "Error: tempo is too slow: " << beatsPerMinute << std::endl;
+ exit(1);
+ }
+ double count = getPeriodCount();
+ period = getTicksPerSecond() * 60.0 / beatsPerMinute;
+ setPeriodCount(count);
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::setTicksPerSecond
+//
+
+void SigTimer::setTicksPerSecond(int aTickRate) {
+ if (aTickRate <= 0) {
+ std::cerr << "Error: Cannot set the tick rate to be negative: "
+ << aTickRate << std::endl;
+ exit(1);
+ }
+ ticksPerSecond = aTickRate;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::start
+//
+
+void SigTimer::start(void) {
+ reset();
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::sync
+//
+
+void SigTimer::sync(SigTimer& aTimer) {
+ offset = aTimer.offset;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::update -- set the timer start to the next period.
+//
+
+void SigTimer::update(void) {
+ if (getTime() >= getPeriod()) {
+ offset += (int64bits)(getPeriod() * getFactor());
+ }
+}
+
+
+// update(int) will do nothing if the periodCount is greater than
+// than the expired period count
+
+void SigTimer::update(int periodCount) {
+ if (periodCount > expired()) {
+ return;
+ } else {
+ offset += (int64bits)(getPeriod() * getFactor() * periodCount);
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// protected functions:
+//
+
+
+//////////////////////////////
+//
+// SigTimer::getFactor --
+//
+
+double SigTimer::getFactor(void) const {
+ return (double)((double)getCpuSpeed()/(double)getTicksPerSecond());
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Miscellaneous timing functions are located here untill a better
+// place can be found:
+//
+
+void millisleep(int milliseconds) {
+ #ifdef VISUAL
+ Sleep(milliseconds);
+ #else
+ usleep( milliseconds * 1000);
+ #endif
+}
+
+
+void millisleep(float milliseconds) {
+ #ifdef VISUAL
+ // cannot convert to microseconds in Visual C++ yet.
+ // Tell me how and I'll fix the following line
+ Sleep((unsigned long)milliseconds);
+ #else
+ usleep((int)(milliseconds * 1000.0));
+ #endif
+}
+
+
+
+
+// md5sum: b35e9e6a8d6fd16636d7fca5d565f284 - SigTimer.cpp =css= 20030102
diff --git a/src/midiio/src/Voice.cpp b/src/midiio/src/Voice.cpp
new file mode 100644
index 0000000..ed05bce
--- /dev/null
+++ b/src/midiio/src/Voice.cpp
@@ -0,0 +1,334 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Oct 11 18:39:14 PDT 1998
+// Last Modified: Sun Oct 11 18:39:18 PDT 1998
+// Filename: ...sig/maint/code/control/Voice/Voice.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/Voice.cpp
+// Syntax: C++
+//
+// Description: The Voice class is a MIDI output class which keeps
+// track of the last note played in to it. If the last
+// note was not turned off when a new note is played,
+// then the old note will be turned off before the
+// new note is played.
+//
+
+#include "Voice.h"
+
+
+// declare static variables:
+SigTimer Voice::timer;
+
+//////////////////////////////
+//
+// Voice::Voice
+//
+
+Voice::Voice(int aChannel) {
+ chan = oldChan = aChannel;
+ vel = oldVel = key = oldKey = 0;
+}
+
+
+Voice::Voice(const Voice& aVoice) {
+ chan = aVoice.chan;
+ vel = aVoice.vel;
+ key = aVoice.key;
+ oldChan = 0;
+ oldVel = 0;
+ oldKey = 0;
+}
+
+
+Voice::Voice(void) {
+ chan = oldChan = key = oldKey = vel = oldVel = 0;
+}
+
+
+//////////////////////////////
+//
+// Voice::~Voice
+//
+
+Voice::~Voice() {
+ off();
+}
+
+
+
+//////////////////////////////
+//
+// Voice::cont -- use default channel if none specified for
+// the continuous controller message.
+//
+
+void Voice::cont(int controller, int data) {
+ MidiOutput::cont(getChannel(), controller, data);
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getChan -- returns the channel of the voice.
+// Synonym for getChannel.
+//
+
+int Voice::getChan(void) const {
+ return chan;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getChannel -- returs the channel of the voice.
+//
+
+int Voice::getChannel(void) const {
+ return chan;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getKey -- returns the current MIDI key number of the voice.
+// Synonym for getKeynum.
+//
+
+int Voice::getKey(void) const {
+ return key;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getKeynum -- returns the current MIDI key number of the voice.
+//
+
+int Voice::getKeynum(void) const {
+ return key;
+}
+
+
+//////////////////////////////
+//
+// Voice::getOffTime -- returns the last note off message sent
+// out of the voice object
+//
+
+int Voice::getOffTime(void) const {
+ return offTime;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getOnTime -- returns the last note on message sent
+// out of the voice object.
+//
+
+int Voice::getOnTime(void) const {
+ return onTime;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getVel -- returns the current velocity of the MIDI key.
+// Synonym for getVelocity.
+//
+
+int Voice::getVel(void) const {
+ return vel;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getVelocity -- returns the current velocity of the MIDI key.
+//
+
+int Voice::getVelocity(void) const {
+ return vel;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::off
+//
+
+void Voice::off(void) {
+ if (status() != 0) {
+ offTime = timer.getTime();
+ MidiOutput::play(oldChan, oldKey, 0);
+ oldVel = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Voice::pc -- use default channel if none is specified
+//
+
+void Voice::pc(int aTimbre) {
+ MidiOutput::pc(getChannel(), aTimbre);
+}
+
+
+
+//////////////////////////////
+//
+// Voice::play
+//
+
+void Voice::play(int aChannel, int aKeyno, int aVelocity) {
+ off();
+ MidiOutput::play(aChannel, aKeyno, aVelocity);
+ oldChan = aChannel;
+ oldKey = aKeyno;
+ oldVel = aVelocity;
+ setChannel(aChannel);
+ setKeynum(aKeyno);
+ setVelocity(aVelocity);
+
+ if (aVelocity != 0) {
+ onTime = timer.getTime();
+ } else {
+ offTime = timer.getTime();
+ }
+}
+
+
+void Voice::play(int aKeyno, int aVelocity) {
+ off();
+ MidiOutput::play(getChannel(), aKeyno, aVelocity);
+ oldChan = getChannel();
+ oldKey = aKeyno;
+ oldVel = aVelocity;
+ setKeynum(aKeyno);
+ setVelocity(aVelocity);
+
+ if (aVelocity != 0) {
+ onTime = timer.getTime();
+ } else {
+ offTime = timer.getTime();
+ }
+}
+
+
+void Voice::play(void) {
+ off();
+ MidiOutput::play(getChannel(), getKey(), getVel());
+ oldChan = getChannel();
+ oldKey = getKey();
+ oldVel = getVel();
+
+ if (getVel() != 0) {
+ onTime = timer.getTime();
+ } else {
+ offTime = timer.getTime();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setChan -- set the MIDI channel. Synonym for setChannel.
+//
+
+void Voice::setChan(int aChannel) {
+ chan = aChannel;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setChannel -- set the MIDI channel of the voice.
+//
+
+void Voice::setChannel(int aChannel) {
+ chan = aChannel;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setKey -- set the keynumber of the voice
+// Synonym for setKeyno.
+//
+
+void Voice::setKey(int aKeynum) {
+ key = aKeynum;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setKeynum -- set the keynumber of the voice
+//
+
+void Voice::setKeynum(int aKeynum) {
+ key = aKeynum;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setVel -- set the MIDI velocity of the voice.
+// Synonym for setVelocity.
+//
+
+void Voice::setVel(int aVelocity) {
+ vel = aVelocity;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setVelocity
+//
+
+void Voice::setVelocity(int aVelocity) {
+ vel = aVelocity;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::status -- returns zero if off or positive if on.
+//
+
+int Voice::status(void) const {
+ return oldVel;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::sustain -- uses default channel if none specified.
+//
+
+void Voice::sustain(int aStatus) {
+ MidiOutput::sustain(getChannel(), aStatus);
+}
+
+
+// md5sum: d02ca41ae3b4e07efe7fedc720e52573 - Voice.cpp =css= 20030102