mirror of https://github.com/tongzx/nt5src
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.
11 KiB
11 KiB
MIDI Mapper Control Panel Applet Mike McQueen (t-mikemc) 1-Oct-90
--------------------------------
Hastily updated by LaurieGr
This document describes how the MIDI Mapper applet was put together, in
order to hopefully make it easier for someone other than myself to find
and fix any bugs or change some features.
Currently the source for this applet is divided into seven modules,
four header files and a resource script file.
Descrption of MIDI Mapper applet:
================================
Modules
-------
LIBINIT.ASM
Contains the LibEntry function. This piece of code sends shivers
up my spine every time I look at it. Someone (other than ToddLa)
really ought to make a nice clean standard DLL entry point asm
module. Doesn't apply to NT.
MIDI.C
Contains the LibMain and WEP functions for windows.
Contains the CPlApplet export function for multimedia control panel.
This is the entry point that the controlpanel calls.
Start debugging here!
Contains the 'MIDI Mapper' dialog box function. Among other things,
this dialog box has three combo boxes into which the available setups,
patchmaps and keymaps are respectively enumerated. When someone
deletes a map, it's not actually deleted from the file, but rather
its entry is simply removed from the combo box. If the guy then
clicks on the 'OK' button, interpreted as 'OK, go ahead and actually
delete the maps', I compare the available maps to the maps left
in the combo boxes, and delete any discrepancies. This is done in
the EnumFunc function described below.
This module also contains several functions that are used by one or
more of the map editing modules. I probably should have thrown
together a 'MISC.C' module and tossed all these functions in there,
but in any case all these functions are at the bottom of the file.
The WriteBoxRect and SizeBox functions were only used in the version
of the applet that allowed sizing of map-editing boxes. If sizing
is never ever going to be used, these can be removed.
**EnumFunc**
This lovely little treat of a function is the callback for the
mapEnumerate function from midimap.c in the MMSYSTEM DLL. it is used
by calls to mapEnumerate from 3 different modules, MIDI.C, SETUP.C
and PATCH.C.
mapEnumerate is called to enumerate Setups, Maps, Patches or ports
which don't have an awful lot in common. It's also called from
all over the place. The price for having only one copy of the 16
statements that actually do the enumeration is that all the different
callback functions are forced into the same straightjacket of
parameters. On 16 bit it inevitably had a handle packed into half
a DWORD. The callback which is executed once for each element now
has three parameters to cater for all cases (with a little casting)
and some subset of these are actually used in each case.
The SETUP.C and PATCH.C modules simply call it to enumerate the
available patchmaps and keymaps into their combo boxes, respectively.
In MIDI.C, the HIWORD of the dwUser parameter is either set to
MMENUM_DELETE, MMENUM_BASIC or MMENUM_INTOCOMBO.
If it is set to MMENUM_INTOCOMBO, it indicates that this enumeration
is taking place into the combo box of the MIDI Mapper dialog box.
When this happens, a handle is allocated for the length of the
description string, and this handle is set to be the new combo box
entry's ITEMDATA. This is how I update the description when the user
changes the current selection in the combo box in the main dialog.
If it is set to MMENUM_DELETE, it indicates that a check is being done
to see if any entrys in the combo box differ from the available maps
being enumerated. In this case, if a map name is sent to EnumFunc
from mapEnumerate, and it does not exist in the combo box, it will be
deleted right then and there with a call to mapDelete (another
midimap.c function).
SETUP.C
PATCH.C
KEY.C
These modules are pretty similar in content, so I am going to try to
describe them all in one plop. A lot of the functions from these
three modules have the same name, but are prefixed with 'Setup',
'Patch' or 'Key' depending on which module they are in. I'm going to
use 'xxx' to mean any or all of those three prefixes.
The 'xxxBox' functions are the three dialog box functions for the
three map-editing dialog boxes.
The 'xxxPaint' functions are the only places where anything is ever
drawn on the screen. These functions are essentially the BeginPaint
EndPaint blocks for each map editor.
In the setup editor, I do a funny little trick to allow tabbing onto
three-state buttons, and it would probably be a good idea to explain
it. Every time SetupSetFocus is called, I remove the WS_TABSTOP style
attribute from the 3-state button on the last edit line, and add it
to the 3-state button on the new edit line. I also change the text to
"&A" which allows the ALT-A accelerator to work.
Global variables which pertain to all three of these modules are
described under the 'extern.h' header file.
PROPBOX.C
Contains only a dialog box function for getting properties for a new
map of any type. If the 'fSaveAs' variable is set, it will
automagically check for duplicate names. Unfortunately, I don't have
any way of doing a 'save as...' in the current version. If you think
of a way, you could just call this dialog box with the fSaveAs
variable set.
CPARROW.C
Contains a routine for registering a window class for a control panel
arrow control, as well as the window function for that class. There
is a arrow in WINCOM, and there is another arrow in SCRNSVR (that's
where I stole this code from). I think my version works/looks better
than both of the others. I also think it still needs to be worked
on. I think that if and when this ever gets done, it should go in
WINCOM and then the static link modules could go away.
Headers
-------
MIDI.H
Contains all sorts of definitions, and I've tried to document them
as best as possible.
PRECLUDE.H
Contains 'preclude' definitions for windows.h and mmsystem.h, to
make compiling a little faster.
CPARROW.H
Contains the prototypes for the arrow class (un)registering functions.
EXTERN.H
Contains external variable definitions, with limited comments. I'll
comment them again right here:
extern HWND hWnd // 'Current' window handle
hEdit, // Edit control handle
hArrow; // Arrow control handle
extern RECT rcBox; // Clipping/scroll rectangle
extern int rgxPos [8], // horizontal line positions
yBox, // rows of data y extent
xClient, // Window client area x pixels
yClient, // Window client area y pixels
iCurPos, // Current position on screen
iVertPos, // Current vertical scroll position
iVertMax, // Maximum veritcal scroll position
nLines, // Number of lines of data
yChar, // Height of character in font
xChar, // Width of average character in font
iMap; // Flag for GetMBData
extern char szCurrent [], // Name of current map
szCurDesc [], // Description of current map
szMidiCtl [], // "MIDI Control Panel"
szNone []; // Static text string '[ None ]'
extern BOOL fModified, // Has map been modified?
fNew, // Is this a new map?
fSaveAs, // Is propbox being used for Save As?
fHidden; // Is the active edit line hidden?
Resource script
---------------
midi.rc
Problems with MIDI Mapper applet:
================================
Currently, the maximum number of any type of map (setup,patchmap,keymap) is
limited to 100. This is a deficiency in midimap routines which are part of
mmsystem. If someone calls the mapWrite function with the flag set to the
type of a map of which there are 100, the write will fail. The only way to
currently get around this problem is deleting maps.
In the process of changing the current selection of either the "Keymap Name"
combobox in the Patchmap editor, or the "Patchmap Name" combobox in the Setup
editor, memory is potentially being reallocated without fail checks, which
means it should be possible to run out of memory in a bad way if the current
selection of these comboboxes is changed a lot.
For the patchmap editor, all keymaps are the
same size. I should never have to reallocate the whole setup just so it turns
out to be the exact same size! Anyway, the problem arises when you have a
patchmap with some keymaps. Someone derefernces a keymap from a specific
patch number in the patchmap editor (that is, selects the [none] entry for
that particular patch). This in turns causes the keymap offset of that
patchmap to be set to zero. If the person proceeds to re-reference that
patchmap back to the same keymap, or any other keymap, the entire setup will
be reallocated, to the same size. Although this will call will probably never
fail, it is unnecessary.
A flag lying around in the patchmap structure which indicates that the memory
for a keymap has been allocated make this very useful. Perhaps it would be a
good idea to define a range of flags in the dwFlags structure entry of the
MIDIKEYMAP/MIDIPATCHMAP/MIDIMAP data structures which are for internal use
only, some reserved bits.
The formula for the size of the new setup is <old setupsize> + <new patchsize>,
which does not take into account subtracting <old patchsize>. The reason for
this is that the patchmap may be referenced by other channels in the setup.
You cannot free the memory of the patchmap just because one channel doesn't
reference it anymore. The thing is, it would be really easy to check and see
if anyother channel references it. There are two APIs called:
mapPatchMapInSetup and..
mapKeyMapInPatchMap
which are exported from mmsystem. These routines should be used by the
SetupComboMsg
function, under the CBN_SELCHANGE message. It is here that the existence
of any given patchmap name in the current setup can be determined by calls
to the former API. It is not necessary to reallocate an entire setup if
one channel in that setup suddenly references a patchmap that is already
referenced in that setup. All that should happen is the new channel's
patchmap offset value should be set to that of the existing channel. In a
similar instance, if a patchmap is dereferenced by a channel of a setup, and
it is determined that no other channels of that setup use that patchmap, the
size of that patchmap may be subtracted from the setup reallocation size.