263 lines
6.3 KiB
Plaintext
263 lines
6.3 KiB
Plaintext
Conversion of mci midi sequencer.
|
|
Originals on \\sysuk1\data\win31mm\src\sonic\mciseq
|
|
|
|
|
|
|
|
|
|
|
|
List utility
|
|
------------
|
|
LIST H 1238 - List management definitions
|
|
LIST C 5648 - Memory management
|
|
|
|
SUPPORT C ** NEW FOR NT ** (replace .asm etc).
|
|
|
|
Common header file
|
|
------------------
|
|
MMSYS H 7810 - Common definitions for MCI and SEQ
|
|
|
|
MCI processing
|
|
--------------
|
|
MCISEQ H 5410 - Definitions for MCI part of driver
|
|
MCICMDS C 23354 - Commands from mciDriverEntry - msXxx
|
|
MCISEQ C 36751 - DriverProc -> mciDriverEntry
|
|
CALLBACK C 2147 - Sequencer callback
|
|
FORMATS C 10845 - Time formats
|
|
-- Convert to passing around MMTIME structures ?
|
|
|
|
Sequencer
|
|
---------
|
|
MMSEQI H 13524 - Definitions local to mmseq.c (internal sequencer)
|
|
MMSEQ C 63220 - midiSeqMessage - the sequencer
|
|
MMSEQ D 3116 - Doc
|
|
UTIL C 21200 - callback, track and timer helpers for sequencer
|
|
|
|
Other bits (not reqd for NT)
|
|
----------------------------
|
|
TASK ASM 2856 - interface to mmTask (why ?)
|
|
CRIT ASM 1895 - critical sections
|
|
MCISEQ DEF 304 - def file
|
|
|
|
|
|
DATA FLOW
|
|
==================================================================
|
|
|
|
|
|
MCI (MMSYS.H) SEQ
|
|
|
|
midiSeqMessage
|
|
(SEQ_...)
|
|
--------------------->
|
|
|
|
MIDISEQINFO
|
|
|
|
MIDISEQOPEN
|
|
|
|
MIDISEQHDR
|
|
|
|
|
|
MIDISEQCALLBACK
|
|
(MIDISEQ_...)
|
|
DONE -> TaskSignal - TO stream task
|
|
DONEPLAY -> TaskSignal - TO stream task
|
|
RESET -> StreamTrackReset -> TaskSignal
|
|
|
|
<---------------------
|
|
|
|
MIDISEQERR_...
|
|
<---------------------
|
|
|
|
|
|
==================================================================
|
|
|
|
|
|
|
|
Notes :
|
|
|
|
mciGetDriverData returns a pointer to the stream - SeqStreamType so
|
|
the stream is equated to a logical device.
|
|
|
|
GETMOTWORD = 'Get Motorola word' (!)
|
|
|
|
Within the timer interrupt routine use the critical section to get
|
|
the other side of the mutual exclusion.
|
|
|
|
SERIALIZATION : A critical section is used which is held over calls
|
|
to mciDriverEntry and in the sequencer tasks but released when
|
|
getting messages (blocking) or temporarily while yielding.
|
|
|
|
|
|
STRUCTURE
|
|
=========
|
|
|
|
DRV_... + MCI_... messages
|
|
(mciseq.c!DriverEntry)
|
|
|
|
|
|
|
V
|
|
|
|
MCI messages :
|
|
(mciseq.c!mciDriverEntry)
|
|
|
|
|
|
MCI_OPEN_DRIVER
|
|
mcicmds.c!msOpen
|
|
|
|
MCI_CLOSE_DRIVER
|
|
mcicmds.c!msClose
|
|
|
|
MCI_PLAY
|
|
mcicmds.c!msPlay
|
|
|
|
MCI_PAUSE
|
|
MCI_STOP
|
|
mmseq.c!midiSeqMessage SEQ_SETPORTOFF
|
|
|
|
MCI_SEEK
|
|
mcicmds.c!msSeek
|
|
|
|
MCI_STATUS
|
|
mcicmds.c!msStatus
|
|
|
|
MCI_GETDEVCAPS
|
|
mcicmds.c!msGetDevCaps
|
|
|
|
MCI_INFO
|
|
mcicmds.c!msInfo
|
|
|
|
MCI_SET
|
|
mcicmds.c!msSet
|
|
|
|
|
|
Rest unsupported
|
|
|
|
|
|
MMSEQ messages :
|
|
(mmseq.c!midiSeqMessage)
|
|
|
|
SEQ_OPEN
|
|
|
|
....................................................................
|
|
|
|
|
|
Tasking structure :
|
|
-------------------
|
|
|
|
|
|
Application task :
|
|
mcicmds.c!msOpen
|
|
|
|
|
V
|
|
mciseq.c!msOpenStream -> mmTaskCreate with routine mciStreamCycle
|
|
|
|
|
V
|
|
TaskSignal
|
|
PostAppMessage
|
|
.
|
|
. WTM_QUITTASK, WTM_DONEPLAY, WTM_FILLBUFFER
|
|
.
|
|
Sequencer task :
|
|
|
|
GetMessage
|
|
TaskBlock
|
|
|
|
|
V
|
|
mciseq.c!mciStreamCycle
|
|
|
|
|
V
|
|
mmseq.c!midiSeqMessage - SEQ_TRACKDATA, SEQ_SETPORTOFF
|
|
| SEQ_GETINFO
|
|
V
|
|
NewTrackData
|
|
|
|
|
|
mciStreamCycle just keeps the buffers for the current stream stoked up.
|
|
|
|
Thus : there is 1 (extra) task PER LOGICAL DEVICE.
|
|
There is 1 SEQ structure per task and 1 stream structure per task (which
|
|
contains an HMIDISEQ handle hSeq to the SEQ structure). The SEQ
|
|
structure remembers the HTASK.
|
|
|
|
|
|
The SeqStreamType structure is the per-stream data on the MCI side.
|
|
This is unfortunately shared between application and stream tasks.
|
|
|
|
|
|
There is no need to inhibit threading between sequencer tasks, only
|
|
between the main task and associated sequencer tasks.
|
|
|
|
Use of Yield etc :
|
|
|
|
mciseq.c!msOpenStream - appears to have a spurious yield near the start
|
|
|
|
mcicmds.c!msOpen - calls Yield to allow the stream task to start
|
|
properly. We need to force this to happen now. Note that this
|
|
is subtle because multiple people might be running - so we
|
|
probably need a special event per task.
|
|
|
|
mcicmds.c!msPlay - sits in a loop at the moment ! Need the event
|
|
again.
|
|
|
|
mmseq NEVER yields or blocks
|
|
|
|
mciseq.c!mciStreamCycle :
|
|
TaskBlock near start when finished init - other side of
|
|
Yield in msOpen. Also later Blocks again for more work.
|
|
This is the other side of msPlay ?
|
|
|
|
mmTaskYeild - probably unnecessary since nothing was kicked off ?
|
|
|
|
......................................................................
|
|
|
|
|
|
MIDISEQ_DONE
|
|
|
|
|
|
Timers :
|
|
========
|
|
|
|
util.c!OneShotTimer has pointer to NPSEQ structure passed to it.
|
|
|
|
|
--> mmseq.c!TimerIntRoutine
|
|
|
|
|
|
|
|
util.c!MIDICallback
|
|
|
|
Conversion Issues
|
|
|
|
tasking
|
|
File format
|
|
Seems OK because :
|
|
|
|
1. mmio... is used to get at the chunks
|
|
2. The data is in big-endian format and macros are used which will
|
|
work for either format (GETMODWORD, GETMOTDWORD etc).
|
|
|
|
file access
|
|
|
|
OK - via MMIO
|
|
|
|
parameter sizes
|
|
api
|
|
build
|
|
globals
|
|
list.c - arrayOfLists
|
|
|
|
window messages
|
|
alignment / structure packing / structure overlays
|
|
|
|
|
|
|
|
Comments :
|
|
==========
|
|
|
|
1. This code is essentially uncommented. On the positive side the
|
|
structure is reasonably clean (though overcomplex and relying
|
|
on 'messages' (untyped calls) rather than subroutine calls which
|
|
means many bugs will get by the compiler into runtime code.
|
|
|
|
BUGS
|
|
====
|
|
|
|
Pointer to MMIOPROC in mcicmds.c should be pointer to pointer to.
|