1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
File: PortMidi Win32 Readme
Author: Belinda Thom, June 16 2002
Revised by: Roger Dannenberg, June 2002, May 2004
=============================================================================
USING PORTMIDI:
=============================================================================
PortMidi has been created using a DLL because the Win32 MMedia API doesn't
handle midiInput properly in the debugger. Specifically, it doesn't clean up
after itself if the user (i.e. you, a PortMidi application) hasn't explicitly
closed all open midi input devices. This lack of cleanup can lead to much
pain and agony, including the blue-screen-of-death. This situation becomes
increasingly unacceptable when you are debugging your code, so a portMidi DLL
seemed to be the most elegant solution.
Using Microsoft Visual C++ project files (provided with PortMidi), there
are two configurations of the PortMidi library. The Debug version is
intended for debugging, especially in a console application. The Debug
version enables some extra error checking and outputs some text as well
as a prompt to type ENTER so that you don't lose any debugging text when
the program exits. You can turn off this extra debugging info by taking
out the compile-time definition for DEBUG. This debugging version also
defines PM_CHECK_ERRORS, which forces a check for error return codes from
every call to PortMidi. You can disable this checking (especially if you
want to handle error codes in your own way) by removing PM_CHECK_ERRORS
from the predefined symbols list in the Settings dialog box.
PortMidi is designed to run without a console and should work perfectly
well within a graphical user interface application. The Release version
is both optimized and lacking the debugging printout code of the Debug
version.
Read the portmidi.h file for PortMidi API details on using the PortMidi API.
See <...>\pm_dll_test\test.c or <...>\multithread\test.c for usage examples.
=============================================================================
TO INSTALL PORTMIDI:
=============================================================================
1) download portmidi.zip
2) unzip portmidi.zip into directory: <...>\portmidi
=============================================================================
TO COMPILE PORTMIDI:
=============================================================================
3) go to this directory
4) click on the portmidi.dsw workspace
5) the following projects exist within this workspace:
- portmidi (the PortMidi library)
- pm_dll (the dll library used to close midi ports on program exit)
- porttime (a small portable library implementing timer facilities)
- test (simple midi I/O testing)
- multithread (an example illustrating low-latency MIDI processing
using a dedicated low-latency thread)
- sysex (simple sysex message I/O testing)
- latency (uses porttime to measure system latency)
6) verify that all project settings are for Win32 Debug release:
- hit Alt-F7
- highlight all three projects in left part of Project Settings window;
- "Settings For" should say "Win32 Debug"
7) set pm_dll as the active project (e.g. Project->Select Active Project)
8) use Build->Batch Build ... to build everything in the project
9) The settings for these projects were distributed in the zip file, so
compile should just work.
10) IMPORTANT! PortMidi uses a DLL, pm_dll.dll, but there is no simple way
to set up projects to use pm_dll. THEREFORE, you need to copy DLLs
as follows (you can do this with <...>\portmidi\pm_win\copy-dll.bat):
copy <...>\portmidi\pm_win\Debug\pm_dll.dll to:
<...>\portmidi\pm_test\latencyDebug\pm_dll.dll
<...>\portmidi\pm_test\midithreadDebug\pm_dll.dll
<...>\portmidi\pm_test\sysexDebug\pm_dll.dll
<...>\portmidi\pm_test\testDebug\pm_dll.dll
<...>\portmidi\pm_test\midithruDebug\pm_dll.dll
and copy <...>\portmidi\pm_win\Release\pm_dll.dll to:
<...>\portmidi\pm_test\latencyRelease\pm_dll.dll
<...>\portmidi\pm_test\midithreadRelease\pm_dll.dll
<...>\portmidi\pm_test\sysexRelease\pm_dll.dll
<...>\portmidi\pm_test\testRelease\pm_dll.dll
<...>\portmidi\pm_test\midithruRelease\pm_dll.dll
each time you rebuild the pm_dll project, these copies must be redone!
Since Windows will look in the executable directory for DLLs, we
recommend that you always install a copy of pm_dll.dll (either the
debug version or the release version) in the same directory as the
application using PortMidi. The release DLL is about 40KB. This will
ensure that the application uses the correct DLL.
11) run test project; use the menu that shows up from the command prompt to
test that portMidi works on your system. tests include:
- verify midi output works
- verify midi input works
- verify midi input w/midi thru works
12) run other projects if you wish: sysex, latency, and midithread
============================================================================
TO CREATE YOUR OWN PORTMIDI CLIENT APPLICATION:
============================================================================
NOTE: this section needs to be reviewed and tested. My suggestion would
be to copy the test project file (test.dsp) and modify it. -RBD
The easiest way is to start a new project w/in the portMidi workspace:
1) To open new project:
- File->New->Projects
- Location: <...>\portmidi\<yourProjectName>
- check Add to current workspace
- select Win32 Console Application (recommended for now)
- do *NOT* select the "make dependency" box (you will explicitly do this
in the next step)
- Click OK
- Select "An Empty Project" and click Finish
2) Now this project will be the active project. Make it explicitly depend
on PortMidi dll:
- Project->Dependencies
- Click pm_dll
3) Important! in order to be able to use portMidi DLL from your new project
and set breakpoints, copy following files from <...>\pm_dll\Debug into
<...>\<yourProjectName>\Debug directory:
pm_dll.lib
pm_dll.dll
each time you rebuild pm_dll, these copies must be redone!
4) add whatever files you wish to add to your new project, using portMidi
calls as desired (see USING PORTMIDI at top of this readme)
5) when you include portMidi files, do so like this:
- #include "..\pm_dll\portmidi.h"
- etc.
6) build and run your project
============================================================================
DESIGN NOTES
============================================================================
The DLL is used so that PortMidi can (usually) close open devices when the
program terminates. Failure to close input devices under WinNT, Win2K, and
probably later systems causes the OS to crash.
This is accomplished with a .LIB/.DLL pair, linking to the .LIB
in order to access functions in the .DLL.
PortMidi for Win32 exists as a simple library,
with Win32-specific code in pmwin.c and MM-specific code in pmwinmm.c.
pmwin.c uses a DLL in pmdll.c to call Pm_Terminate() when the program
exits to make sure that all MIDI ports are closed.
Orderly cleanup after errors are encountered is based on a fixed order of
steps and state changes to reflect each step. Here's the order:
To open input:
initialize return value to NULL
- allocate the PmInternal strucure (representation of PortMidiStream)
return value is (non-null) PmInternal structure
- allocate midi buffer
set buffer field of PmInternal structure
- call system-dependent open code
- allocate midiwinmm_type for winmm dependent data
set descriptor field of PmInternal structure
- open device
set handle field of midiwinmm_type structure
- allocate buffer 1 for sysex
buffer is added to input port
- allocate buffer 2 for sysex
buffer is added to input port
- return
- return
|