README_WIN.txt (15978B)
1 File: PortMidi Win32 Readme 2 Author: Belinda Thom, June 16 2002 3 Revised by: Roger Dannenberg, June 2002, May 2004, June 2007, 4 Umpei Kurokawa, June 2007 5 Roger Dannenberg Sep 2009 6 7 Contents: 8 Using Portmidi 9 To Install Portmidi 10 To Compile Portmidi 11 About Cmake 12 Using other versions of Visual C++ 13 To Create Your Own Portmidi Client Application 14 15 16 17 ============================================================================= 18 USING PORTMIDI: 19 ============================================================================= 20 21 Using Microsoft Visual C++ project files (provided with PortMidi), there 22 are two configurations of the PortMidi library. The Debug version is 23 intended for debugging, especially in a console application. The Debug 24 version enables some extra error checking and outputs some text as well 25 as a prompt to type ENTER so that you don't lose any debugging text when 26 the program exits. You can turn off this extra debugging info by taking 27 out the compile-time definition for DEBUG. (But leave _DEBUG, which I 28 think is important for compiling in Debug mode.) This debugging version also 29 defines PM_CHECK_ERRORS, which forces a check for error return codes from 30 every call to PortMidi. You can disable this checking (especially if you 31 want to handle error codes in your own way) by removing PM_CHECK_ERRORS 32 from the predefined symbols list in the Settings dialog box. 33 34 PortMidi is designed to run without a console and should work perfectly 35 well within a graphical user interface application. The Release version 36 is both optimized and lacking the debugging printout code of the Debug 37 version. 38 39 Read the portmidi.h file for PortMidi API details on using the PortMidi API. 40 See <...>\pm_test\test.c and other files in pm_test for usage examples. 41 42 ============================================================================= 43 TO INSTALL PORTMIDI: 44 ============================================================================= 45 1) get current source from the portmedia project at SourceForge.net 46 47 2) copy source into directory: <...>\portmidi 48 49 ============================================================================= 50 TO COMPILE PORTMIDI: 51 ============================================================================= 52 53 3) cd to or open the portmidi directory 54 55 4) start or click on the portmidi.sln workspace (note, all Visual Studio 56 files are built by CMake. If you need a different version or have 57 problems with paths, try rebuilding the Visual Studio project files 58 using CMake -- See "Using other versions of visual C++" below.) 59 60 5) the following projects exist within this workspace: 61 - portmidi-static, portmidi-dynamic (versions of the PortMidi library) 62 - test (simple midi I/O testing) 63 - midithread (an example illustrating low-latency MIDI processing 64 using a dedicated low-latency thread) 65 - sysex (simple sysex message I/O testing) 66 - latency (uses porttime to measure system latency) 67 - midithru (an example illustrating software MIDI THRU) 68 - qtest (a test of the new multicore-safe queue implementation) 69 - mm (allows monitoring of midi messages) 70 - pmjni (a dll to provide an interface to PortMidi for Java) 71 72 6) set the Java SDK path using one of two methods: 73 Method 1: open portmidi/CMakeLists.txt with CMake, configure, and 74 generate -- this should find the Java SDK path and update your 75 solution and project files 76 Method 2: (does not require CMake): 77 - open the pmjni project properties 78 - visit Configuration Properties, C/C++, General 79 - find Additional Include Directories property and open the editor (...) 80 - at the end of the list, you will find two paths mentioning Java 81 - these are absolute paths to the Java SDK; you'll need to install the 82 Java SDK (from Sun) and update these directories in order to build 83 this project. 84 - similarly, the Linker->Input->Additional Dependencies list has a 85 path to the jvm.lib file, which needs to be correct(ed). 86 87 6) use Build->Batch Build ... to build everything in the project. If a 88 build fails, try building again. There seem to be some missing 89 dependencies, so you may have to "ALL_BUILD" several times before 90 everything builds successfully. 91 92 7) The settings for these projects were distributed in the zip file, so 93 compile should just work. 94 95 8) run test project; use the menu that shows up from the command prompt to 96 test that portMidi works on your system. tests include: 97 - verify midi output works 98 - verify midi input works 99 100 9) run other projects if you wish: sysex, latency, midithread, mm, 101 qtest, midithru 102 103 10) compile the java code: 104 - cd pm_java 105 - make.bat 106 + If there is a problem running javac, note that you must have 107 a path to javac.exe on your PATH environment variable. Edit 108 your path (in Vista) using Control Panel > User Accounts > 109 User Accounts > Change my environment variables; then select 110 Path and click Edit... After changing, you will have to 111 restart the command window to see any effect. 112 + In Vista, you may get a warning about running 113 UpdateRsrcJavaExe.exe. This is called by make.bat, and you 114 should allow the program to run. 115 + Note that make.bat does not build pmjni\jportmidi_JPortMidiApi.h 116 because it is included in the distribution. You can rebuild it 117 from sources as follows: 118 cd pm_java 119 javah jportmidi.JPortMidiApi 120 move jportmidi_JPortMidiApi pmjni\jportmidi_JPortMidiApi.h 121 122 11) you might wish to move pm_java/win32 to another location; run the 123 pmdefaults.exe program from the (entire) win32 directory to use 124 PmDefaults. This program let's you select default input/output 125 midi devices for PortMidi applications. 126 127 ============================================================================ 128 ABOUT CMAKE 129 ============================================================================ 130 131 cmake was used to generate .vcproj files. cmake embeds absolute paths 132 into .vcproj files, which makes the files non-portable to other systems. 133 To work around this problem, pm_win\clean_up_vcproj.bat can be used to 134 replace absolute paths with relative paths. To use it, you will need to 135 install gawk and set your search path to allow you to execute gawk, e.g. 136 my path includes "C:\Program Files\GnuWin32\bin;". You will also need to 137 edit pm_win\clean_up_vcproj.awk, replacing C:\Users\rbd\portmidi with 138 whatever absolute path cmake uses in your vcproj files. 139 140 This is not a general or robust fix, but it seems to work with the 141 vcproj files currently created by CMake. 142 143 ============================================================================ 144 USING OTHER VERSIONS OF VISUAL C++ 145 ============================================================================ 146 147 You can use cmake to make Visual Studio solution and project files. 148 If you do not want to use the provided Version 9 project files, install 149 cmake, run it, set the "Where is the source code" box to your portmidi 150 directory, and click on Configure. A menu will allow you to choose the 151 Visual Studio project version you want. Click Configure once again, then 152 Generate, and you should be all set to open portmidi.sln. 153 154 ============================================================================ 155 TO CREATE YOUR OWN PORTMIDI CLIENT APPLICATION: 156 ============================================================================ 157 158 NOTE: this section needs to be reviewed and tested. My suggestion would 159 be to copy the test project file (test.dsp) and modify it. -RBD 160 161 The easiest way is to start a new project w/in the portMidi workspace: 162 163 1) To open new project: 164 - File->New->Projects 165 - Location: <...>\portmidi\<yourProjectName> 166 - check Add to current workspace 167 - select Win32 Console Application (recommended for now) 168 - do *NOT* select the "make dependency" box (you will explicitly do this 169 in the next step) 170 - Click OK 171 - Select "An Empty Project" and click Finish 172 173 In Visual C++ 2005 Express Edition, 174 - File->New->Projects 175 - Location: <...>\portmidi\<yourProjectName> 176 - select Add to solution 177 - select CLR Empty project in CLR 178 - select Win32 Console Application in Win32 179 - select Empty project in General 180 181 2) Now this project will be the active project. Make it explicitly depend 182 on PortMidi dll: 183 - Project->Dependencies 184 - Click pm_dll 185 186 3) add whatever files you wish to add to your new project, using portMidi 187 calls as desired (see USING PORTMIDI at top of this readme) 188 189 4) when you include portMidi files, do so like this: 190 - #include "..\pm_common\portmidi.h" 191 - etc. 192 193 5) build and run your project 194 195 ============================================================================ 196 DESIGN NOTES 197 ============================================================================ 198 199 PortMidi for Win32 exists as a simple static library, 200 with Win32-specific code in pmwin.c and MM-specific code in pmwinmm.c. 201 202 Orderly cleanup after errors are encountered is based on a fixed order of 203 steps and state changes to reflect each step. Here's the order: 204 205 To open input: 206 initialize return value to NULL 207 - allocate the PmInternal strucure (representation of PortMidiStream) 208 return value is (non-null) PmInternal structure 209 - allocate midi buffer 210 set buffer field of PmInternal structure 211 - call system-dependent open code 212 - allocate midiwinmm_type for winmm dependent data 213 set descriptor field of PmInternal structure 214 - open device 215 set handle field of midiwinmm_type structure 216 - allocate buffers 217 - start device 218 - return 219 - return 220 221 SYSEX HANDLING -- the most complex, least exercised, and therefore most 222 buggy part of PortMidi (but maybe bugs are finally gone) 223 224 There are three cases: simple output, stream output, input 225 Each must deal with: 226 1. Buffer Initialization (creating buffers) 227 2. Buffer Allocation (finding a free buffer) 228 3. Buffer Fill (putting bytes in the buffer) 229 4. Buffer Preparation (midiOutPrepare, etc.) 230 5. Buffer Send (to Midi device) 231 6. Buffer Receive (in callback) 232 7. Buffer Empty (removing bytes from buffer) 233 8. Buffer Free (returning to the buffer pool) 234 9. Buffer Finalization (returning to heap) 235 236 Here's how simple output handles sysex: 237 1. Buffer Initialization (creating buffers) 238 allocated when code tries to write first byte to a buffer 239 the test is "if (!m->sysex_buffers[0]) { ... }" 240 this field is initialized to NULL when device is opened 241 the size is SYSEX_BYTES_PER_BUFFER 242 allocate_sysex_buffers() does the initialization 243 note that the actual size of the allocation includes 244 additional space for a MIDIEVENT (3 longs) which are 245 not used in this case 246 2. Buffer Allocation (finding a free buffer) 247 see get_free_sysex_buffer() 248 cycle through m->sysex_buffers[] using m->next_sysex_buffer 249 to determine where to look next 250 if nothing is found, wait by blocking on m->sysex_buffer_signal 251 this is signaled by the callback every time a message is 252 received 253 3. Buffer Fill (putting bytes in the buffer) 254 essentially a state machine approach 255 hdr->dwBytesRecorded is a position in message pointed to by m->hdr 256 keep appending bytes until dwBytesRecorded >= SYSEX_BYTES_PER_BUFFER 257 then send the message, reseting the state to initial values 258 4. Buffer Preparation (midiOutPrepare, etc.) 259 just before sending in winmm_end_sysex() 260 5. Buffer Send (to Midi device) 261 message is padded with zero at end (since extra space was allocated 262 this is ok) -- the zero works around a bug in (an old version of) 263 MIDI YOKE drivers 264 dwBufferLength gets dwBytesRecorded, and dwBytesRecorded gets 0 265 uses midiOutLongMsg() 266 6. Buffer Receive (in callback) 267 7. Buffer Empty (removing bytes from buffer) 268 not applicable for output 269 8. Buffer Free (returning to the buffer pool) 270 unprepare message to indicate that it is free 271 SetEvent on m->buffer_signal in case client is waiting 272 9. Buffer Finalization (returning to heap) 273 when device is closed, winmm_out_delete frees all sysex buffers 274 275 Here's how stream output handles sysex: 276 1. Buffer Initialization (creating buffers) 277 same code as simple output (see above) 278 2. Buffer Allocation (finding a free buffer) 279 same code as simple output (see above) 280 3. Buffer Fill (putting bytes in the buffer) 281 essentially a state machine approach 282 m->dwBytesRecorded is a position in message 283 keep appending bytes until buffer is full (one byte to spare) 284 4. Buffer Preparation (midiOutPrepare, etc.) 285 done before sending message 286 dwBytesRecorded and dwBufferLength are set in winmm_end_sysex 287 5. Buffer Send (to Midi device) 288 uses midiStreamOutMsg() 289 6. Buffer Receive (in callback) 290 7. Buffer Empty (removing bytes from buffer) 291 not applicable for output 292 8. Buffer Free (returning to the buffer pool) 293 unprepare message to indicate that it is free 294 SetEvent on m->buffer_signal in case client is waiting 295 9. Buffer Finalization (returning to heap) 296 when device is closed, winmm_out_delete frees all sysex buffers 297 298 299 Here's how input handles sysex: 300 1. Buffer Initialization (creating buffers) 301 two buffers are allocated in winmm_in_open 302 2. Buffer Allocation (finding a free buffer) 303 same code as simple output (see above) 304 3. Buffer Fill (putting bytes in the buffer) 305 not applicable for input 306 4. Buffer Preparation (midiOutPrepare, etc.) 307 done before sending message -- in winmm_in_open and in callback 308 5. Buffer Send (to Midi device) 309 uses midiInAddbuffer in allocate_sysex_input_buffer (called from 310 winmm_in_open) and callback 311 6. Buffer Receive (in callback) 312 7. Buffer Empty (removing bytes from buffer) 313 done without pause in loop in callback 314 8. Buffer Free (returning to the buffer pool) 315 done by midiInAddBuffer in callback, no pointer to buffers 316 is retained except by device 317 9. Buffer Finalization (returning to heap) 318 when device is closed, empty buffers are delivered to callback, 319 which frees them 320 321 IMPORTANT: In addition to the above, PortMidi now has 322 "shortcuts" to optimize the transfer of sysex data. To enable 323 the optimization for sysex output, the system-dependent code 324 sets fields in the pmInternal structure: fill_base, fill_offset_ptr, 325 and fill_length. When fill_base is non-null, the system-independent 326 part of PortMidi is allowed to directly copy sysex bytes to 327 "fill_base[*fill_offset_ptr++]" until *fill_offset_ptr reaches 328 fill_length. See the code for details. 329 330 ----------- 331 332 Additional notes on using VS 2005 (maybe this is obsolete now?): 333 334 1) Make sure "Configuration: All Configurations" is selected in all of the following Properties modifications! 335 336 2) In my case the project defaulted to compiling all .c files with the C++ compiler, which was disastrous. I had to go to set Properties for each file, to wit: Expand Configuration Properties, Expand C/C++, Select Advanced, set the Compile As popup to Compile as C Code (/TC). (For better or worse, the project I inherited has a bunch of .c files that rely on C++ features, so I couldn't reliably set this the project properties level.) 337 338 3) While you're there, make sure that the C/C++ -> General -> "Compile with Common Language Runtime support" is set to "No Common Language Runtime support" (the C compiler *can't* support CLR, but VS won't do anything useful like automatically set the two options to match)-. 339 340 4) I never got VS precompiled header thing to work sensibly, so I took the path of least resistance and turned PCH's off for all my files. Properties -> Configuration Properties -> C/C++ -> Precompiled Headers -> Create/Use Precompiled Header popup set to "Not Using Precompiled Headers". The compiler is reasonably fast even if it has to parse all the header files, so unless someone wants to explain VS's PCHs to me, the hell with it, I say. 341