Update of /cvsroot/pure-data/pd/portmidi/pm_win In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5166/pd/portmidi/pm_win
Modified Files: README_WIN.txt copy-dll.bat pm_dll.dsp pmwin.c pmwinmm.c Log Message: 0.41-0 test 11
Index: README_WIN.txt =================================================================== RCS file: /cvsroot/pure-data/pd/portmidi/pm_win/README_WIN.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** README_WIN.txt 15 Dec 2005 00:57:00 -0000 1.1 --- README_WIN.txt 16 Jan 2008 21:54:10 -0000 1.2 *************** *** 21,25 **** 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 --- 21,26 ---- 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. (But leave _DEBUG, which I ! think is important for compiling in Debug mode.) 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 *************** *** 46,52 **** =============================================================================
! 3) go to this directory
! 4) click on the portmidi.dsw workspace
5) the following projects exist within this workspace: --- 47,53 ---- =============================================================================
! 3) cd to or open the portmidi directory
! 4) start or click on the portmidi.dsw workspace
5) the following projects exist within this workspace: *************** *** 61,76 ****
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): --- 62,75 ----
6) verify that all project settings are for Win32 Debug release: ! - type Alt-F7 - highlight all three projects in left part of Project Settings window; - "Settings For" should say "Win32 Debug"
! 7) use Build->Batch Build ... to build everything in the project
! 8) The settings for these projects were distributed in the zip file, so compile should just work.
! 9) 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): *************** *** 95,99 **** 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 --- 94,98 ---- ensure that the application uses the correct DLL.
! 10) 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 *************** *** 101,105 **** - verify midi input w/midi thru works
! 12) run other projects if you wish: sysex, latency, and midithread
============================================================================ --- 100,104 ---- - verify midi input w/midi thru works
! 11) run other projects if you wish: sysex, latency, midithread, mm, qtest
============================================================================ *************** *** 180,183 **** --- 179,291 ---- - return
+ SYSEX HANDLING -- the most complex, least exercised, and therefore most + buggy part of PortMidi (but maybe bugs are finally gone) + + There are three cases: simple output, stream output, input + Each must deal with: + 1. Buffer Initialization (creating buffers) + 2. Buffer Allocation (finding a free buffer) + 3. Buffer Fill (putting bytes in the buffer) + 4. Buffer Preparation (midiOutPrepare, etc.) + 5. Buffer Send (to Midi device) + 6. Buffer Receive (in callback) + 7. Buffer Empty (removing bytes from buffer) + 8. Buffer Free (returning to the buffer pool) + 9. Buffer Finalization (returning to heap) + + Here's how simple output handles sysex: + 1. Buffer Initialization (creating buffers) + allocated when code tries to write first byte to a buffer + the test is "if (!m->sysex_buffers[0]) { ... }" + this field is initialized to NULL when device is opened + the size is SYSEX_BYTES_PER_BUFFER + allocate_sysex_buffers() does the initialization + note that the actual size of the allocation includes + additional space for a MIDIEVENT (3 longs) which are + not used in this case + 2. Buffer Allocation (finding a free buffer) + see get_free_sysex_buffer() + cycle through m->sysex_buffers[] using m->next_sysex_buffer + to determine where to look next + if nothing is found, wait by blocking on m->sysex_buffer_signal + this is signaled by the callback every time a message is + received + 3. Buffer Fill (putting bytes in the buffer) + essentially a state machine approach + hdr->dwBytesRecorded is a position in message pointed to by m->hdr + keep appending bytes until dwBytesRecorded >= SYSEX_BYTES_PER_BUFFER + then send the message, reseting the state to initial values + 4. Buffer Preparation (midiOutPrepare, etc.) + just before sending in winmm_end_sysex() + 5. Buffer Send (to Midi device) + message is padded with zero at end (since extra space was allocated + this is ok) -- the zero works around a bug in (an old version of) + MIDI YOKE drivers + dwBufferLength gets dwBytesRecorded, and dwBytesRecorded gets 0 + uses midiOutLongMsg() + 6. Buffer Receive (in callback) + 7. Buffer Empty (removing bytes from buffer) + not applicable for output + 8. Buffer Free (returning to the buffer pool) + unprepare message to indicate that it is free + SetEvent on m->buffer_signal in case client is waiting + 9. Buffer Finalization (returning to heap) + when device is closed, winmm_out_delete frees all sysex buffers + + Here's how stream output handles sysex: + 1. Buffer Initialization (creating buffers) + same code as simple output (see above) + 2. Buffer Allocation (finding a free buffer) + same code as simple output (see above) + 3. Buffer Fill (putting bytes in the buffer) + essentially a state machine approach + m->dwBytesRecorded is a position in message + keep appending bytes until buffer is full (one byte to spare) + 4. Buffer Preparation (midiOutPrepare, etc.) + done before sending message + dwBytesRecorded and dwBufferLength are set in winmm_end_sysex + 5. Buffer Send (to Midi device) + uses midiStreamOutMsg() + 6. Buffer Receive (in callback) + 7. Buffer Empty (removing bytes from buffer) + not applicable for output + 8. Buffer Free (returning to the buffer pool) + unprepare message to indicate that it is free + SetEvent on m->buffer_signal in case client is waiting + 9. Buffer Finalization (returning to heap) + when device is closed, winmm_out_delete frees all sysex buffers
+ Here's how input handles sysex: + 1. Buffer Initialization (creating buffers) + two buffers are allocated in winmm_in_open + 2. Buffer Allocation (finding a free buffer) + same code as simple output (see above) + 3. Buffer Fill (putting bytes in the buffer) + not applicable for input + 4. Buffer Preparation (midiOutPrepare, etc.) + done before sending message -- in winmm_in_open and in callback + 5. Buffer Send (to Midi device) + uses midiInAddbuffer in allocate_sysex_input_buffer (called from + winmm_in_open) and callback + 6. Buffer Receive (in callback) + 7. Buffer Empty (removing bytes from buffer) + done without pause in loop in callback + 8. Buffer Free (returning to the buffer pool) + done by midiInAddBuffer in callback, no pointer to buffers + is retained except by device + 9. Buffer Finalization (returning to heap) + when device is closed, empty buffers are delivered to callback, + which frees them + + IMPORTANT: In addition to the above, PortMidi now has + "shortcuts" to optimize the transfer of sysex data. To enable + the optimization for sysex output, the system-dependent code + sets fields in the pmInternal structure: fill_base, fill_offset_ptr, + and fill_length. When fill_base is non-null, the system-independent + part of PortMidi is allowed to directly copy sysex bytes to + "fill_base[*fill_offset_ptr++]" until *fill_offset_ptr reaches + fill_length. See the code for details. + + + \ No newline at end of file
Index: pmwin.c =================================================================== RCS file: /cvsroot/pure-data/pd/portmidi/pm_win/pmwin.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pmwin.c 15 Dec 2005 00:57:02 -0000 1.1 --- pmwin.c 16 Jan 2008 21:54:10 -0000 1.2 *************** *** 14,17 **** --- 14,18 ---- #include "stdlib.h" #include "portmidi.h" + #include "pmutil.h" #include "pminternal.h" #include "pmwinmm.h"
Index: copy-dll.bat =================================================================== RCS file: /cvsroot/pure-data/pd/portmidi/pm_win/copy-dll.bat,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** copy-dll.bat 15 Dec 2005 00:57:02 -0000 1.1 --- copy-dll.bat 16 Jan 2008 21:54:10 -0000 1.2 *************** *** 4,7 **** --- 4,9 ---- copy Debug\pm_dll.dll ..\pm_test\latencyDebug\pm_dll.dll copy Debug\pm_dll.dll ..\pm_test\midithruDebug\pm_dll.dll + copy Debug\pm_dll.dll ..\pm_test\qtestDebug\pm_dll.dll + copy Debug\pm_dll.dll ..\pm_test\mmDebug\pm_dll.dll
copy Release\pm_dll.dll ..\pm_test\testRelease\pm_dll.dll *************** *** 10,13 **** --- 12,17 ---- copy Release\pm_dll.dll ..\pm_test\latencyRelease\pm_dll.dll copy Release\pm_dll.dll ..\pm_test\midithruRelease\pm_dll.dll + copy Release\pm_dll.dll ..\pm_test\qtestRelease\pm_dll.dll + copy Release\pm_dll.dll ..\pm_test\mmRelease\pm_dll.dll
Index: pm_dll.dsp =================================================================== RCS file: /cvsroot/pure-data/pd/portmidi/pm_win/pm_dll.dsp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pm_dll.dsp 15 Dec 2005 00:57:02 -0000 1.1 --- pm_dll.dsp 16 Jan 2008 21:54:10 -0000 1.2 *************** *** 39,44 **** # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 ! # PROP Output_Dir "pm_win\Release" ! # PROP Intermediate_Dir "pm_win\Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" --- 39,44 ---- # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 ! # PROP Output_Dir "Release" ! # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" *************** *** 65,74 **** # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 ! # PROP Output_Dir "pm_win\Debug" ! # PROP Intermediate_Dir "pm_win\Debug" # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PM_DLL_EXPORTS" /YX /FD /GZ /c ! # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "pm_common" /D "_WINDOWS" /D "_USRDLL" /D "PM_DLL_EXPORTS" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "USE_DLL_FOR_CLEANUP" /FR /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 --- 65,74 ---- # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 ! # PROP Output_Dir "Debug" ! # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PM_DLL_EXPORTS" /YX /FD /GZ /c ! # ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "pm_common" /D "_WINDOWS" /D "_USRDLL" /D "PM_DLL_EXPORTS" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "USE_DLL_FOR_CLEANUP" /FR /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
Index: pmwinmm.c =================================================================== RCS file: /cvsroot/pure-data/pd/portmidi/pm_win/pmwinmm.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pmwinmm.c 15 Dec 2005 00:57:02 -0000 1.1 --- pmwinmm.c 16 Jan 2008 21:54:10 -0000 1.2 *************** *** 1,7 **** --- 1,14 ---- /* pmwinmm.c -- system specific definitions */
+ /* without this define, InitializeCriticalSectionAndSpinCount is undefined */ + /* this version level means "Windows 2000 and higher" */ + #define _WIN32_WINNT 0x0500 + #include "windows.h" #include "mmsystem.h" #include "portmidi.h" [...1881 lines suppressed...] if (winmm_has_host_error(midi)) { winmm_get_host_error(midi, msg, PM_HOST_ERROR_MSG_LEN); ! printf("%s\n", msg); } #endif *************** *** 1538,1541 **** --- 1450,1461 ---- } } + if (midi_in_caps) { + pm_free(midi_in_caps); + midi_in_caps = NULL; + } + if (midi_out_caps) { + pm_free(midi_out_caps); + midi_out_caps = NULL; + } #ifdef DEBUG if (doneAny) {