Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
11 KiB

  1. MIDI Mapper Control Panel Applet Mike McQueen (t-mikemc) 1-Oct-90
  2. --------------------------------
  3. Hastily updated by LaurieGr
  4. This document describes how the MIDI Mapper applet was put together, in
  5. order to hopefully make it easier for someone other than myself to find
  6. and fix any bugs or change some features.
  7. Currently the source for this applet is divided into seven modules,
  8. four header files and a resource script file.
  9. Descrption of MIDI Mapper applet:
  10. ================================
  11. Modules
  12. -------
  13. LIBINIT.ASM
  14. Contains the LibEntry function. This piece of code sends shivers
  15. up my spine every time I look at it. Someone (other than ToddLa)
  16. really ought to make a nice clean standard DLL entry point asm
  17. module. Doesn't apply to NT.
  18. MIDI.C
  19. Contains the LibMain and WEP functions for windows.
  20. Contains the CPlApplet export function for multimedia control panel.
  21. This is the entry point that the controlpanel calls.
  22. Start debugging here!
  23. Contains the 'MIDI Mapper' dialog box function. Among other things,
  24. this dialog box has three combo boxes into which the available setups,
  25. patchmaps and keymaps are respectively enumerated. When someone
  26. deletes a map, it's not actually deleted from the file, but rather
  27. its entry is simply removed from the combo box. If the guy then
  28. clicks on the 'OK' button, interpreted as 'OK, go ahead and actually
  29. delete the maps', I compare the available maps to the maps left
  30. in the combo boxes, and delete any discrepancies. This is done in
  31. the EnumFunc function described below.
  32. This module also contains several functions that are used by one or
  33. more of the map editing modules. I probably should have thrown
  34. together a 'MISC.C' module and tossed all these functions in there,
  35. but in any case all these functions are at the bottom of the file.
  36. The WriteBoxRect and SizeBox functions were only used in the version
  37. of the applet that allowed sizing of map-editing boxes. If sizing
  38. is never ever going to be used, these can be removed.
  39. **EnumFunc**
  40. This lovely little treat of a function is the callback for the
  41. mapEnumerate function from midimap.c in the MMSYSTEM DLL. it is used
  42. by calls to mapEnumerate from 3 different modules, MIDI.C, SETUP.C
  43. and PATCH.C.
  44. mapEnumerate is called to enumerate Setups, Maps, Patches or ports
  45. which don't have an awful lot in common. It's also called from
  46. all over the place. The price for having only one copy of the 16
  47. statements that actually do the enumeration is that all the different
  48. callback functions are forced into the same straightjacket of
  49. parameters. On 16 bit it inevitably had a handle packed into half
  50. a DWORD. The callback which is executed once for each element now
  51. has three parameters to cater for all cases (with a little casting)
  52. and some subset of these are actually used in each case.
  53. The SETUP.C and PATCH.C modules simply call it to enumerate the
  54. available patchmaps and keymaps into their combo boxes, respectively.
  55. In MIDI.C, the HIWORD of the dwUser parameter is either set to
  56. MMENUM_DELETE, MMENUM_BASIC or MMENUM_INTOCOMBO.
  57. If it is set to MMENUM_INTOCOMBO, it indicates that this enumeration
  58. is taking place into the combo box of the MIDI Mapper dialog box.
  59. When this happens, a handle is allocated for the length of the
  60. description string, and this handle is set to be the new combo box
  61. entry's ITEMDATA. This is how I update the description when the user
  62. changes the current selection in the combo box in the main dialog.
  63. If it is set to MMENUM_DELETE, it indicates that a check is being done
  64. to see if any entrys in the combo box differ from the available maps
  65. being enumerated. In this case, if a map name is sent to EnumFunc
  66. from mapEnumerate, and it does not exist in the combo box, it will be
  67. deleted right then and there with a call to mapDelete (another
  68. midimap.c function).
  69. SETUP.C
  70. PATCH.C
  71. KEY.C
  72. These modules are pretty similar in content, so I am going to try to
  73. describe them all in one plop. A lot of the functions from these
  74. three modules have the same name, but are prefixed with 'Setup',
  75. 'Patch' or 'Key' depending on which module they are in. I'm going to
  76. use 'xxx' to mean any or all of those three prefixes.
  77. The 'xxxBox' functions are the three dialog box functions for the
  78. three map-editing dialog boxes.
  79. The 'xxxPaint' functions are the only places where anything is ever
  80. drawn on the screen. These functions are essentially the BeginPaint
  81. EndPaint blocks for each map editor.
  82. In the setup editor, I do a funny little trick to allow tabbing onto
  83. three-state buttons, and it would probably be a good idea to explain
  84. it. Every time SetupSetFocus is called, I remove the WS_TABSTOP style
  85. attribute from the 3-state button on the last edit line, and add it
  86. to the 3-state button on the new edit line. I also change the text to
  87. "&A" which allows the ALT-A accelerator to work.
  88. Global variables which pertain to all three of these modules are
  89. described under the 'extern.h' header file.
  90. PROPBOX.C
  91. Contains only a dialog box function for getting properties for a new
  92. map of any type. If the 'fSaveAs' variable is set, it will
  93. automagically check for duplicate names. Unfortunately, I don't have
  94. any way of doing a 'save as...' in the current version. If you think
  95. of a way, you could just call this dialog box with the fSaveAs
  96. variable set.
  97. CPARROW.C
  98. Contains a routine for registering a window class for a control panel
  99. arrow control, as well as the window function for that class. There
  100. is a arrow in WINCOM, and there is another arrow in SCRNSVR (that's
  101. where I stole this code from). I think my version works/looks better
  102. than both of the others. I also think it still needs to be worked
  103. on. I think that if and when this ever gets done, it should go in
  104. WINCOM and then the static link modules could go away.
  105. Headers
  106. -------
  107. MIDI.H
  108. Contains all sorts of definitions, and I've tried to document them
  109. as best as possible.
  110. PRECLUDE.H
  111. Contains 'preclude' definitions for windows.h and mmsystem.h, to
  112. make compiling a little faster.
  113. CPARROW.H
  114. Contains the prototypes for the arrow class (un)registering functions.
  115. EXTERN.H
  116. Contains external variable definitions, with limited comments. I'll
  117. comment them again right here:
  118. extern HWND hWnd // 'Current' window handle
  119. hEdit, // Edit control handle
  120. hArrow; // Arrow control handle
  121. extern RECT rcBox; // Clipping/scroll rectangle
  122. extern int rgxPos [8], // horizontal line positions
  123. yBox, // rows of data y extent
  124. xClient, // Window client area x pixels
  125. yClient, // Window client area y pixels
  126. iCurPos, // Current position on screen
  127. iVertPos, // Current vertical scroll position
  128. iVertMax, // Maximum veritcal scroll position
  129. nLines, // Number of lines of data
  130. yChar, // Height of character in font
  131. xChar, // Width of average character in font
  132. iMap; // Flag for GetMBData
  133. extern char szCurrent [], // Name of current map
  134. szCurDesc [], // Description of current map
  135. szMidiCtl [], // "MIDI Control Panel"
  136. szNone []; // Static text string '[ None ]'
  137. extern BOOL fModified, // Has map been modified?
  138. fNew, // Is this a new map?
  139. fSaveAs, // Is propbox being used for Save As?
  140. fHidden; // Is the active edit line hidden?
  141. Resource script
  142. ---------------
  143. midi.rc
  144. Problems with MIDI Mapper applet:
  145. ================================
  146. Currently, the maximum number of any type of map (setup,patchmap,keymap) is
  147. limited to 100. This is a deficiency in midimap routines which are part of
  148. mmsystem. If someone calls the mapWrite function with the flag set to the
  149. type of a map of which there are 100, the write will fail. The only way to
  150. currently get around this problem is deleting maps.
  151. In the process of changing the current selection of either the "Keymap Name"
  152. combobox in the Patchmap editor, or the "Patchmap Name" combobox in the Setup
  153. editor, memory is potentially being reallocated without fail checks, which
  154. means it should be possible to run out of memory in a bad way if the current
  155. selection of these comboboxes is changed a lot.
  156. For the patchmap editor, all keymaps are the
  157. same size. I should never have to reallocate the whole setup just so it turns
  158. out to be the exact same size! Anyway, the problem arises when you have a
  159. patchmap with some keymaps. Someone derefernces a keymap from a specific
  160. patch number in the patchmap editor (that is, selects the [none] entry for
  161. that particular patch). This in turns causes the keymap offset of that
  162. patchmap to be set to zero. If the person proceeds to re-reference that
  163. patchmap back to the same keymap, or any other keymap, the entire setup will
  164. be reallocated, to the same size. Although this will call will probably never
  165. fail, it is unnecessary.
  166. A flag lying around in the patchmap structure which indicates that the memory
  167. for a keymap has been allocated make this very useful. Perhaps it would be a
  168. good idea to define a range of flags in the dwFlags structure entry of the
  169. MIDIKEYMAP/MIDIPATCHMAP/MIDIMAP data structures which are for internal use
  170. only, some reserved bits.
  171. The formula for the size of the new setup is <old setupsize> + <new patchsize>,
  172. which does not take into account subtracting <old patchsize>. The reason for
  173. this is that the patchmap may be referenced by other channels in the setup.
  174. You cannot free the memory of the patchmap just because one channel doesn't
  175. reference it anymore. The thing is, it would be really easy to check and see
  176. if anyother channel references it. There are two APIs called:
  177. mapPatchMapInSetup and..
  178. mapKeyMapInPatchMap
  179. which are exported from mmsystem. These routines should be used by the
  180. SetupComboMsg
  181. function, under the CBN_SELCHANGE message. It is here that the existence
  182. of any given patchmap name in the current setup can be determined by calls
  183. to the former API. It is not necessary to reallocate an entire setup if
  184. one channel in that setup suddenly references a patchmap that is already
  185. referenced in that setup. All that should happen is the new channel's
  186. patchmap offset value should be set to that of the existing channel. In a
  187. similar instance, if a patchmap is dereferenced by a channel of a setup, and
  188. it is determined that no other channels of that setup use that patchmap, the
  189. size of that patchmap may be subtracted from the setup reallocation size.