home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / msdos / sndbords / proaudio / pas_sdk1 / pas / subs / mixers / dialog.c < prev    next >
Text File  |  1992-09-09  |  77KB  |  3,483 lines

  1. ;    /*\
  2. ;    |*| $Author:   BCRANE  $
  3. ;    |*| 
  4. ;    |*| $Date:   09 Sep 1992 13:44:30  $
  5. ;    |*| 
  6. ;    |*| $Header:   X:/sccs/mixers/dialog.c_v   1.11   09 Sep 1992 13:44:30   BCRANE  $
  7. ;    |*| 
  8. ;    |*| $Log:   X:/sccs/mixers/dialog.c_v  $
  9.  * 
  10.  *    Rev 1.11   09 Sep 1992 13:44:30   BCRANE
  11.  * changed MixerRect, RecordRect, and all mixer elements start and end x-coords
  12.  * up 1.
  13.  * 
  14.  *    Rev 1.10   04 Sep 1992 13:24:42   BCRANE
  15.  * changed bottom coordinate of MixerRect
  16.  * 
  17.  *    Rev 1.9   02 Sep 1992 10:03:04   BCRANE
  18.  * added SB volume control
  19.  * 
  20.  *    Rev 1.8   22 Jul 1992 08:21:14   BCRANE
  21.  * added #if USEMIXERGET to use either MixerGetSettings with 
  22.  * callback to "subsavecurrent" or "savecurrent".  Currently set
  23.  * to 1 to use MixerGetSettings.
  24.  * 
  25.  *    Rev 1.7   13 Jul 1992 11:57:02   BCRANE
  26.  * changed F3/SF3 to F5-F8/SF5-SF8
  27.  * now saves setting#.pas where # is 0-3
  28.  * modified F1 help to indicate this new feature 
  29.  * 
  30.  *    Rev 1.6   13 Jul 1992 09:41:56   DCODY
  31.  * GetMixerSettings now reports dead mixer settings
  32.  * 
  33.  *    Rev 1.5   10 Jul 1992 16:57:44   BCRANE
  34.  * changed INPUT to MIXER
  35.  * 
  36.  *    Rev 1.4   10 Jul 1992 16:38:52   BCRANE
  37.  * finalized (!) save and load defaults - handles input/output mixers
  38.  * last-one-active situation, as well as absolute vs. percent values
  39.  * 
  40.  *    Rev 1.3   09 Jul 1992 17:45:16   BCRANE
  41.  * added load and save current state and getdriverpath
  42.  * not fully complete
  43.  * 
  44.  *    Rev 1.2   01 Jul 1992 14:40:58   DCODY
  45.  * added OEM specific wording
  46. *    Rev 1.1   23 Jun 1992 16:44:32   DCODY
  47. * PAS2 update
  48. *    Rev 1.0   15 Jun 1992 09:41:16   BCRANE
  49. * Initial revision.
  50. ;    |*| 
  51. ;    |*| /*$Logfile:   X:/sccs/mixers/dialog.c_v  $
  52. ;    |*| 
  53. ;    |*| /*$Modtimes$
  54. ;    |*| 
  55. ;    \*/
  56.  
  57.     /*\
  58.     |*|---====< DIALOG.C  --  PAS User interface module >====----
  59.     |*|
  60.     |*| Pro Audio Spectrum Mixer User Interface program. This
  61.     |*| program provides mixer control from the command line.
  62.     |*|
  63.     |*| Media Vision, Inc. Copyright (c) 1991, All rights reserved
  64.     |*|
  65.     \*/
  66.  
  67.     /* minor revisions to allow integration with audiolnk (large model) */
  68.  
  69. #include <stdio.h>
  70. #include <stdlib.h>
  71. #include <string.h>
  72. #include <ctype.h>
  73. #include <bios.h>
  74.  
  75. #include <fcntl.h>
  76. #include <sys\types.h>
  77. #include <sys\stat.h>
  78. #include <io.h>
  79.  
  80. #include "dialog.h"
  81. #include <binary.h>
  82.  
  83. #ifndef OEM
  84. #define OEM 0
  85. #endif
  86.  
  87.     /*\
  88.     |*|----====< some prototypes >====----
  89.     \*/
  90.  
  91.         int     EqualizerLevels     ( );
  92.         int     ScrollObjectHandler ( );
  93.         int     SwitchObjectHandler ( );
  94.         int     VolumeLevels        ( );
  95.         int     VolumeButtons        ( );
  96.         int     EffectsButtons        ( );
  97.  
  98.  
  99.     /*\
  100.     |*|----====< global data >====----
  101.     \*/
  102.  
  103. #define TRUE    -1
  104. #define FALSE    0
  105.  
  106.     static char makemenull[]="";
  107.  
  108.     static char *screenlayout[] = {
  109.  
  110.         "┌───────────────────────────────┐",
  111. #if OEM
  112.         "│           Spectrum            │",
  113. #else
  114.         "│Media Vision Pro AudioSpectrum │",
  115. #endif
  116.         "├────────────┬──────────────────┼",
  117.         "│ FM         │││",
  118.         "│ Synthesizer│││",
  119.         "├────────────┼─┤                ├",
  120.         "│ External   │││",
  121.         "│ Jack       │││",
  122.         "├────────────┼─┤                ├",
  123.         "│ Internal   │││",
  124.         "│ Connector  │││",
  125.         "├────────────┼─┤                ├",
  126.         "│ Microphone │││",
  127.         "│ Jack       │││",
  128.         "├────────────┼─┤                ├",
  129.         "│ PC         │││",
  130.         "│ Speaker    │││",
  131.         "├────────────┼─┤                ├",
  132.         "│ SB Digital │││",
  133.         "│ Audio      │││",
  134.         "├────────────┼─┤                ├",
  135.         "│ Digital    │││",
  136.         "│ Audio      │││",
  137.         "└───────────────────────────────┘"
  138.     };
  139.  
  140.     static char *screen2[] = {
  141.  
  142.         "┌────────┬────────────────┬─┐",
  143.         "│Volume  │ Volume Control │ │",
  144.         "├──────┬─┼────────────────┼─┤",
  145.         "│Left  ││││",
  146.         "│Right ││││",
  147.         "├──────┼─┤                ├─┤",
  148.         "│Bass  ││││",
  149.         "├──────┼─┤                ├─┤",
  150.         "│Treble││││",
  151.         "└──────┴─┴────────────────┴─┘",
  152.         "┌───────────┬─┬───────────┬─┐",
  153.         "│ Loudness  ││ Enhanced  ││",
  154.         "└───────────┴─┴───────────┴─┘",
  155.  
  156.     };
  157.  
  158.     static char *screen3[] = {
  159.  
  160.         "─╔══════╗",
  161.         "║Play &║",
  162.         "║Record║",
  163.         "─╠══════╣",
  164.         "║Play &║",
  165.         "║Record║",
  166.         "─╠══════╣",
  167.         "║Play &║",
  168.         "║Record║",
  169.         "─╠══════╣",
  170.         "║Play &║",
  171.         "║Record║",
  172.         "─╠══════╣",
  173.         "║Play &║",
  174.         "║Record║",
  175.         "─╠══════╣",
  176.         "║Play &║",
  177.         "║Record║",
  178.         "─╠╦╦╦╦╦╦╣",
  179.         "╠╬╬╬╬╬╬╣",
  180.         "╠╬╬╬╬╬╬╣",
  181.         "─╚╩╩╩╩╩╩╝",
  182.  
  183.     };
  184.  
  185.     static char *screen4[] = {       /* Help2rect                         */
  186.  
  187.         "┌───────────────────────────┐",
  188.         "│ Type the F1 key for help. │",
  189.         "└───────────────────────────┘"
  190.     };
  191.  
  192.     static char EffectsString[] = "▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒";
  193.  
  194.     static char *effectsbkgn[] = {
  195.         EffectsString,
  196.         EffectsString,
  197.         EffectsString,
  198.         EffectsString,
  199.         EffectsString,
  200.       EffectsString,
  201.         EffectsString,
  202.         EffectsString,
  203.         EffectsString,
  204.         EffectsString,
  205.         EffectsString,
  206.         EffectsString,
  207.         EffectsString,
  208.         EffectsString,
  209.         EffectsString,
  210.         EffectsString,
  211.         EffectsString,
  212.       EffectsString,
  213.       EffectsString,
  214.       EffectsString,
  215.       EffectsString,
  216.         EffectsString
  217.     };
  218.  
  219.     static char *screen5[] = {       /* input mixer helps                 */
  220.  
  221.         "┌───────────────────────────┐",
  222.         "│    Channel Connections    │",
  223.         "├────────┬─────────┬────────┤",
  224.         "│ Left   ││ Left   │",
  225.         "│ Left   ││ Right  │",
  226.         "│ Right  ││ Left   │",
  227.         "│ Right  ││ Right  │",
  228.         "└────────┴─────────┴────────┘"
  229.     };
  230.  
  231.     static char *screen6[] = {       /* input mixer helps                 */
  232.         "┌───────────────────────────┐",
  233.         "│  Recording Monitor Level  │",
  234.         "├──────┬─┬────────────────┬─┤",
  235.         "│Left  ││││",
  236.         "│Right ││││",
  237.         "└──────┴─┴────────────────┴─┘"
  238.     };
  239.  
  240.     static char *screen7[] = {       /* realsound switch                    */
  241.  
  242.         "┌─────────────────────────┬─┐",
  243.         "│   Real Sound Support    ││",
  244.         "└─────────────────────────┴─┘"
  245.     };
  246.  
  247.     static char playmsgi1[] = "Play &";
  248.     static char playmsgi2[] = "Record";
  249.     static char playmsgo1[] = "Play  ";
  250.     static char playmsgo2[] = "Only  ";
  251.  
  252.     static char *helpscreen[] = {
  253.  
  254.         "╔═══════════════════════════════╗",
  255. #if OEM
  256.         "║           Spectrum            ║",
  257.         "║                               ║",
  258. #else
  259.         "║    Pro AudioSpectrum,  V1.21  ║",
  260.         "║      By Media Vision, Inc.    ║",
  261. #endif
  262.         "╟───────────────────────────────╢",
  263.         "║        Keyboard Control       ║",
  264.         "║       ──────────────────      ║",
  265.         "║HOME  to decrease left volume  ║",
  266.         "║     to decrease both volumes ║",
  267.         "║ END  to decrease right volume ║",
  268.         "║PGUP  to increase left volume  ║",
  269.         "║  3   to increase both volumes ║",
  270.         "║PGDN  to increase right volume ║",
  271.         "║ENTER to toggle a button on/off║",
  272.         "║ TAB  to move between fields   ║",
  273.         "║ F4   reset mixer to defaults  ║",
  274.         "║ F2   special effects          ║",
  275.         "║F5-F8 load mixer settings (use ║",
  276.         "║      Shifted-FKEY to save)    ║",
  277.         "║ ESC  will exit all dialogs    ║",
  278.         "║       ──────────────────      ║",
  279.         "║       Copyright (c) 1991      ║",
  280.         "║      All Rights Reserved.     ║",
  281.         "╚═══════════════════════════════╝"
  282.     };
  283.  
  284.  
  285.         static char twobar[]            = "·····∙∙∙∙∙";
  286.         static char channelconnect[]    = "";
  287.         static char channeldisconnect[] = "· · · · ·";
  288.  
  289.         extern char leftswitch;
  290.         extern int    leftvolume;
  291.         extern char ritswitch;
  292.         extern int    ritvolume;
  293.         extern int    VolumeNumber;
  294.         extern char VolumeSwitch;
  295.         extern int    Left2LeftState;
  296.         extern int    Left2RightState;
  297.         extern int    Right2LeftState;
  298.         extern int    Right2RightState;
  299.  
  300.     //    static char NumLockState;
  301.  
  302.         static VideoStruct OurWnd = { 0,0,0x18,0x4f, 0,0, 0x1f,0, 0,0xb800 };
  303.         VideoStruct *CurWnd = &OurWnd;
  304.         unsigned int VideoSegment = 0xb800;
  305.  
  306.         static rect Help1Rect  = { 1,23, 23,57 };
  307.         static rect Help2Rect  = {19,47, 21,77 };
  308.         static rect MixerRect  = { 0, 2, 23,36 };
  309.         static rect RecordRect = { 2,35, 23,45 };
  310.         static rect VolRect    = { 4,47, 16,77 };
  311.         static rect EffectsRect = { 1,20, 22,60 };
  312.         static rect Screen6Rect = { 2,25,  7,55 };
  313.         static rect Screen5Rect = { 9,25, 16,55 };
  314.         static rect Screen7Rect = {18,25, 20,55 };
  315.  
  316.     /* file handle for accessing MVPROAS                                */
  317.  
  318.         static int    mv;             /* mvsound dos driver                */
  319.  
  320.     /* objects                                                            */
  321.  
  322. #define OBJ_SCROLL        1
  323. #define OBJ_VOLUME        2
  324. #define OBJ_BUTTON        3
  325.  
  326.         typedef struct {
  327.             int  type;                // structure type
  328.             void *next;             // next structure pointer
  329.             void *back;             // prior structure pointer
  330.             int (*scr)();            // object processor
  331.             int (*swi)();            // object processor
  332.             rect namr;                // channel name rectangle
  333.             rect scrr;                // scroll bar rectangle
  334.             rect swir;                // record mixer select switch rectangle
  335.             char name[10];            // channel name "mic"/"ext", etc
  336.             int leftchannel;        // current left channel setting
  337.             int ritchannel;         // current right channel setting
  338.             int mixerselect;        // choosen mixer
  339.             int deadlchannel;        // current left channel setting
  340.             int deadrchannel;        // current right channel setting
  341.             int deadmixer;            // choosen mixer
  342.  
  343.         } Scroll, *SPtr;
  344.  
  345.         typedef struct {
  346.             int  type;                // structure type
  347.             void *next;             // next structure pointer
  348.             void *back;             // prior structure pointer
  349.             int (*scr)();            // object processor
  350.             rect namr;                // channel name rectangle
  351.             rect scrr;                // scroll bar rectangle
  352.             char name[20];            // channel name "mic"/"ext", etc
  353.             int channel;            // current channel setting
  354.         } Volume, *VPtr;
  355.  
  356.         typedef struct {
  357.             int  type;                // structure type
  358.             void *next;             // next structure pointer
  359.             void *back;             // prior structure pointer
  360.             int (*scr)();            // object processor
  361.             rect namr;                // channel name rectangle
  362.             rect scrr;                // scroll bar rectangle
  363.             char name[20];            // channel name "mic"/"ext", etc
  364.             int state;                // current button state
  365.         } Button, *BPtr;
  366.  
  367.         typedef struct {
  368.             void *head;
  369.             void *tail;
  370.             void *nextlist;
  371.         } ObjectList, *OLPtr;
  372.  
  373.     // Scroll bar objects
  374.  
  375.         static Scroll SynthScroll;           // structure prototypes
  376.         static Scroll ExtScroll;
  377.         static Scroll IntScroll;
  378.         static Scroll MicScroll;
  379.         static Scroll DigitalScroll;
  380.         static Scroll TBScroll;
  381.         static Scroll SpkrScroll;
  382.         static Scroll OutputMixerScroll;
  383.  
  384.         static Volume LeftVolumeLevel;
  385.         static Volume RitVolumeLevel;
  386.         static Volume BassVolume;
  387.         static Volume TrebVolume;
  388.  
  389.         static Button Loudness;
  390.         static Button Enhanced;
  391.         static Button Left2Left;
  392.         static Button Left2Right;
  393.         static Button Right2Left;
  394.         static Button Right2Right;
  395.         static Button RealSoundButton;
  396.  
  397.         static ObjectList MainList;
  398.         static ObjectList EffectsList;
  399.  
  400.         static ObjectList MainList = {
  401.             &SynthScroll,
  402.             &Enhanced,
  403.             &EffectsList
  404.         };
  405.  
  406.         static ObjectList EffectsList = {
  407.             &OutputMixerScroll,
  408.             &RealSoundButton,
  409.             0
  410.         };
  411.  
  412.         static OLPtr   CurrList = &MainList;
  413.  
  414.         static Scroll *CurrentObject = &SynthScroll;  // current object pointer
  415.  
  416.         static Scroll SynthScroll = {
  417.             OBJ_SCROLL,
  418.             &ExtScroll,
  419.             0,
  420.             &ScrollObjectHandler,
  421.             &SwitchObjectHandler,
  422.              3, 3, 4,14,
  423.              3,18, 4,33,
  424.              3,37, 4,42,
  425.             "FM ",
  426.             0,
  427.             0,
  428.             0,0,0,0
  429.         };
  430.  
  431.         static Scroll ExtScroll = {
  432.             OBJ_SCROLL,
  433.             &IntScroll,
  434.             &SynthScroll,
  435.             &ScrollObjectHandler,
  436.             &SwitchObjectHandler,
  437.              6, 3, 7,14,
  438.              6,18, 7,33,
  439.              6,37, 7,42,
  440.             "EXT ",
  441.             0,
  442.             0,
  443.             0,0,0,0
  444.         };
  445.  
  446.         static Scroll IntScroll = {
  447.             OBJ_SCROLL,
  448.             &MicScroll,
  449.             &ExtScroll,
  450.             &ScrollObjectHandler,
  451.             &SwitchObjectHandler,
  452.              9, 3,10,14,
  453.              9,18,10,33,
  454.              9,37,10,42,
  455.             "INT ",
  456.             0,
  457.             0,
  458.             0,0,0,0
  459.         };
  460.  
  461.         static Scroll MicScroll = {
  462.             OBJ_SCROLL,
  463.             &SpkrScroll,
  464.             &IntScroll,
  465.             &ScrollObjectHandler,
  466.             &SwitchObjectHandler,
  467.             12, 3,13,14,
  468.             12,18,13,33,
  469.             12,37,13,42,
  470.             "MIC ",
  471.             0,
  472.             0,
  473.             0,0,0,0
  474.         };
  475.  
  476.         static Scroll SpkrScroll = {
  477.             OBJ_SCROLL,
  478.             &TBScroll,
  479.             &MicScroll,
  480.             &ScrollObjectHandler,
  481.             &SwitchObjectHandler,
  482.             15, 3,16,14,
  483.             15,18,16,33,
  484.             15,37,16,42,
  485.             "SPEAKER ",
  486.             0,
  487.             0,
  488.             0,0,0,0
  489.         };
  490.  
  491.         static Scroll TBScroll = {
  492.             OBJ_SCROLL,
  493.             &DigitalScroll,
  494.             &SpkrScroll,
  495.             &ScrollObjectHandler,
  496.             &SwitchObjectHandler,
  497.             18, 3,19,14,
  498.             18,18,19,33,
  499.             18,37,19,42,
  500.             "SB      ",
  501.             0,
  502.             0,
  503.             0,0,0,0
  504.         };
  505.  
  506.         static Scroll DigitalScroll = {
  507.             OBJ_SCROLL,
  508.             &LeftVolumeLevel,
  509.             &TBScroll,
  510.             &ScrollObjectHandler,
  511.             0,
  512.             21, 3,22,14,
  513.             21,18,22,33,
  514.             21,37,22,42,
  515.             "PCM ",
  516.             0,
  517.             0,
  518.             0,0,0,0
  519.         };
  520.  
  521.         static Volume LeftVolumeLevel = {
  522.             OBJ_VOLUME,
  523.             &BassVolume,
  524.             &DigitalScroll,
  525.             &VolumeLevels,
  526.              7,48, 7,53,
  527.              7,57, 7,72,
  528.             "LEVEL ",
  529.             0
  530.         };
  531.  
  532.             // this object is owned byte LeftVolumeLevel
  533.  
  534.                 static Volume RitVolumeLevel  = {
  535.                     OBJ_VOLUME,
  536.                     0,
  537.                     0,
  538.                     &VolumeLevels,
  539.                      8,48, 8,53,
  540.                      8,57, 8,72,
  541.                     "LEVEL ",
  542.                     0
  543.                 };
  544.  
  545.         static Volume BassVolume = {
  546.             OBJ_VOLUME,
  547.             &TrebVolume,
  548.             &LeftVolumeLevel,
  549.             &EqualizerLevels,
  550.             10,48,10,53,
  551.             10,57,10,72,
  552.             "BASS ",
  553.             0
  554.         };
  555.  
  556.         static Volume TrebVolume = {
  557.             OBJ_VOLUME,
  558.             &Loudness,
  559.             &BassVolume,
  560.             &EqualizerLevels,
  561.             12,48,12,53,
  562.             12,57,12,72,
  563.             "TREBLE ",
  564.             0
  565.         };
  566.  
  567.         static Button Loudness    = {
  568.             OBJ_BUTTON,
  569.             &Enhanced,
  570.             &TrebVolume,
  571.             &VolumeButtons,
  572.             15,48,15,58,
  573.             15,60,15,60,
  574.             "LOUDNESS ",
  575.             0
  576.         };
  577.  
  578.         static Button Enhanced = {
  579.             OBJ_BUTTON,
  580.             0,
  581.             &Loudness,
  582.             &VolumeButtons,
  583.             15,63,15,72,
  584.             15,74,15,74,
  585.             "ENHANCED ",
  586.             0
  587.         };
  588.  
  589.  
  590.     /*\
  591.     |*| effects dialog box structures
  592.     \*/
  593.  
  594.         static Scroll OutputMixerScroll = {
  595.             OBJ_SCROLL,
  596.             &Left2Left,
  597.             0,
  598.             &ScrollObjectHandler,
  599.             0,
  600.             5,26,6,31,
  601.             5,35,6,50,
  602.              0, 0, 0, 0,
  603.             "MIXER ",
  604.             0,
  605.             0,
  606.             0,0,0,0
  607.         };
  608.  
  609.         static Button Left2Left = {
  610.             OBJ_BUTTON,
  611.             &Left2Right,
  612.             &OutputMixerScroll,
  613.             &EffectsButtons,
  614.             12,26,12,33,
  615.             12,35,12,43,
  616.             "Left to Left ",
  617.             0
  618.         };
  619.  
  620.         static Button Left2Right = {
  621.             OBJ_BUTTON,
  622.             &Right2Left,
  623.             &Left2Left,
  624.             &EffectsButtons,
  625.             13,26,13,33,
  626.             13,35,13,43,
  627.             "Left to Right ",
  628.             0
  629.         };
  630.  
  631.         static Button Right2Left = {
  632.             OBJ_BUTTON,
  633.             &Right2Right,
  634.             &Left2Right,
  635.             &EffectsButtons,
  636.             14,26,14,33,
  637.             14,35,14,43,
  638.             "Right to Left ",
  639.             0
  640.         };
  641.  
  642.         static Button Right2Right = {
  643.             OBJ_BUTTON,
  644.             &RealSoundButton,
  645.             &Right2Left,
  646.             &EffectsButtons,
  647.             15,26,15,33,
  648.             15,35,15,43,
  649.             "Right to Right ",
  650.             0
  651.         };
  652.  
  653.         static Button RealSoundButton = {
  654.             OBJ_BUTTON,
  655.             0,
  656.             &Right2Left,
  657.             &EffectsButtons,
  658.             19,26,19,49,
  659.             19,52,19,52,
  660.             " ",
  661.             0
  662.         };
  663.  
  664.         static int OrigRow;            // original row position
  665.         static int OrigCol;            // original column position
  666.  
  667.         static char CommandString[80]; // text buffer that holds commands to MVPROAS
  668.         static char MVResponse[80];    // text buffer that holds the MVPROAS responses
  669.  
  670.         static int screenbuffer[2048]; // screen backup buffer
  671.  
  672. #define MAIN_DLG        0x0001    // main screen dialog boxes
  673. #define EFFECTS_DLG     0x0002    // recording effects dialog box
  674.  
  675.         static int DialogBox=MAIN_DLG; // bit field indicating witch dialog box is up
  676.  
  677.  
  678.         typedef struct {
  679.  
  680.             int Filler;         // all other screen area
  681.  
  682.             int BkGn_AND;       // background AND mask
  683.             int BkGn_XOR;        // background XOR mask
  684.  
  685.             int Shdw_AND;       // shadow AND mask
  686.             int Shdw_XOR;        // shadow XOR mask
  687.  
  688.             int TmpHi_AND;      // temp High AND mask
  689.             int TmpHi_XOR;        // temp high XOR mask
  690.  
  691.             int TmpLo_AND;      // temp low  AND mask
  692.             int TmpLo_XOR;        // temp low  XOR mask
  693.  
  694.             int ScrTmpHi_AND;    // temp High AND mask
  695.             int ScrTmpHi_XOR;    // temp high XOR mask
  696.  
  697.             int ScrTmpLo_AND;    // temp low  AND mask
  698.             int ScrTmpLo_XOR;    // temp low  XOR mask
  699.  
  700.             int ButLo_AND;      // button low AND mask
  701.             int ButLo_XOR;        // button low XOR mask
  702.  
  703.             int ButHi_AND;      // button high AND mask
  704.             int ButHi_XOR;        // button high XOR mask
  705.  
  706.         } scheme, *SCMPtr;
  707.  
  708.         static scheme MonoScheme = {   // attribute control for MONO screens
  709.  
  710.             0x0e,                // full bright
  711.  
  712.             0x00,                // background AND mask
  713.             0x07,                // background XOR mask
  714.  
  715.             0x77,                // shadow AND mask
  716.             0x00,                // shadow XOR mask
  717.  
  718.             0x77,                // temp High AND mask
  719.             0x08,                // temp high XOR mask
  720.  
  721.             0x77,                // temp low  AND mask
  722.             0x00,                // temp low  XOR mask
  723.  
  724.             0x77,                // scroll temp High AND mask
  725.             0x08,                // scroll temp high XOR mask
  726.  
  727.             0x77,                // scroll temp low    AND mask
  728.             0x00,                // scroll temp low    XOR mask
  729.  
  730.             0x00,                // button low AND mask
  731.             0x1f,                // button low XOR mask
  732.  
  733.             0x08,                // button high AND mask
  734.             0x70,                // button high XOR mask
  735.  
  736.         };
  737.  
  738.         static scheme ColorScheme = {  // attribute control for COLOR screens
  739.  
  740.             0x09,                // bright blue background
  741.  
  742.             0x00,               // background AND mask
  743.             0x30,                // background XOR mask
  744.  
  745.             0x00,                // shadow AND mask
  746.             0x00,                // shadow XOR mask
  747.  
  748.             0x70,                // temp High AND mask
  749.             0x0e,                // temp high XOR mask
  750.  
  751.             0x70,                // temp low  AND mask
  752.             0x00,                // temp low  XOR mask
  753.  
  754.             0x70,                // scroll temp High AND mask
  755.             0x0e,                // scroll temp high XOR mask
  756.  
  757.             0x70,                // scroll temp low    AND mask
  758.             0x0a,                // scroll temp low    XOR mask
  759.  
  760.             0x00,                // button low AND mask
  761.             0x37,                // button low XOR mask
  762.  
  763.             0x00,                // button high AND mask
  764.             0x3f,                // button high XOR mask
  765.  
  766.         };
  767.  
  768.         static scheme HelpsColorScheme = {    // attribute control for COLOR screens
  769.  
  770.             0x09,                // bright blue
  771.  
  772.             0x00,               // background AND mask
  773.             0x20,                // background XOR mask
  774.  
  775.             0x00,                // shadow AND mask
  776.             0x00,                // shadow XOR mask
  777.  
  778.             0x77,                // temp High AND mask
  779.             0x08,                // temp high XOR mask
  780.  
  781.             0x77,                // temp low  AND mask
  782.             0x00,                // temp low  XOR mask
  783.  
  784.             0x77,                // scroll temp High AND mask
  785.             0x08,                // scroll temp high XOR mask
  786.  
  787.             0x77,                // scroll temp low    AND mask
  788.             0x00,                // scroll temp low    XOR mask
  789.  
  790.             0x08,                // button low AND mask
  791.             0x17,                // button low XOR mask
  792.  
  793.             0x08,                // button high AND mask
  794.             0x70,                // button high XOR mask
  795.  
  796.         };
  797.  
  798.         static SCMPtr  Colors = &ColorScheme;  // default to color adapber scheme
  799.  
  800.  
  801.     /*\
  802.     |*|----====< more prototypes >====----
  803.     \*/
  804.  
  805.         int            MixerDialogInit       ( );
  806.         int            MixerDialogHalt       ( );
  807.         static int       BroadcastMsg        ( int );
  808.         static int       BroadcastToLlist    ( int, ObjectList * );
  809.         static void    DrawScreen           ( rect *, char *([]) );
  810.         static int       GetEvent            ( EPtr );
  811.         static void    MatchObj            ( EPtr );
  812.         static void    PaintScreen           ( int );
  813.         static int       PtInRect            ( point *,rect * );
  814.         static int       SendMixer           ( char *, int, int, SPtr, int, int );
  815.         static int       SendVolume           ( char *, int, VPtr, int, int );
  816.  
  817.         static int       SystemKey           ( EPtr );
  818.         static int       SystemInit           ( );
  819.         static void    SystemShutDown       ( );
  820.  
  821.         extern void    BackupVideo           ( rect *, char far *, int, int );
  822.         extern void    RestoreVideo        ( rect *, char far *, int, int );
  823.         long extern    _videogetcurs       ( );  /* ***** was near kdn */
  824.  
  825.  
  826.     /*\
  827.     |*|----------------==============================----------------
  828.     |*|----------------====< Start of Execution >====----------------
  829.     |*|----------------==============================----------------
  830.     \*/
  831.  
  832.         static int exitcode = FALSE;    // our exit flag
  833.         static int CallersFillChar;     // Callers screen fill char (0) for none
  834.  
  835. MixerDialogBox(fill)
  836.     int fill;
  837. {
  838. Event ev;
  839. char *s;
  840.  
  841.     /* make the fill character available to the masses                    */
  842.  
  843.         s = EffectsString;
  844.         if ((CallersFillChar = fill) != 0)
  845.             while (*s) *s++ = fill;
  846.  
  847.     /* initialize the hardware.                                         */
  848.  
  849.         SystemInit();
  850.  
  851.     /* go forever                                                        */
  852.  
  853.         while (!exitcode) {
  854.  
  855.             /* if a keyboard/mouse action, the pass to handlers         */
  856.  
  857.                 if (GetEvent (&ev)) {
  858.                     if (!SystemKey(&ev)) {
  859.                         if (CurrentObject)
  860.                             (*CurrentObject->scr)(OPEVENT,CurrentObject,&ev);
  861.                     }
  862.                 }
  863.  
  864.             /* if no action, just move the cross hairs                    */
  865.  
  866.                 else
  867.                     UpdateTotalVolume();        /* changes via keyboard */
  868.                     MatchObj ( &ev );           /* find a new object    */
  869.         }
  870.  
  871.     /* exit back to caller                                                */
  872.  
  873.         SystemShutDown();
  874.  
  875.     /* reset the exit code so we can process again...                    */
  876.  
  877.         exitcode=FALSE;
  878.  
  879. }
  880.  
  881.  
  882.     /*\
  883.     |*|----====< MixerGetSettings() >====----
  884.     |*|
  885.     |*| call the user back with the appropriate data
  886.     |*|
  887.     |*| Entry Conditions:
  888.     |*|     None
  889.     |*|
  890.     |*| Exit Conditions:
  891.     |*|     0 = okay, !0 = failure
  892.     |*|
  893.     \*/
  894.  
  895. MixerGetSettings(c)
  896.     void (*c)();
  897. {
  898. SPtr o;
  899. OLPtr l;
  900.  
  901.     /* start at the top & send to all objects, even the caller            */
  902.  
  903.         l = &MainList;
  904.  
  905.         while (l) {
  906.  
  907.             o = l->head;
  908.  
  909.             while (o) {
  910.  
  911.                 // send the message to the next object
  912.  
  913.                     (*o->scr)(OPENINIT,o);
  914.  
  915.                     // if the dead mixer, then send this string too!
  916.  
  917.                     if (o->type == OBJ_SCROLL) {
  918.                         SendMixer ("SET ",o->deadmixer,1,o,BI_SETTO,o->deadlchannel);
  919.                         (*c)(&CommandString);
  920.                         SendMixer ("SET ",o->deadmixer,2,o,BI_SETTO,o->deadrchannel);
  921.                         (*c)(&CommandString);
  922.                     }
  923.                     (*o->scr)(SENDIT,o,c);
  924.  
  925.                 // go to next object
  926.  
  927.                     o = o->next;
  928.             }
  929.  
  930.             l = l->nextlist;
  931.         }
  932. }
  933.  
  934.  
  935.     /*\
  936.     |*|----====< MixerDialogInit() >====----
  937.     |*|
  938.     |*| Perform any startup needed
  939.     |*|
  940.     |*| Entry Conditions:
  941.     |*|     None
  942.     |*|
  943.     |*| Exit Conditions:
  944.     |*|     0 = okay, !0 = failure
  945.     |*|
  946.     \*/
  947. int MixerDialogInit()
  948. {
  949.  
  950.     // open the device
  951.  
  952.         //if ((mv = open ("MVPROAS",O_RDWR, S_IREAD | S_IWRITE)) == -1) {
  953.  
  954.         if ((mv = open ("MVPROAS",O_RDWR )) == -1) {
  955.           //_ttyout ("\acannot open the MVPROAS device!\n",0);
  956.             return(1);
  957.         }
  958.  
  959.     // make an IBM PC right arrow appear in some text
  960.  
  961.         helpscreen[10][3]= 26;    /* used to be:        hackaline[3] = 26; */
  962.  
  963.     // everything is fine...
  964.  
  965.         return (0);
  966.  
  967. }
  968.  
  969.  
  970.     /*\
  971.     |*|----====< MixerDialogHalt() >====----
  972.     |*|
  973.     |*| Perform any other shutdown
  974.     |*|
  975.     |*| Entry Conditions:
  976.     |*|     None
  977.     |*|
  978.     |*| Exit Conditions:
  979.     |*|     0 = okay, !0 = failure
  980.     |*|
  981.     \*/
  982. int  MixerDialogHalt()
  983. {
  984.  
  985.     // close down the file handle
  986.  
  987.         close (mv);
  988.  
  989.     // everything is fine...
  990.  
  991.         return (0);
  992.  
  993. }
  994.  
  995.  
  996.     /*\
  997.     |*|--------------------=======================--------------------
  998.     |*|--------------------====< Subroutines >====--------------------
  999.     |*|--------------------=======================--------------------
  1000.     \*/
  1001.  
  1002.  
  1003.     /*\
  1004.     |*|----====< void BroadcastMsg ( int ) >====----
  1005.     |*|
  1006.     |*|    This routine broadcasts a message to all objects.
  1007.     |*|
  1008.     \*/
  1009. static int BroadcastMsg (msg)
  1010.     int msg;
  1011. {
  1012. SPtr o;
  1013.  
  1014.     /* send to all linked lists of objects                                */
  1015.  
  1016.         BroadcastToList (msg,&MainList);
  1017.         BroadcastToList (msg,&EffectsList);
  1018. }
  1019.  
  1020.  
  1021.     /*\
  1022.     |*|----====< void BroadcastToList ( int, ObjectList * ) >====----
  1023.     |*|
  1024.     |*|    This routine broadcasts a message to all objects.
  1025.     |*|
  1026.     \*/
  1027. static int BroadcastToList (msg,l)
  1028.     int msg;
  1029.      ObjectList *l;
  1030. {
  1031. SPtr o;
  1032.  
  1033.     /* start at the top & send to all objects, even the caller            */
  1034.  
  1035.         o = l->head;
  1036.  
  1037.         while (o) {
  1038.  
  1039.             /* send the message to the next object                        */
  1040.  
  1041.                 (*o->scr)(msg,o);
  1042.  
  1043.             /* go to next object                                        */
  1044.  
  1045.                 o = o->next;
  1046.         }
  1047. }
  1048.  
  1049.  
  1050. #if 0
  1051.     /*\
  1052.     |*|----====< void DupTheEvent ( EPtr, EPtr ); >====----
  1053.     |*|
  1054.     |*|    Duplicate our event record.
  1055.     |*|
  1056.     \*/
  1057.         void    DupTheEvent         ( EPtr, EPtr );
  1058. static void DupTheEvent(src,dst)
  1059.     EPtr src,dst;
  1060. {
  1061.  
  1062.     /* duplicate the event using an intrinsic function                    */
  1063.  
  1064.         memcpy
  1065.           (
  1066.             (char *) dst,
  1067.             (char *) src,
  1068.             sizeof (Event)
  1069.           );
  1070. }
  1071. #endif
  1072.  
  1073.  
  1074.     /*\
  1075.     |*|----====< int EffectsButtons() >====----
  1076.     |*|
  1077.     |*| Cross Channel object control
  1078.     |*|
  1079.     |*| Entry Conditions:
  1080.     |*|     None
  1081.     |*|
  1082.     |*| Exit Conditions:
  1083.     |*|     None
  1084.     |*|
  1085.     \*/
  1086. static int EffectsButtons(msg,o,ptr)
  1087.     int msg;
  1088.     BPtr o;
  1089.     void *ptr;
  1090. {
  1091. void **pptr;
  1092. rect r;
  1093. int l,ri,i;
  1094. char c1,c2;
  1095.  
  1096.     // get a pointer to the stack
  1097.  
  1098.         pptr = &ptr;
  1099.  
  1100.     // process the message
  1101.  
  1102.         switch (msg) {
  1103.  
  1104.             case OPEVENT:
  1105.  
  1106.                 switch (((EPtr)pptr[0])->buttons) {
  1107.  
  1108.                     case ENTER:
  1109.  
  1110.                         // ENTER here can toggle the buttons
  1111.  
  1112.                        o->state = ((o->state) ? FALSE : TRUE );
  1113.  
  1114.                         (*o->scr) (DRAWIT,o);
  1115.  
  1116.                         if (o == &RealSoundButton)
  1117.                             SendOnOff ("SET ","REALSOUND ",o);
  1118.                         else
  1119.                             SendOnOff ("SET ","CROSS ",o);
  1120.  
  1121.                         break;
  1122.  
  1123.                     default:
  1124.                         break;
  1125.                 }
  1126.  
  1127.                 break;
  1128.  
  1129.             case SENDIT:
  1130.  
  1131.                 if (o == &RealSoundButton)
  1132.                     SendOnOff ("SET ","REALSOUND ",o);
  1133.                 else
  1134.                     SendOnOff ("SET ","CROSS ",o);
  1135.  
  1136.                 (*(void(*)())ptr)(&CommandString);
  1137.  
  1138.                 break;
  1139.  
  1140.             case FOCUS_GIVEN:
  1141.  
  1142.                 // highlight the entire field
  1143.  
  1144.                     if (o == &RealSoundButton) {
  1145.  
  1146.                       //r.row2 = o->namr.row2;
  1147.                       //r.row1 = o->namr.row1;
  1148.                       //r.col2 = r.col1 = o->namr.col2+2;
  1149.                       //_videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &r       );
  1150.                         _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &o->namr );
  1151.                         _videoattr ( Colors->ScrTmpHi_AND, Colors->ScrTmpHi_XOR, &o->scrr );
  1152.  
  1153.                     }
  1154.                     else {
  1155.  
  1156.                         r.row1 = o->scrr.row1;
  1157.                         r.row2 = o->scrr.row2;
  1158.                         r.col2 = (r.col1 = o->scrr.col2+2) + 7;
  1159.  
  1160.                         _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &o->namr );
  1161.                         _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &r );
  1162.                         _videoattr ( Colors->ScrTmpHi_AND, Colors->ScrTmpHi_XOR, &o->scrr );
  1163.                     }
  1164.  
  1165.                     break;
  1166.  
  1167.             case FOCUS_TAKEN:
  1168.  
  1169.                 // remove the highlight from the entire field
  1170.  
  1171.                     if (o == &RealSoundButton) {
  1172.  
  1173.                       //r.row1 = o->namr.row1;
  1174.                       //r.row2 = o->namr.row2;
  1175.                       //r.col2 = r.col1 = o->namr.col2+2;
  1176.                       //_videoattr ( Colors->TmpLo_AND,    Colors->TmpLo_XOR,     &r       );
  1177.                         _videoattr ( Colors->TmpLo_AND,    Colors->TmpLo_XOR,     &o->namr );
  1178.                         _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &o->scrr );
  1179.  
  1180.                     }
  1181.                     else {
  1182.                         r.row1 = o->scrr.row1;
  1183.                         r.row2 = o->scrr.row2;
  1184.                         r.col2 = (r.col1 = o->scrr.col2+2) + 7;
  1185.  
  1186.                         _videoattr ( Colors->TmpLo_AND,    Colors->TmpLo_XOR,     &o->namr );
  1187.                         _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &o->scrr );
  1188.                         _videoattr ( Colors->TmpLo_AND,    Colors->TmpLo_XOR,     &r );
  1189.                     }
  1190.  
  1191.                     break;
  1192.  
  1193.             case DRAWIT:
  1194.  
  1195.                 // move the cursor to the slide bar area
  1196.  
  1197.                     if (o == &RealSoundButton) {
  1198.  
  1199.                         _videosetcurs ( o->scrr.row1, o->scrr.col1 );
  1200.  
  1201.                         if (o->state)
  1202.                             _zipout   ( "X" );
  1203.                         else
  1204.                             _zipout   ( "∙" );
  1205.                     }
  1206.  
  1207.                     else {
  1208.  
  1209.                         _videosetcurs ( o->scrr.row1, o->scrr.col1 );
  1210.  
  1211.                         if (o->state)
  1212.                             _zipout ( channelconnect, 0);
  1213.                         else
  1214.                             _zipout ( channeldisconnect, 0);
  1215.                     }
  1216.  
  1217.                 break;
  1218.  
  1219.             case OPENINIT:
  1220.  
  1221.                 // get the output mixer current state
  1222.  
  1223.                     if (o == &RealSoundButton) {
  1224.  
  1225.                         SendOnOff ("GET ","REALSOUND ",o);
  1226.  
  1227.                         o->state = (MVResponse[0] == '+') ? TRUE : FALSE;
  1228.  
  1229.                     }
  1230.                     else {
  1231.  
  1232.                         SendOnOff ("GET ","CROSS ",o);
  1233.  
  1234.                         DecodeCrossChannel (MVResponse);
  1235.  
  1236.                         if (o == &Left2Left)
  1237.                             o->state = Left2LeftState;
  1238.  
  1239.                         if (o == &Left2Right)
  1240.                             o->state = Left2RightState;
  1241.  
  1242.                         if (o == &Right2Left)
  1243.                             o->state = Right2LeftState;
  1244.  
  1245.                         if (o == &Right2Right)
  1246.                             o->state = Right2RightState;
  1247.                     }
  1248.  
  1249.                     break;
  1250.  
  1251.             case CLEARIT:
  1252.             default:
  1253.                 break;
  1254.         }
  1255. }
  1256.  
  1257.  
  1258.  
  1259.     /*\
  1260.     |*|----====< int EqualizerLevels() >====----
  1261.     |*|
  1262.     |*| BASS/TREBLE slide bar object control
  1263.     |*|
  1264.     |*| Entry Conditions:
  1265.     |*|     None
  1266.     |*|
  1267.     |*| Exit Conditions:
  1268.     |*|     None
  1269.     |*|
  1270.     \*/
  1271. static int EqualizerLevels(msg,o,ptr)
  1272.     int msg;
  1273.     VPtr o;
  1274.     void *ptr;
  1275. {
  1276. void **pptr;
  1277. rect r;
  1278. int l,ri,i;
  1279. char c1,c2;
  1280.  
  1281.     // get a pointer to the stack
  1282.  
  1283.         pptr = &ptr;
  1284.  
  1285.     // process the message
  1286.  
  1287.         switch (msg) {
  1288.  
  1289.             case OPEVENT:
  1290.  
  1291.                 switch (((EPtr)pptr[0])->buttons) {
  1292.  
  1293.                     case ENDKEY:
  1294.                     case HOMEKEY:
  1295.                     case LFARROW:
  1296.  
  1297.                         if (o->channel > 0)
  1298.                             o->channel -= 4;
  1299.  
  1300.                         SendVolume
  1301.                           (
  1302.                             "SET ",
  1303.                             0,
  1304.                             o,
  1305.                             BI_SETTO,
  1306.                             o->channel
  1307.                           );
  1308.  
  1309.                         (*o->scr) (DRAWIT,o);
  1310.  
  1311.                         break;
  1312.  
  1313.                     case PGDNKEY:
  1314.                     case PGUPKEY:
  1315.                     case RIARROW:
  1316.  
  1317.                         if (o->channel < 100)
  1318.                             o->channel += 4;
  1319.  
  1320.                         SendVolume
  1321.                           (
  1322.                             "SET ",
  1323.                             0,
  1324.                             o,
  1325.                             BI_SETTO,
  1326.                             o->channel
  1327.                           );
  1328.  
  1329.                         (*o->scr) (DRAWIT,o);
  1330.  
  1331.                         break;
  1332.  
  1333.                     case ENTER:
  1334.  
  1335.                         // ENTER here can toggle the buttons
  1336.  
  1337.                         if (o == &BassVolume)
  1338.                             (*Loudness.scr)(msg,&Loudness,ptr);
  1339.  
  1340.                         if (o == &TrebVolume)
  1341.                             (*Enhanced.scr)(msg,&Enhanced,ptr);
  1342.                         break;
  1343.  
  1344.                     default:
  1345.                         break;
  1346.                 }
  1347.  
  1348.                 break;
  1349.  
  1350.             case SENDIT:
  1351.  
  1352.                 SendVolume
  1353.                   (
  1354.                     "SET ",
  1355.                     0,
  1356.                     o,
  1357.                     BI_SETTO,
  1358.                     o->channel
  1359.                   );
  1360.                 (*(void(*)())ptr)(&CommandString);
  1361.  
  1362.                 break;
  1363.  
  1364.             case FOCUS_GIVEN:
  1365.  
  1366.                 // highlight the entire field
  1367.  
  1368.                     r.row1 = o->namr.row1;
  1369.                     r.row2 = o->namr.row2;
  1370.                     r.col2 = r.col1 = o->namr.col2+2;
  1371.                     _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &o->namr );
  1372.                     _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &r       );
  1373.  
  1374.                     r.row1 = o->scrr.row1;
  1375.                     r.row2 = o->scrr.row2;
  1376.                     r.col2 = r.col1 = o->scrr.col2+2;
  1377.                     _videoattr ( Colors->ScrTmpHi_AND, Colors->ScrTmpHi_XOR, &o->scrr );
  1378.                     _videoattr ( Colors->ScrTmpHi_AND, Colors->ScrTmpHi_XOR, &r       );
  1379.  
  1380.                     break;
  1381.  
  1382.             case FOCUS_TAKEN:
  1383.  
  1384.                 // highlight the entire field
  1385.  
  1386.                     r.row1 = o->namr.row1;
  1387.                     r.row2 = o->namr.row2;
  1388.                     r.col2 = r.col1 = o->namr.col2+2;
  1389.                     _videoattr ( Colors->TmpLo_AND,    Colors->TmpLo_XOR,    &o->namr );
  1390.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &r       );
  1391.  
  1392.                     r.row1 = o->scrr.row1;
  1393.                     r.row2 = o->scrr.row2;
  1394.                     r.col2 = r.col1 = o->scrr.col2+2;
  1395.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &o->scrr );
  1396.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &r       );
  1397.  
  1398.                     break;
  1399.  
  1400.             case DRAWIT:
  1401.  
  1402.                 // move the cursor to the slide bar area
  1403.  
  1404.                     _videosetcurs ( o->scrr.row1, o->scrr.col1 );
  1405.                     _zipout       ( twobar, 0);
  1406.  
  1407.                     l = (o->channel * 31) / 100;
  1408.                     _videosetcurs ( o->scrr.row1, o->scrr.col1+(l>>1) );
  1409.                     _zipout (((l & 1) ? "▐" : "▌"), 0);
  1410.  
  1411.                     break;
  1412.  
  1413.             case OPENINIT:
  1414.  
  1415.                 // get the output mixer current state
  1416.  
  1417.                     SendVolume ("GET ",0,o,0,0);
  1418.                     DecodeVolumeNumber (MVResponse);
  1419.                     o->channel = VolumeNumber;
  1420.  
  1421.                     break;
  1422.  
  1423.             case CLEARIT:
  1424.             default:
  1425.                 break;
  1426.         }
  1427. }
  1428.  
  1429.  
  1430.     /*\
  1431.     |*|----====< int GetEvent ( EPtr ) >====----
  1432.     |*|
  1433.     |*|   This routine fetches the next event from the mouse driver
  1434.     |*|
  1435.     |*| This routine is used by permission from Douglas S. Cody
  1436.     |*| Douglas S. Cody, Copyright 1989,1990 (c), All Rights Reserved.
  1437.     |*|
  1438.     \*/
  1439. static int GetEvent (e)
  1440.     EPtr e;
  1441. {
  1442.  
  1443.     // if there is a key waiting...
  1444.  
  1445.         if (_bios_keybrd( _KEYBRD_READY )) {
  1446.  
  1447.             // ...return it
  1448.  
  1449.             e->type = EV_KEYB;
  1450.             return (e->buttons =  _bios_keybrd ( _KEYBRD_READ ));
  1451.         }
  1452.  
  1453.     // ...else return 0
  1454.  
  1455.         return( 0 );
  1456.  
  1457. }
  1458.  
  1459.  
  1460.     /*\
  1461.     |*|----====< void MatchObj(EPtr) >====----
  1462.     |*|
  1463.     |*|    This routine matches the mouse pointer to a screen object
  1464.     |*|
  1465.     \*/
  1466. static void MatchObj(e)
  1467.     EPtr e;
  1468. {
  1469. SPtr o;
  1470.  
  1471. #if 0
  1472.     // if this is a mouse type, match it to the list
  1473.  
  1474.         if (e->type == EV_MOUS) {
  1475.  
  1476.             // if point is still within the current object, just return
  1477.  
  1478.                 if (PtInRect ((point *)&e->vpos,&CurrentObject->scrr) ||
  1479.                     PtInRect ((point *)&e->vpos,&CurrentObject->scrr))
  1480.                         return;
  1481.  
  1482.             // we must take the focus away so we don't send bogus mouse events
  1483.  
  1484.                 (*CurrentObject->scr) (FOCUS_TAKEN,CurrentObject);
  1485.  
  1486.             // the mouse is pointing to something else. try to find it
  1487.  
  1488.                 o = CurrList->head;
  1489.                 while (o) {
  1490.  
  1491.                     if (PtInRect ((point *)&e->vpos,&o->scrr) ||
  1492.                         PtInRect ((point *)&e->vpos,&o->swir)) {
  1493.  
  1494.                         // focus given if the object takes mouse events
  1495.  
  1496.                         CurrentObject = o;
  1497.                         (*o->scr) (FOCUS_GIVEN,o);
  1498.                         break;
  1499.  
  1500.                     }
  1501.                     o = o->next;
  1502.                 }
  1503.         }
  1504. #endif
  1505. }
  1506.  
  1507.  
  1508.     /*\
  1509.     |*|----====< void DrawScreen (rect *, char *argv[]) >====----
  1510.     |*|
  1511.     |*| Perform the screen draw for this screen
  1512.     |*|
  1513.     |*| Entry Conditions:
  1514.     |*|     2 parms
  1515.     |*|
  1516.     |*| Exit Conditions:
  1517.     |*|     None
  1518.     |*|
  1519.     \*/
  1520. static void DrawScreen (r,txt)
  1521.     rect *r;
  1522.     char *txt[];
  1523. {
  1524. rect wr;
  1525. int x;
  1526.  
  1527.     // inner box color
  1528.  
  1529.         wr.row1 = r->row1;
  1530.         wr.row2 = r->row2;
  1531.         wr.col1 = r->col1;
  1532.         wr.col2 = r->col2-2;
  1533.         _videoattr (Colors->BkGn_AND,Colors->BkGn_XOR,&wr);
  1534.  
  1535.     // vertical right side shadow
  1536.  
  1537.         wr.row1 = r->row1+1;
  1538.         wr.row2 = r->row2+1;
  1539.         wr.col1 = r->col2-1;
  1540.         wr.col2 = r->col2+0;
  1541.         _videoattr (Colors->Shdw_AND,Colors->Shdw_XOR,&wr);
  1542.  
  1543.     // horizontal bottom shadow
  1544.  
  1545.         wr.row1 = wr.row2;
  1546.         wr.col1 = r->col1+2;
  1547.         _videoattr (Colors->Shdw_AND,Colors->Shdw_XOR,&wr);
  1548.  
  1549.     // actual text
  1550.  
  1551.         if (txt) {
  1552.             for (x=r->row1;x<=r->row2;x++) {
  1553.                 _videosetcurs (x,r->col1);
  1554.                 _zipout (txt[x-r->row1],0);
  1555.             }
  1556.         }
  1557.  
  1558.     // change some attributes on the color screen
  1559.  
  1560.         if (VideoSegment == 0xb800)
  1561.             ChangeAttributes (r->row1, r->col1, r->row2, r->col2-2);
  1562. }
  1563.  
  1564.  
  1565.     /*\
  1566.     |*|----====< PaintScreen (int) >====----
  1567.     |*|
  1568.     |*| Draw/Restore the screen
  1569.     |*|
  1570.     |*| Entry Conditions:
  1571.     |*|     INT is a TRUE/FALSE flag
  1572.     |*|
  1573.     |*| Exit Conditions:
  1574.     |*|     None
  1575.     |*|
  1576.     \*/
  1577. static void PaintScreen (tf)
  1578.     int tf;
  1579. {
  1580. rect r;
  1581.  
  1582. static int backedup = FALSE;
  1583.  
  1584.     if (tf) {            // paint the screen
  1585.  
  1586.         if (!backedup)
  1587.             BackupVideo ( &OurWnd.wndr, (char far *)&screenbuffer[0], 0, 0 );
  1588.  
  1589.         backedup = TRUE;
  1590.  
  1591.         if (CallersFillChar)
  1592.             _videofill ( CallersFillChar, Colors->Filler, &OurWnd.wndr );
  1593.  
  1594.         DrawScreen ( &MixerRect,  &screenlayout[0] );
  1595.         r.row2 = r.row1 = MixerRect.row1+1;
  1596.         r.col1 = MixerRect.col1+1;
  1597.         r.col2 = MixerRect.col2-3;
  1598.         _videoattr ( Colors->ButHi_AND, Colors->ButHi_XOR,&r);
  1599.  
  1600.         DrawScreen ( &RecordRect, &screen3[0] );
  1601.         DrawScreen ( &VolRect,      &screen2[0] );
  1602.         DrawScreen ( &Help2Rect,  &screen4[0] );
  1603.  
  1604.     }
  1605.  
  1606.     else {
  1607.         if (backedup) {
  1608.             RestoreVideo ( &OurWnd.wndr, (char far *) &screenbuffer[0], 0, 0 );
  1609.             backedup = FALSE;
  1610.         }
  1611.     }
  1612. }
  1613.  
  1614.  
  1615.     /*\
  1616.     |*|----====< ProcessRecordEffects (int) >====----
  1617.     |*|
  1618.     |*| Process the Effects dialog box
  1619.     |*|
  1620.     |*| Entry Conditions:
  1621.     |*|     None
  1622.     |*|
  1623.     |*| Exit Conditions:
  1624.     |*|     None
  1625.     |*|
  1626.     \*/
  1627. static void ProcessRecordEffects(msg)
  1628.     int msg;
  1629. {
  1630. rect r;
  1631.  
  1632. static void *ol;
  1633. static void *effectslastobj;
  1634. static void *effectscurrobj;
  1635.  
  1636.         switch (msg) {
  1637.  
  1638.             case DRAWIT:
  1639.                 DrawScreen ( &EffectsRect, &effectsbkgn[0] );
  1640.                 DrawScreen ( &Screen6Rect, &screen6[0]       );
  1641.                 DrawScreen ( &Screen5Rect, &screen5[0]       );
  1642.                 DrawScreen ( &Screen7Rect, &screen7[0]       );
  1643.                 BroadcastToList (DRAWIT,CurrList);    // draw the controls
  1644.                 break;
  1645.  
  1646.             case FOCUS_GIVEN:
  1647.  
  1648.                 // let the current object know its not in foreground
  1649.  
  1650.                     (*CurrentObject->scr)(FOCUS_TAKEN,CurrentObject);
  1651.  
  1652.                 // switch linked lists and current objects
  1653.  
  1654.                     ol = CurrList;                    // switch object lists
  1655.                     CurrList = &EffectsList;
  1656.  
  1657.                     effectslastobj = CurrentObject; // switch objects
  1658.                     if ((CurrentObject = effectscurrobj) == 0)
  1659.                         CurrentObject = CurrList->head;
  1660.  
  1661.                 // paint the screen
  1662.  
  1663.                     ProcessRecordEffects(DRAWIT);
  1664.  
  1665.                     (*CurrentObject->scr)(FOCUS_GIVEN,CurrentObject); // highlight
  1666.  
  1667.                 // all done till a FOCUS_TAKEN is received
  1668.  
  1669.                     break;
  1670.  
  1671.             case FOCUS_TAKEN:
  1672.  
  1673.                 // let the current object know its not in foreground
  1674.  
  1675.                     (*CurrentObject->scr)(FOCUS_TAKEN,CurrentObject);
  1676.  
  1677.                 // switch linked lists and current objects
  1678.  
  1679.                     CurrList = ol;                    // restore the old list
  1680.  
  1681.                     effectscurrobj = CurrentObject; // switch objects
  1682.                     if (effectslastobj)
  1683.                         CurrentObject  = effectslastobj;
  1684.  
  1685.                 // restore the screen
  1686.  
  1687.                     PaintScreen     (FALSE);            // restore the screen
  1688.                     PaintScreen     (TRUE);             // put up the screen
  1689.                     BroadcastToList (DRAWIT,CurrList);    // draw the controls
  1690.  
  1691.                     (*CurrentObject->scr)(FOCUS_GIVEN,CurrentObject); // highlight
  1692.  
  1693.                     break;
  1694.  
  1695.                 default:
  1696.                     break;
  1697.  
  1698.             }
  1699. }
  1700.  
  1701.  
  1702.  
  1703.     /*\
  1704.     |*|----====< PtInRect (point *, rect *) >====----
  1705.     |*|
  1706.     |*| return TRUE if point is within the rectangle
  1707.     |*|
  1708.     |*| Entry Conditions:
  1709.     |*|     None
  1710.     |*|
  1711.     |*| Exit Conditions:
  1712.     |*|     None
  1713.     |*|
  1714.     \*/
  1715. static int PtInRect (p,r)
  1716.     point *p;
  1717.     rect  *r;
  1718. {
  1719.  
  1720.     if ((p->row < r->row1) && (p->row >= r->row2))
  1721.         return(FALSE);
  1722.     if ((p->col < r->col1) && (p->col >= r->col2))
  1723.         return(FALSE);
  1724.  
  1725.     return (TRUE);
  1726. }
  1727.  
  1728.  
  1729.     /*\
  1730.     |*|----====< int ScrollObjectHandler() >====----
  1731.     |*|
  1732.     |*| Scroll bar object control
  1733.     |*|
  1734.     |*| Entry Conditions:
  1735.     |*|     None
  1736.     |*|
  1737.     |*| Exit Conditions:
  1738.     |*|     None
  1739.     |*|
  1740.     \*/
  1741. static int ScrollObjectHandler (msg,o,ptr)
  1742.     int msg;
  1743.     SPtr o;
  1744.     void *ptr;
  1745. {
  1746. void **pptr;
  1747. rect r;
  1748. int l,ri,i,key;
  1749. char c1,c2;
  1750.  
  1751.     // get a pointer to the stack
  1752.  
  1753.         pptr = &ptr;
  1754.  
  1755.     // process the message
  1756.  
  1757.         switch (msg) {
  1758.  
  1759.             case OPEVENT:
  1760.  
  1761.                 key = 0;
  1762.  
  1763.                 switch (((EPtr)pptr[0])->buttons) {
  1764.  
  1765.                     case ENDKEY:                // right = 2;
  1766.                         key++;
  1767.                     case HOMEKEY:                // left  = 1;
  1768.                         key++;
  1769.                     case LFARROW:                // both  = 0;
  1770.  
  1771.                         if (key != 2) {         // do LEFT on left/both cases
  1772.  
  1773.                             if (o->leftchannel > 0)
  1774.                                 o->leftchannel -= 3;
  1775.  
  1776.                             SendMixer
  1777.                               (
  1778.                                 "SET ",
  1779.                                 o->mixerselect,
  1780.                                 1,
  1781.                                 o,
  1782.                                 BI_SETTO,
  1783.                                 o->leftchannel
  1784.                               );
  1785.  
  1786.                         }
  1787.  
  1788.                         if (key != 1) {         // do RIGHT on right/both cases
  1789.  
  1790.                             if (o->ritchannel > 0)
  1791.                                 o->ritchannel -= 3;
  1792.  
  1793.                             SendMixer
  1794.                               (
  1795.                                 "SET ",
  1796.                                 o->mixerselect,
  1797.                                 2,
  1798.                                 o,
  1799.                                 BI_SETTO,
  1800.                                 o->ritchannel
  1801.                               );
  1802.  
  1803.                         }
  1804.  
  1805.                         (*o->scr) (DRAWIT,o);
  1806.  
  1807.                         break;
  1808.  
  1809.                     case PGDNKEY:                // right = 2;
  1810.                         key++;
  1811.                     case PGUPKEY:               // left  = 1;
  1812.                         key++;
  1813.                     case RIARROW:                // both  = 0;
  1814.  
  1815.                         if (key != 2) {         // do LEFT on left/both cases
  1816.  
  1817.                             if (o->leftchannel < 100)
  1818.                                 o->leftchannel += 3;
  1819.  
  1820.                             SendMixer
  1821.                               (
  1822.                                 "SET ",
  1823.                                 o->mixerselect,
  1824.                                 1,
  1825.                                 o,
  1826.                                 BI_SETTO,
  1827.                                 o->leftchannel
  1828.                               );
  1829.                         }
  1830.  
  1831.                         if (key != 1) {         // do RIGHT on right/both cases
  1832.  
  1833.                             if (o->ritchannel < 100)
  1834.                                 o->ritchannel += 3;
  1835.  
  1836.                             SendMixer
  1837.                               (
  1838.                                 "SET ",
  1839.                                 o->mixerselect,
  1840.                                 2,
  1841.                                 o,
  1842.                                 BI_SETTO,
  1843.                                 o->ritchannel
  1844.                               );
  1845.                         }
  1846.  
  1847.                         (*o->scr) (DRAWIT,o);
  1848.  
  1849.                         break;
  1850.  
  1851.                     default:
  1852.                         break;
  1853.                 }
  1854.  
  1855.                 break;
  1856.  
  1857.             case SENDIT:
  1858.  
  1859.                 SendMixer ("SET ",o->mixerselect,1,o,BI_SETTO,o->leftchannel);
  1860.                 (*(void(*)())ptr)(&CommandString);
  1861.                 SendMixer ("SET ",o->mixerselect,2,o,BI_SETTO,o->ritchannel);
  1862.                 (*(void(*)())ptr)(&CommandString);
  1863.                 break;
  1864.  
  1865.             case FOCUS_GIVEN:
  1866.  
  1867.                 // highlight the entire field
  1868.  
  1869.                     r.row1 = o->namr.row1;
  1870.                     r.row2 = o->namr.row2;
  1871.                     r.col2 = r.col1 = o->namr.col2+2;
  1872.                     _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &o->namr );
  1873.                     _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &r       );
  1874.  
  1875.                     r.row1 = o->scrr.row1;
  1876.                     r.row2 = o->scrr.row2;
  1877.                     r.col2 = r.col1 = o->scrr.col2+2;
  1878.                     _videoattr ( Colors->ScrTmpHi_AND, Colors->ScrTmpHi_XOR, &o->scrr );
  1879.                     _videoattr ( Colors->ScrTmpHi_AND, Colors->ScrTmpHi_XOR, &r       );
  1880.  
  1881.                     if (o->swi)
  1882.                         _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &o->swir );
  1883.  
  1884.                     break;
  1885.  
  1886.             case FOCUS_TAKEN:
  1887.  
  1888.                 // highlight the entire field
  1889.  
  1890.                     r.row1 = o->namr.row1;
  1891.                     r.row2 = o->namr.row2;
  1892.                     r.col2 = r.col1 = o->namr.col2+2;
  1893.                     _videoattr ( Colors->TmpLo_AND,    Colors->TmpLo_XOR,     &o->namr );
  1894.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &r       );
  1895.  
  1896.                     r.row1 = o->scrr.row1;
  1897.                     r.row2 = o->scrr.row2;
  1898.                     r.col2 = r.col1 = o->scrr.col2+2;
  1899.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &o->scrr );
  1900.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &r       );
  1901.  
  1902.                     if (o->swi)
  1903.                         _videoattr ( Colors->TmpLo_AND,    Colors->TmpLo_XOR,     &o->swir );
  1904.  
  1905.                     break;
  1906.  
  1907.             case DRAWIT:
  1908.  
  1909.                 // move the cursor to the slide bar area
  1910.  
  1911.                     _videosetcurs ( o->scrr.row1, o->scrr.col1 );
  1912.                     _zipout       ( twobar, 0);
  1913.                     _videosetcurs ( o->scrr.row1+1, o->scrr.col1 );
  1914.                     _zipout       ( twobar, 0);
  1915.  
  1916.                     l = (o->leftchannel * 31) / 100;
  1917.                     _videosetcurs ( o->scrr.row1, o->scrr.col1+(l>>1) );
  1918.                     _zipout (((l & 1) ? "▐" : "▌"), 0);
  1919.                     l = (o->ritchannel * 31) / 100;
  1920.                     _videosetcurs ( o->scrr.row1+1, o->scrr.col1+(l>>1) );
  1921.                     _zipout (((l & 1) ? "▐" : "▌"), 0);
  1922.  
  1923.                 // display a mixer bar
  1924.  
  1925.                     if (o->swi) {
  1926.  
  1927.                       //if (o->mixerselect == BI_INPUTMIXER)
  1928.                       //    _videoattr (Colors->ButHi_AND,Colors->ButHi_XOR,&o->swir);
  1929.                       //else
  1930.                       //    _videoattr (Colors->ButLo_AND,Colors->ButLo_XOR,&o->swir);
  1931.  
  1932.                         if (o->mixerselect == BI_INPUTMIXER) {
  1933.                             _videosetcurs (o->swir.row1,o->swir.col1);
  1934.                             _zipout (playmsgi1);
  1935.                             _videosetcurs (o->swir.row1+1,o->swir.col1);
  1936.                             _zipout (playmsgi2);
  1937.                         }
  1938.                         else {
  1939.                             _videosetcurs (o->swir.row1,o->swir.col1);
  1940.                             _zipout (playmsgo1);
  1941.                             _videosetcurs (o->swir.row1+1,o->swir.col1);
  1942.                             _zipout (playmsgo2);
  1943.                         }
  1944.                     }
  1945.  
  1946.                 break;
  1947.  
  1948.             case OPENINIT:
  1949.  
  1950.                 // get the output mixer current state
  1951.  
  1952.                 SendMixer ("GET ",BI_OUTPUTMIXER,0,o,0,0);
  1953.                 DecodeMixer (MVResponse);
  1954.  
  1955.                 if (leftswitch == '+') {
  1956.                     o->mixerselect    = BI_OUTPUTMIXER;
  1957.                     o->leftchannel    = leftvolume;
  1958.                 }
  1959.                 else {
  1960.                     o->deadmixer    = BI_OUTPUTMIXER;
  1961.                     o->deadlchannel = leftvolume;
  1962.                 }
  1963.  
  1964.                 if (ritswitch == '+') {
  1965.                     o->mixerselect    = BI_OUTPUTMIXER;
  1966.                     o->ritchannel    = ritvolume;
  1967.                 }
  1968.                 else {
  1969.                     o->deadmixer    = BI_OUTPUTMIXER;
  1970.                     o->deadrchannel = ritvolume;
  1971.                 }
  1972.  
  1973.                 // get the input mixer current state
  1974.  
  1975.                 SendMixer ("GET ",BI_INPUTMIXER,0,o,0,0);
  1976.                 DecodeMixer (MVResponse);
  1977.  
  1978.                 if (leftswitch == '+') {
  1979.                     o->mixerselect    = BI_INPUTMIXER;
  1980.                     o->leftchannel    = leftvolume;
  1981.                 }
  1982.                 else {
  1983.                     o->deadmixer    = BI_INPUTMIXER;
  1984.                     o->deadlchannel = leftvolume;
  1985.                 }
  1986.  
  1987.                 if (ritswitch == '+') {
  1988.                     o->mixerselect    = BI_INPUTMIXER;
  1989.                     o->ritchannel    = ritvolume;
  1990.                 }
  1991.                 else {
  1992.                     o->deadmixer    = BI_INPUTMIXER;
  1993.                     o->deadrchannel = ritvolume;
  1994.                 }
  1995.  
  1996.                 // make sure both inputs are on the same mixer
  1997.  
  1998.                 SendMixer ("SET ",o->mixerselect,1,o,BI_SETTO,o->leftchannel);
  1999.                 SendMixer ("SET ",o->mixerselect,2,o,BI_SETTO,o->ritchannel);
  2000.                 break;
  2001.  
  2002.             case CLEARIT:
  2003.                 break;
  2004.  
  2005.             default:
  2006.                 break;
  2007.         }
  2008. }
  2009.  
  2010.  
  2011.     /*\
  2012.     |*|----====< int SendOnOff( char *, char *, int, VPtr, int, int ) >====----
  2013.     |*|
  2014.     |*| Send a mixer selection
  2015.     |*|
  2016.     |*| Entry Conditions:
  2017.     |*|     char *cmd = "SET", "GET"
  2018.     |*|     VPtr o      = Volume device name
  2019.     |*|     int  v      = new volume setting
  2020.     |*|
  2021.     |*| Exit Conditions:
  2022.     |*|     MVResponse string holds the result
  2023.     |*|
  2024.     \*/
  2025. static int SendOnOff(cmd,dev,o)
  2026.     char *cmd;    // command
  2027.     char *dev;    // device
  2028.     BPtr o;     // channel name & state
  2029.  
  2030. {
  2031.  
  2032.     // build the string
  2033.  
  2034.         strcpy (CommandString,cmd);        // command
  2035.         strcat (CommandString,dev);        // device name
  2036.         strcat (CommandString,o->name);    // input channel
  2037.         strcat (CommandString,((o->state) ? "ON" : "OFF"));
  2038.  
  2039.         SendTextOut (CommandString);
  2040. }
  2041.  
  2042.  
  2043.     /*\
  2044.     |*|----====< int SendMixer( char *, int, int, SPtr, int, int ) >====----
  2045.     |*|
  2046.     |*| Send a mixer selection
  2047.     |*|
  2048.     |*|     char *cmd = "SET", "GET"
  2049.     |*|     int  dev  = INPUTMIXER or OUTPUTMIXER
  2050.     |*|     int  lr   = both(0),left(1),right(2)
  2051.     |*|     VPtr o      = Volume device name
  2052.     |*|     int  f      = function (UP/DOWN/TO)
  2053.     |*|     int  v      = new volume setting
  2054.     |*|
  2055.     |*| Exit Conditions:
  2056.     |*|     MVResponse string holds the result
  2057.     |*|
  2058.     \*/
  2059. static int SendMixer (cmd,dev,lr,o,f,v)
  2060.     char *cmd;    // command
  2061.     int dev;    // device name
  2062.     int lr;     // left/right/both
  2063.     SPtr o;     // input channel name
  2064.     int f;        // movement function
  2065.     int v;        // new mixer value
  2066.  
  2067. {
  2068. char *fs,*ms,*lrs;
  2069. char val[7];
  2070.  
  2071.     // get the text string equvalent for the function
  2072.  
  2073.         switch (lr) {
  2074.  
  2075.             case 1:
  2076.                 lrs = "LEFT ";  // LEFT side only
  2077.                 break;
  2078.  
  2079.             case 2:
  2080.                 lrs = "RIGHT "; // RIGHT side only
  2081.                 break;
  2082.  
  2083.             case 0:             // BOTH
  2084.             default:
  2085.                 lrs = makemenull;
  2086.                 break;
  2087.         }
  2088.  
  2089.     // get the text string equvalent for the function
  2090.  
  2091.         switch (f) {
  2092.             case BI_SETTO:
  2093.                 fs = "TO ";
  2094.                 break;
  2095.  
  2096.             case BI_UPTO:
  2097.                 fs = "UP ";
  2098.                 break;
  2099.  
  2100.             case BI_DOWNTO:
  2101.                 fs = "DOWN ";
  2102.                 break;
  2103.  
  2104.             default:
  2105.                 fs = makemenull;
  2106.                 break;
  2107.         }
  2108.  
  2109.     // correct the value
  2110.  
  2111.         if (v < 0)     v = 0;
  2112.         if (v > 100) v = 100;
  2113.  
  2114.     // build the string
  2115.  
  2116.         ms = (dev == BI_OUTPUTMIXER) ? "OUTPUT MIXER " : "INPUT MIXER ";
  2117.         itoa   (v,val,10);
  2118.  
  2119.         strcpy (CommandString,cmd);          // command
  2120.         strcat (CommandString,ms);             // device name
  2121.         strcat (CommandString,lrs);          // left/right
  2122.         strcat (CommandString,o->name);      // input channel
  2123.         strcat (CommandString,fs);             // function (up/down/to)
  2124.         strcat (CommandString,val);          // new #
  2125.         strcat (CommandString," PERCENT");
  2126.  
  2127.         SendTextOut (CommandString);
  2128. }
  2129.  
  2130.  
  2131.     /*\
  2132.     |*|----====< int SendVolume( char *, int, VPtr, int, int ) >====----
  2133.     |*|
  2134.     |*| Send a mixer selection
  2135.     |*|
  2136.     |*| Entry Conditions:
  2137.     |*|     char *cmd = "SET", "GET"
  2138.     |*|     int  lr   = both(0),left(1),right(2)
  2139.     |*|     VPtr o      = Volume device name
  2140.     |*|     int  f      = function (UP/DOWN/TO)
  2141.     |*|     int  v      = new volume setting
  2142.     |*|
  2143.     |*| Exit Conditions:
  2144.     |*|     MVResponse string holds the result
  2145.     |*|
  2146.     \*/
  2147. static int SendVolume (cmd,lr,o,f,v)
  2148.     char *cmd;    // command
  2149.     int lr;     // left/right/both
  2150.     VPtr o;     // channel name
  2151.     int f;        // movement function
  2152.     int v;        // new mixer value
  2153.  
  2154. {
  2155. char *fs,*ms,*lrs;
  2156. char val[7];
  2157.  
  2158.     // get the text string equvalent for the function
  2159.  
  2160.         switch (lr) {
  2161.  
  2162.             case 1:
  2163.                 lrs = "LEFT ";  // LEFT side only
  2164.                 break;
  2165.  
  2166.             case 2:
  2167.                 lrs = "RIGHT "; // RIGHT side only
  2168.                 break;
  2169.  
  2170.             case 0:             // BOTH
  2171.             default:
  2172.                 lrs = makemenull;
  2173.                 break;
  2174.         }
  2175.  
  2176.     // get the text string equvalent for the function
  2177.  
  2178.         switch (f) {
  2179.             case BI_SETTO:
  2180.                 fs = "TO ";
  2181.                 break;
  2182.  
  2183.             case BI_UPTO:
  2184.                 fs = "UP ";
  2185.                 break;
  2186.  
  2187.             case BI_DOWNTO:
  2188.                 fs = "DOWN ";
  2189.                 break;
  2190.  
  2191.             default:
  2192.                 fs = makemenull;
  2193.                 break;
  2194.         }
  2195.  
  2196.     // correct the value on slide bars
  2197.  
  2198.         if (o->type == OBJ_VOLUME) {
  2199.  
  2200.             // fudge the volume to correct the rounding errors
  2201.  
  2202.             if (++v < 0)   v = 0;
  2203.             if (v > 100) v = 100;
  2204.         }
  2205.  
  2206.     // build the string
  2207.  
  2208.         itoa   (v,val,10);
  2209.  
  2210.         strcpy (CommandString,cmd);          // command
  2211.         strcat (CommandString,"VOLUME ");    // device name
  2212.         strcat (CommandString,lrs);          // left/right
  2213.         strcat (CommandString,o->name);      // input channel
  2214.         strcat (CommandString,fs);             // function (up/down/to)
  2215.  
  2216.         if (o->type == OBJ_VOLUME) {
  2217.             strcat (CommandString,val);      // new #
  2218.             strcat (CommandString," PERCENT");
  2219.         }
  2220.         else
  2221.             strcat (CommandString,((v) ? "ON" : "OFF"));
  2222.  
  2223.         SendTextOut (CommandString);
  2224. }
  2225.  
  2226.  
  2227.     /*\
  2228.     |*|----====< int SendTextOut( char * ) >====----
  2229.     |*|
  2230.     |*| Send a text string to MVPROAS
  2231.     |*|
  2232.     |*| Entry Conditions:
  2233.     |*|     None
  2234.     |*|
  2235.     |*| Exit Conditions:
  2236.     |*|     None
  2237.     |*|
  2238.     \*/
  2239. static int SendTextOut(s)
  2240.     char *s;
  2241. {
  2242. char *b;
  2243.  
  2244.         b = s;
  2245.         while (*b++) ;
  2246.         write (mv,s,b-s);
  2247.  
  2248.         _dlgflushfile(mv);    // the below code is now in dialoga.asm
  2249.         //    _asm {
  2250.         //        mov     bx,mv
  2251.         //        mov     ah,45h
  2252.         //        int     21h
  2253.         //        jnc     thisisbad
  2254.         //        mov     bx,ax
  2255.         //        mov     ah,3eh
  2256.         //        int     21h
  2257.         //    thisisbad:
  2258.         //    }
  2259.  
  2260.        read (mv,MVResponse,80);
  2261.  
  2262.             {
  2263.             char *m= MVResponse;
  2264.  
  2265.             do
  2266.                 if (*m == '\n')
  2267.                     *m= ' ';
  2268.             while (*++m);
  2269.             do
  2270.                 if (*m == ' ')
  2271.                     *m--= '\0';
  2272.                 else
  2273.                     m--;
  2274.             while (isspace(*m));
  2275.             }
  2276.  
  2277. }
  2278.  
  2279.  
  2280.     /*\
  2281.     |*|----====< int SwitchObjectHandler() >====----
  2282.     |*|
  2283.     |*| mixer selection switch object control
  2284.     |*|
  2285.     |*| Entry Conditions:
  2286.     |*|     None
  2287.     |*|
  2288.     |*| Exit Conditions:
  2289.     |*|     None
  2290.     |*|
  2291.     \*/
  2292.  
  2293. static int SwitchObjectHandler(msg,o,ptr)
  2294.     int msg;
  2295.     SPtr o;
  2296.     void *ptr;
  2297. {
  2298. void **pptr;
  2299.  
  2300.     // get a pointer to the stack
  2301.  
  2302.         pptr = &ptr;
  2303.  
  2304.     // process the message
  2305.  
  2306.         switch (msg) {
  2307.  
  2308.             case OPEVENT:
  2309.  
  2310.                 switch (((EPtr)pptr[0])->buttons) {
  2311.  
  2312.                     case ENTER:
  2313.  
  2314.                         // toggle the input/output mixer selection
  2315.  
  2316.                         if (o == &DigitalScroll)
  2317.                             break;
  2318.  
  2319.                         if (o->mixerselect == BI_OUTPUTMIXER)
  2320.                             o->mixerselect = BI_INPUTMIXER;
  2321.                         else
  2322.                             o->mixerselect = BI_OUTPUTMIXER;
  2323.  
  2324.                         SendMixer
  2325.                           (
  2326.                             "SET ",
  2327.                             o->mixerselect,
  2328.                             1,
  2329.                             o,
  2330.                             BI_SETTO,
  2331.                             o->leftchannel
  2332.                           );
  2333.  
  2334.                         SendMixer
  2335.                           (
  2336.                             "SET ",
  2337.                             o->mixerselect,
  2338.                             2,
  2339.                             o,
  2340.                             BI_SETTO,
  2341.                             o->ritchannel
  2342.                           );
  2343.  
  2344.                         (*o->scr) (DRAWIT,o);
  2345.  
  2346.                     default:
  2347.                         break;
  2348.                 }
  2349.                 break;
  2350.  
  2351.             case SENDIT:
  2352.             case FOCUS_GIVEN:
  2353.             case FOCUS_TAKEN:
  2354.             case DRAWIT:
  2355.             case CLEARIT:
  2356.             case OPENINIT:
  2357.             default:
  2358.                 break;
  2359.         }
  2360. }
  2361.  
  2362.  
  2363.  
  2364.     /*\
  2365.     |*|----====< int  SystemKey(EPtr); >====----
  2366.     |*|
  2367.     |*|    Check the event for a system keystroke.
  2368.     |*|
  2369.     \*/
  2370. static int    SystemKey(e)
  2371.     EPtr e;
  2372. {
  2373. Event ev;
  2374. rect r;
  2375. OLPtr ol;
  2376.  
  2377.     // exit if not a keyboard event
  2378.  
  2379.         if (e->type != EV_KEYB)
  2380.             return(0);
  2381.  
  2382.     // process it...
  2383.  
  2384.         switch (e->buttons) {
  2385.  
  2386.             case ESCAPE:
  2387.  
  2388.                 if (DialogBox & EFFECTS_DLG) {
  2389.                     ProcessRecordEffects(FOCUS_TAKEN);
  2390.                     DialogBox &= ~EFFECTS_DLG;
  2391.                 }
  2392.                 else
  2393.                     exitcode = TRUE;
  2394.  
  2395.                 return(1);
  2396.  
  2397.             case ENTER:
  2398.                 if (CurrentObject->type == OBJ_SCROLL) {
  2399.                     if (CurrentObject->swi)
  2400.                         (*CurrentObject->swi) (OPEVENT,CurrentObject,e);
  2401.                 }
  2402.                 else
  2403.                     (*CurrentObject->scr) (OPEVENT,CurrentObject,e);
  2404.                 return(1);
  2405.  
  2406.             case HOMEKEY:
  2407.             case PGDNKEY:
  2408.             case ENDKEY:
  2409.             case PGUPKEY:
  2410.             case PLUSKEY1:
  2411.             case PLUSKEY2:
  2412.             case MINUSKEY1:
  2413.             case MINUSKEY2:
  2414.             case RIARROW:
  2415.             case LFARROW:
  2416.                 (*CurrentObject->scr) (OPEVENT,CurrentObject,e);
  2417.                 return(1);
  2418.  
  2419.             case SH_TABKEY:
  2420.             case UPARROW:
  2421.  
  2422.                 (*CurrentObject->scr) (FOCUS_TAKEN,CurrentObject);
  2423.  
  2424.                 if (CurrentObject->back)
  2425.                     CurrentObject = CurrentObject->back;
  2426.                 else
  2427.                     CurrentObject = CurrList->tail;
  2428.  
  2429.                 (*CurrentObject->scr) (FOCUS_GIVEN,CurrentObject);
  2430.                 return(TRUE);
  2431.  
  2432.             case TABKEY:
  2433.             case DNARROW:
  2434.  
  2435.                 (*CurrentObject->scr) (FOCUS_TAKEN,CurrentObject);
  2436.  
  2437.                 if (CurrentObject->next)
  2438.                     CurrentObject = CurrentObject->next;
  2439.                 else
  2440.                     CurrentObject = CurrList->head;
  2441.  
  2442.                 (*CurrentObject->scr) (FOCUS_GIVEN,CurrentObject);
  2443.                 return(TRUE);
  2444.  
  2445.             case F1KEY:
  2446.  
  2447.                 // draw the help screen
  2448.  
  2449.                     if (VideoSegment == 0xb800)
  2450.                         Colors = &HelpsColorScheme;
  2451.  
  2452.                     DrawScreen    ( &Help1Rect, &helpscreen[0] );
  2453.  
  2454.                 // do some special highlighting for enhanced looks
  2455.  
  2456.                     if (VideoSegment == 0xb800) {
  2457.  
  2458.                         r.row2 = ( r.row1 = Help1Rect.row1 + 1) + 1;
  2459.                         r.col1 = Help1Rect.col1 + 1;
  2460.                         r.col2 = Help1Rect.col2 - 3;
  2461.  
  2462.                         _videoattr
  2463.                           (
  2464.                             0x00,
  2465.                             0x3f,
  2466.                             &r
  2467.                           );
  2468.                     }
  2469.  
  2470.                 // wait for a keystroke
  2471.  
  2472.                     while (!GetEvent (&ev))  ;
  2473.  
  2474.                     if (VideoSegment == 0xb800)
  2475.                         Colors = &ColorScheme;
  2476.  
  2477.                 // restore the screen
  2478.  
  2479.                     PaintScreen  (FALSE);     // restore the screen
  2480.                     PaintScreen  (TRUE);     // put up the screen
  2481.                     BroadcastToList (DRAWIT,&MainList); // draw the controls
  2482.  
  2483.                     if (DialogBox & EFFECTS_DLG) {
  2484.                         ProcessRecordEffects(DRAWIT);
  2485.                         BroadcastToList (DRAWIT,&EffectsList);
  2486.                     }
  2487.  
  2488.                     (*CurrentObject->scr)(FOCUS_GIVEN,CurrentObject); // re-highlight
  2489.                     return(TRUE);
  2490.  
  2491.             case F2KEY:
  2492.  
  2493.                 // try to open and process the effects windows
  2494.  
  2495.                     if (!(DialogBox & EFFECTS_DLG)) {
  2496.  
  2497.                         // do not re-enter
  2498.  
  2499.                             DialogBox |= EFFECTS_DLG;
  2500.  
  2501.                             ProcessRecordEffects(FOCUS_GIVEN);
  2502.                     }
  2503.                     return(TRUE);
  2504.  
  2505.             case F5KEY:    /* F5-F8 load mixer settings from DOS file */
  2506.             case F6KEY: /* subtract F5 scancode from key pressed */
  2507.             case F7KEY: /* move high byte to low and use as index (0-3) */
  2508.             case F8KEY:
  2509.                 loadcurrent((e->buttons- F5KEY)>> 8);    /* open, read setting[0-3].pas and SendTextOut */
  2510.                 BroadcastMsg (OPENINIT); // tell everyone we are starting
  2511.                 BroadcastToList (DRAWIT,CurrList);     // draw the controls
  2512.                 return(TRUE);
  2513.  
  2514.             case SF5KEY: /* Shift F5-F8 save mixer settings into DOS file */
  2515.             case SF6KEY: /* subtract SF5 scancode from key pressed */
  2516.             case SF7KEY: /* move high byte to load and use as index (0-3) */
  2517.             case SF8KEY:
  2518.                 savecurrent((e->buttons- SF5KEY)>> 8); /* save setting[0-3].pas */
  2519.                 return(TRUE);
  2520.  
  2521.             case F4KEY:
  2522.  
  2523.                 // have all objects re-init themselves, then redraw
  2524.  
  2525.                     SendTextOut  ("RESET");  // reset the mixers
  2526.                     BroadcastMsg (OPENINIT); // tell everyone we are starting
  2527.                     BroadcastToList (DRAWIT,CurrList);     // draw the controls
  2528.                     return(TRUE);
  2529.  
  2530.             default:
  2531.                 return(FALSE);
  2532.         }
  2533.  
  2534. }
  2535.  
  2536.  
  2537.     /*\
  2538.     |*|----====< void SystemShutDown(); >====----
  2539.     |*|
  2540.     |*|    Exits to the swapper to exit for good, or loads a program.
  2541.     |*|
  2542.     \*/
  2543. static void SystemShutDown()
  2544. {
  2545.    //    MouseInit        ( OFF,OFF );            // kill the mouse
  2546.  
  2547.    // restore the video
  2548.  
  2549.         PaintScreen   ( FALSE );            // take down the screen
  2550.         _videosetcurs ( OrigRow, OrigCol ); // restore the cursor position
  2551.         _videocshape  ( -1, -1);            // now, restore the original shape
  2552.  
  2553.     // restore numlock
  2554.  
  2555.         _dlgrestorenumlock();    // the below code is now in dialoga.asm
  2556.         //    _asm {
  2557.         //        push    es                        ; save the numlock state
  2558.         //        sub     ax,ax
  2559.         //        mov     es,ax
  2560.         //        mov     al,NumLockState
  2561.         //        or        es:[0x417],al            ; possibly set it
  2562.         //        pop     es
  2563.         //    }
  2564. }
  2565.  
  2566.  
  2567.     /*\
  2568.     |*|----====< void SystemInit() >====----
  2569.     |*|
  2570.     |*| System wide initialization of the program
  2571.     |*|
  2572.     |*| Entry Conditions:
  2573.     |*|     None
  2574.     |*|
  2575.     |*| Exit Conditions:
  2576.     |*|     None
  2577.     |*|
  2578.     \*/
  2579. static int SystemInit()
  2580. {
  2581. int n;
  2582. long l;
  2583.  
  2584.     /* setup the mouse & move to the middle of the wave window          */
  2585.  
  2586.     //    MouseInit    (ON,OFF);
  2587.     //    MouseAction (0x12);             // left button down/up action
  2588.  
  2589.         if (_videocard() == 1) {        // if mono, point to that segment
  2590.             VideoSegment = OurWnd.sseg = 0xb000;
  2591.             Colors = &MonoScheme;
  2592.         }
  2593.  
  2594.     // get the original row, column and kill numlock
  2595.  
  2596.  
  2597.         l = _videogetcurs();
  2598.         OrigCol = (int) (l >> 16) & 0xffff;
  2599.         OrigRow = (int) l & 0xffff;
  2600.  
  2601.         _dlgsavenumlock();        // the below code is now in dialoga.asm
  2602.         //    _asm {
  2603.         //        push    es                            ; save the numlock state
  2604.         //        sub     ax,ax
  2605.         //        mov     es,ax
  2606.         //        mov     al,0x20
  2607.         //        and     al,es:[0x417]
  2608.         //        and     byte ptr es:[0x417],0xdf    ; clear it...
  2609.         //        mov     NumLockState,al
  2610.         //        pop     es
  2611.         //    }
  2612.  
  2613.     // turn off the cursor
  2614.  
  2615.         _videocshape (0,0x20);            // make it invisible
  2616.  
  2617.     /* init all objects, then paint them on the screen                    */
  2618.  
  2619.         BroadcastMsg (OPENINIT);        // tell everyone we are starting
  2620.  
  2621.         PaintScreen  (TRUE);            // put up the screen
  2622.  
  2623.         BroadcastToList (DRAWIT,CurrList);// draw the controls
  2624.  
  2625.         (*CurrentObject->scr) (FOCUS_GIVEN,CurrentObject);
  2626.  
  2627.     // return good
  2628.  
  2629.         return (0);
  2630. }
  2631.  
  2632.  
  2633.     /*\
  2634.     |*|----====< int VolumeButtons() >====----
  2635.     |*|
  2636.     |*| Volume slide bar object control
  2637.     |*|
  2638.     |*| Entry Conditions:
  2639.     |*|     None
  2640.     |*|
  2641.     |*| Exit Conditions:
  2642.     |*|     None
  2643.     |*|
  2644.     \*/
  2645. static int VolumeButtons (msg,o,ptr)
  2646.     int msg;
  2647.     BPtr o;
  2648.     void *ptr;
  2649. {
  2650. void **pptr;
  2651. rect r;
  2652. int l,ri,i;
  2653. char c1,c2;
  2654.  
  2655.     // get a pointer to the stack
  2656.  
  2657.         pptr = &ptr;
  2658.  
  2659.     // process the message
  2660.  
  2661.         switch (msg) {
  2662.  
  2663.             case OPEVENT:
  2664.  
  2665.                 switch (((EPtr)pptr[0])->buttons) {
  2666.  
  2667.                     case ENTER:
  2668.  
  2669.                         if (o->state)
  2670.                             o->state = 0;
  2671.                         else
  2672.                             o->state = -1;
  2673.  
  2674.                         SendVolume
  2675.                           (
  2676.                             "SET ",
  2677.                             0,
  2678.                             (VPtr) o,
  2679.                             BI_SETTO,
  2680.                             o->state
  2681.                           );
  2682.  
  2683.                         (*o->scr) (DRAWIT,o);
  2684.  
  2685.                         break;
  2686.  
  2687.                     case ENDKEY:
  2688.                     case HOMEKEY:
  2689.                     case LFARROW:
  2690.                     case PGDNKEY:
  2691.                     case PGUPKEY:
  2692.                     case RIARROW:
  2693.  
  2694.                         // Direction keys can move these sliders
  2695.  
  2696.                         if (o == &Loudness)
  2697.                             (*BassVolume.scr)(msg,&BassVolume,ptr);
  2698.  
  2699.                         if (o == &Enhanced)
  2700.                             (*TrebVolume.scr)(msg,&TrebVolume,ptr);
  2701.                         break;
  2702.  
  2703.                     default:
  2704.                         break;
  2705.                 }
  2706.  
  2707.                 break;
  2708.  
  2709.             case SENDIT:
  2710.  
  2711.                 SendVolume
  2712.                   (
  2713.                     "SET ",
  2714.                     0,
  2715.                     (VPtr) o,
  2716.                     BI_SETTO,
  2717.                     o->state
  2718.                   );
  2719.                 (*(void(*)())ptr)(&CommandString);
  2720.  
  2721.                 break;
  2722.  
  2723.             case FOCUS_GIVEN:
  2724.  
  2725.                 // highlight the entire field
  2726.  
  2727.                     r.row1 = o->namr.row1;
  2728.                     r.row2 = o->namr.row2;
  2729.                     r.col2 = r.col1 = o->namr.col2+2;
  2730.                     _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &o->namr );
  2731.                     _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &r       );
  2732.  
  2733.                 //    r.row1 = o->scrr.row1;
  2734.                 //    r.row2 = o->scrr.row2;
  2735.                 //    r.col2 = r.col1 = o->scrr.col2+2;
  2736.                     _videoattr ( Colors->ScrTmpHi_AND, Colors->ScrTmpHi_XOR, &o->scrr );
  2737.                 //    _videoattr ( Colors->ScrTmpHi_AND, Colors->ScrTmpHi_XOR, &r       );
  2738.  
  2739.                     break;
  2740.  
  2741.             case FOCUS_TAKEN:
  2742.  
  2743.                 // highlight the entire field
  2744.  
  2745.                     r.row1 = o->namr.row1;
  2746.                     r.row2 = o->namr.row2;
  2747.                     r.col2 = r.col1 = o->namr.col2+2;
  2748.                     _videoattr ( Colors->TmpLo_AND,    Colors->TmpLo_XOR,     &o->namr );
  2749.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &r       );
  2750.  
  2751.                 //    r.row1 = o->scrr.row1;
  2752.                 //    r.row2 = o->scrr.row2;
  2753.                 //    r.col2 = r.col1 = o->scrr.col2+2;
  2754.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &o->scrr );
  2755.                 //    _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &r       );
  2756.  
  2757.                     break;
  2758.  
  2759.             case DRAWIT:
  2760.  
  2761.                 // move the cursor to the slide bar area
  2762.  
  2763.                     _videosetcurs ( o->scrr.row1, o->scrr.col1 );
  2764.                     if (o->state)
  2765.                         _zipout   ( "X" );
  2766.                     else
  2767.                         _zipout   ( "∙" );
  2768.  
  2769.                 break;
  2770.  
  2771.             case OPENINIT:
  2772.  
  2773.                 // get the output mixer current state
  2774.  
  2775.                     SendVolume ("GET ",0,(VPtr)o,0,0);
  2776.  
  2777.                     DecodeVolumeSwitch (MVResponse);
  2778.                     o->state = (VolumeSwitch == '+') ? -1 : 0;
  2779.                     break;
  2780.  
  2781.  
  2782.             case CLEARIT:
  2783.             default:
  2784.                 break;
  2785.         }
  2786. }
  2787.  
  2788.  
  2789.     /*\
  2790.     |*|----====< int UpdateTotalVolume() >====----
  2791.     |*|
  2792.     |*| update the screen if the user is typing the hot keys
  2793.     |*|
  2794.     |*| Entry Conditions:
  2795.     |*|     None
  2796.     |*|
  2797.     |*| Exit Conditions:
  2798.     |*|     None
  2799.     |*|
  2800.     \*/
  2801. static int UpdateTotalVolume()
  2802. {
  2803. int lv,rv;
  2804.  
  2805. static int delta;
  2806. static int mintic    = 18;
  2807. static int minrest    = 0;
  2808. //static int lasttime = 0;
  2809.  
  2810.     // get the clock tic, this whole routine is done once a second
  2811.  
  2812.         delta += _dlggettimedelta();    // the below code is now in dialoga.asm
  2813.         //    _asm {
  2814.         //        mov ah,0
  2815.         //        int 1Ah
  2816.         //        cmp lasttime,dx     ; ax = delta of current/last time
  2817.         //        mov lasttime,dx
  2818.         //        adc delta,0
  2819.         //    }
  2820.  
  2821.     // if the main dialog box is covered, we cannot draw, so just return
  2822.  
  2823.         if (DialogBox & EFFECTS_DLG)
  2824.             return(0);
  2825.  
  2826.     // if the change is greater than 1 second, update the screen now...
  2827.  
  2828.         if (delta > mintic) {
  2829.  
  2830.             delta    = 0;
  2831.  
  2832.             lv = LeftVolumeLevel.channel;
  2833.             rv = RitVolumeLevel.channel;
  2834.  
  2835.             (*LeftVolumeLevel.scr)(OPENINIT,&LeftVolumeLevel);
  2836.  
  2837.             if((lv != LeftVolumeLevel.channel) ||
  2838.                (rv != RitVolumeLevel.channel)) {
  2839.                     minrest = (1*19)/4;         // restore speed after 1 second
  2840.                     mintic    = 2;                // speed up polling
  2841.                     (*LeftVolumeLevel.scr)(DRAWIT,&LeftVolumeLevel);
  2842.             }
  2843.  
  2844.             if (minrest)                        // if fast poll
  2845.                 if (!--minrest)                 // check to see if we should
  2846.                     mintic = 18;                // slow it down.
  2847.         }
  2848. }
  2849.  
  2850.  
  2851.     /*\
  2852.     |*|----====< int VolumeLevels() >====----
  2853.     |*|
  2854.     |*| VOLUME LEFT/RIGHT control
  2855.     |*|
  2856.     |*| Entry Conditions:
  2857.     |*|     None
  2858.     |*|
  2859.     |*| Exit Conditions:
  2860.     |*|     None
  2861.     |*|
  2862.     \*/
  2863. static int VolumeLevels(msg,o,ptr)
  2864.     int msg;
  2865.     VPtr o;
  2866.     void *ptr;
  2867. {
  2868. void **pptr;
  2869. rect r;
  2870. int l,ri,i;
  2871. char c1,c2;
  2872.  
  2873. #define VOLE_RAMPUP 0x4001        // ramp the volume up
  2874. #define VOLE_RAMPDN 0x4002        // ramp the volume down
  2875.  
  2876.     // get a pointer to the stack
  2877.  
  2878.         pptr = &ptr;
  2879.  
  2880.     // process the message
  2881.  
  2882.         switch (msg) {
  2883.  
  2884.             case OPEVENT:
  2885.  
  2886.                 switch (((EPtr)pptr[0])->buttons) {
  2887.  
  2888.                     case ENDKEY:
  2889.                         VolumeLevels (VOLE_RAMPUP,&RitVolumeLevel,ptr);
  2890.                         break;
  2891.  
  2892.                     case HOMEKEY:
  2893.                         VolumeLevels (VOLE_RAMPUP,&LeftVolumeLevel,ptr);
  2894.                         break;
  2895.  
  2896.                     case LFARROW:
  2897.                         VolumeLevels (VOLE_RAMPUP,&LeftVolumeLevel,ptr);
  2898.                         VolumeLevels (VOLE_RAMPUP,&RitVolumeLevel,ptr);
  2899.                         break;
  2900.  
  2901.                     case PGDNKEY:
  2902.                         VolumeLevels (VOLE_RAMPDN,&RitVolumeLevel,ptr);
  2903.                         break;
  2904.  
  2905.                     case PGUPKEY:
  2906.                         VolumeLevels (VOLE_RAMPDN,&LeftVolumeLevel,ptr);
  2907.                         break;
  2908.  
  2909.                     case RIARROW:
  2910.                         VolumeLevels (VOLE_RAMPDN,&LeftVolumeLevel,ptr);
  2911.                         VolumeLevels (VOLE_RAMPDN,&RitVolumeLevel,ptr);
  2912.                         break;
  2913.  
  2914.                     default:
  2915.                         break;
  2916.                 }
  2917.  
  2918.                 break;
  2919.  
  2920.             case SENDIT:
  2921.  
  2922.                 SendVolume                    // set the left
  2923.                   (
  2924.                     "SET ",
  2925.                     1,
  2926.                     &LeftVolumeLevel,
  2927.                     BI_SETTO,
  2928.                     LeftVolumeLevel.channel
  2929.                   );
  2930.                 (*(void(*)())ptr)(&CommandString);
  2931.  
  2932.                 SendVolume                    // set the right
  2933.                   (
  2934.                     "SET ",
  2935.                     2,
  2936.                     &RitVolumeLevel,
  2937.                     BI_SETTO,
  2938.                     RitVolumeLevel.channel
  2939.                   );
  2940.  
  2941.                 (*(void(*)())ptr)(&CommandString);
  2942.  
  2943.                 break;
  2944.  
  2945.             case FOCUS_GIVEN:
  2946.  
  2947.                 // highlight the entire field
  2948.  
  2949.                     r.row1 = o->namr.row1;
  2950.                     r.row2 = o->namr.row2;
  2951.                     r.col2 = r.col1 = o->namr.col2+2;
  2952.                     _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &o->namr );
  2953.                     _videoattr ( Colors->TmpHi_AND,    Colors->TmpHi_XOR,     &r       );
  2954.  
  2955.                     r.row1 = o->scrr.row1;
  2956.                     r.row2 = o->scrr.row2;
  2957.                     r.col2 = r.col1 = o->scrr.col2+2;
  2958.                     _videoattr ( Colors->ScrTmpHi_AND, Colors->ScrTmpHi_XOR, &o->scrr );
  2959.                     _videoattr ( Colors->ScrTmpHi_AND, Colors->ScrTmpHi_XOR, &r       );
  2960.  
  2961.                 // let the right channel know too!
  2962.  
  2963.                     if (o == &LeftVolumeLevel)
  2964.                         (*RitVolumeLevel.scr)(msg,&RitVolumeLevel,ptr);
  2965.  
  2966.                     break;
  2967.  
  2968.             case FOCUS_TAKEN:
  2969.  
  2970.                 // highlight the entire field
  2971.  
  2972.                     r.row1 = o->namr.row1;
  2973.                     r.row2 = o->namr.row2;
  2974.                     r.col2 = r.col1 = o->namr.col2+2;
  2975.                     _videoattr ( Colors->TmpLo_AND,    Colors->TmpLo_XOR,     &o->namr );
  2976.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &r       );
  2977.  
  2978.                     r.row1 = o->scrr.row1;
  2979.                     r.row2 = o->scrr.row2;
  2980.                     r.col2 = r.col1 = o->scrr.col2+2;
  2981.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &o->scrr );
  2982.                     _videoattr ( Colors->ScrTmpLo_AND, Colors->ScrTmpLo_XOR, &r       );
  2983.  
  2984.                 // let the right channel know too!
  2985.  
  2986.                     if (o == &LeftVolumeLevel)
  2987.                         (*RitVolumeLevel.scr)(msg,&RitVolumeLevel,ptr);
  2988.  
  2989.                     break;
  2990.  
  2991.             case DRAWIT:
  2992.  
  2993.                 // move the cursor to the slide bar area
  2994.  
  2995.                     _videosetcurs ( o->scrr.row1, o->scrr.col1 );
  2996.                     _zipout       ( twobar, 0);
  2997.  
  2998.                     l = (o->channel * 31) / 100;
  2999.                     _videosetcurs ( o->scrr.row1, o->scrr.col1+(l>>1) );
  3000.                     _zipout (((l & 1) ? "▐" : "▌"), 0);
  3001.  
  3002.                 // let the right channel know too!
  3003.  
  3004.                     if (o == &LeftVolumeLevel)
  3005.                         (*RitVolumeLevel.scr)(msg,&RitVolumeLevel,ptr);
  3006.  
  3007.                 break;
  3008.  
  3009.             case OPENINIT:
  3010.  
  3011.                 // get the output mixer current state
  3012.  
  3013.                     SendVolume
  3014.                       (
  3015.                         "GET ",
  3016.                         ((o == &LeftVolumeLevel) ? 1 : 2),
  3017.                         o,
  3018.                         0,
  3019.                         0
  3020.                       );
  3021.  
  3022.                     DecodeVolumeNumber (MVResponse);
  3023.                     o->channel = VolumeNumber;
  3024.  
  3025.                 // let the right channel know too!
  3026.  
  3027.                     if (o == &LeftVolumeLevel)
  3028.                         (*RitVolumeLevel.scr)(msg,&RitVolumeLevel,ptr);
  3029.  
  3030.                     break;
  3031.  
  3032.             case CLEARIT:
  3033.                 break;
  3034.  
  3035.             case VOLE_RAMPUP:
  3036.  
  3037.                 // send the volume up
  3038.  
  3039.                     if (o->channel > 0)
  3040.                         o->channel -= 4;
  3041.  
  3042.                     SendVolume                    // set left/both/right
  3043.                       (
  3044.                         "SET ",
  3045.                         ((o == &LeftVolumeLevel) ? 1 : 2),
  3046.                         o,
  3047.                         BI_SETTO,
  3048.                         o->channel
  3049.                     );
  3050.  
  3051.                     (*o->scr) (DRAWIT,o);        // redraw it
  3052.  
  3053.                     break;
  3054.  
  3055.             case VOLE_RAMPDN:
  3056.  
  3057.                 // send the volume down
  3058.  
  3059.                     if (o->channel < 100)
  3060.                         o->channel += 4;
  3061.  
  3062.                     SendVolume
  3063.                       (
  3064.                         "SET ",
  3065.                         ((o == &LeftVolumeLevel) ? 1 : 2),
  3066.                         o,
  3067.                         BI_SETTO,
  3068.                         o->channel
  3069.                       );
  3070.  
  3071.                     (*o->scr) (DRAWIT,o);
  3072.  
  3073.                     break;
  3074.  
  3075.             default:
  3076.                 break;
  3077.         }
  3078. }
  3079.  
  3080.     /*\
  3081.     |*| end DIALOG.C
  3082.     \*/
  3083.  
  3084. clrbuf(char *buf, int size)
  3085. {
  3086.     int s;
  3087.  
  3088.     for (s= 0; s < size; s++)
  3089.         *buf++= '\0';
  3090. }
  3091.  
  3092. /* filename is catted onto driver pathname, and the "s." is changed to "#." */
  3093. /* where "#" is from 0 to 3, allowing 4 different mixer settings to be saved. */
  3094.  
  3095. char *filename= "settings.pas";
  3096.  
  3097. /* miscellaneous words used with mvproas */
  3098.  
  3099. #define WORD_GET 0
  3100. #define WORD_MIXER 1
  3101. #define WORD_TO 2
  3102. #define WORD_ON 3
  3103. #define WORD_OFF 4
  3104. #define WORD_LEVEL 5
  3105. #define WORD_PERCENT 6
  3106.  
  3107. char *words[]=     {"GET ", "MIXER ", "TO ", "ON ", "OFF ", "LEVEL ", " PERCENT ", ""};
  3108.  
  3109. /* these words are used to retrieve/save the mixer settings */
  3110.  
  3111. char *direct[]=     {"INPUT ",     "OUTPUT ",     ""};
  3112. char *output[]=     {"PCM ",     "MIXER "};
  3113. char *channel[]=     {"LEFT ",     "RIGHT ",     ""};
  3114. char *source[]=     {"FM ",         "INT ", "EXT ", "SPEAKER ", "MIC ", "" };
  3115. char *levels[]=     {"BASS ",     "TREBLE ",     "ENHANCED ", ""};
  3116. char *buttons[]=     {"REALSOUND ", ""};
  3117. char *crossch[]=     {"CROSSCHANNEL ", ""};
  3118. char *volume[]=     {"VOLUME ", ""};
  3119. char *onoff[]=     {"-", "+", ""};
  3120.  
  3121. /* getdriverpath() - use int 2F function BC0B to get path to mvsound.sys */
  3122. /* return !0 and fill "pathname" buffer with path to driver if successful */
  3123. /* return 0 if failed */
  3124.  
  3125. getdriverpath(char far *pathname)
  3126. {
  3127.     int status;
  3128.     char far *p= pathname;
  3129.  
  3130.     _asm
  3131.         {
  3132.         mov ax, 0BC0Bh
  3133.         int 2Fh
  3134.  
  3135.         xor ax, 'M' SHL 8 + 'V'
  3136.         mov status, ax
  3137.         jnz sorry
  3138.  
  3139.         push ds
  3140.         push es
  3141.  
  3142.  
  3143.         mov di, word ptr p[2]
  3144.         mov es, di
  3145.         mov di, word ptr p[0]
  3146.         mov ds, dx
  3147.         mov si, bx
  3148.  
  3149.         mov cx, 79
  3150. again:
  3151.         lodsb
  3152.         stosb
  3153.         or al, al
  3154.         jz done
  3155.         loop again
  3156.  
  3157.         jmp short done
  3158.  
  3159. done:
  3160.         pop es
  3161.         pop ds
  3162.  
  3163. sorry:
  3164.         }
  3165.  
  3166.     return(!status);
  3167. }
  3168.  
  3169. /* evaluate the "##   +/-   ##   +/-" string */
  3170. /* the first "## +/-" pair is the left channel, the second is the right */
  3171. /* set up four pointers to point to each of the four elements */
  3172. /* passed in is "channel", either 'L' or 'R', and "onoroff", either "+" or "-" */
  3173. /* if the L/R "onoroff" matches the passed "onoroff", return the L/R val */
  3174.  
  3175. char *isonoroff(char channel, char onoroff)
  3176. {
  3177.     char *lfvalue, *lfonoff, *rtvalue, *rtonoff;
  3178.     char *val, *oo;
  3179.  
  3180.     /* MVResponse= "LeftVal   LeftOnOff   RightVal   RightOnOff" */
  3181.     lfvalue= MVResponse;
  3182.     while (isspace(*lfvalue)) lfvalue++;
  3183.  
  3184.     lfonoff= lfvalue;
  3185.     while (!isspace(*lfonoff)) lfonoff++;
  3186.     while (isspace(*lfonoff)) lfonoff++;
  3187.  
  3188.     rtvalue= lfonoff;
  3189.     while (!isspace(*rtvalue)) rtvalue++;
  3190.     while (isspace(*rtvalue)) rtvalue++;
  3191.  
  3192.     rtonoff= rtvalue;
  3193.     while (!isspace(*rtonoff)) rtonoff++;
  3194.     while (isspace(*rtonoff)) rtonoff++;
  3195.  
  3196.     /* select val and oo according to Left or Right channel */
  3197.     switch (channel)
  3198.         {
  3199.         case 'l':
  3200.         case 'L': val= lfvalue; oo= lfonoff; break;
  3201.         case 'r':
  3202.         case 'R': val= rtvalue; oo= rtonoff; break;
  3203.         default: val= NULL; oo= NULL; break;
  3204.         }
  3205.  
  3206.     if (*oo == onoroff)
  3207.         return(val);
  3208.  
  3209.     return(NULL);
  3210.  
  3211. }
  3212.  
  3213. /* put an ascii number for "num" into the character left of the "." */
  3214. /* from the end of the string, search backwards to the first "." */
  3215. /* if not at the start of the string, stuff the ascii number */
  3216.  
  3217. putnuminname(char *pathname, int num)
  3218. {
  3219.     int i= strlen(pathname);
  3220.     while (i && pathname[i] != '.')
  3221.         i--;
  3222.     if (i)
  3223.         pathname[--i]= num+ '0';
  3224. }
  3225.  
  3226. /* get the driver path, stuff the number into the name, and create the file */
  3227. /* save the master L/R volume, the "dead" then the "live" mixer settings */
  3228. /* the bass, treble and enhanced status, the realsound setting, and the */
  3229. /* crosschannel settings */
  3230. /* These are saved as strings in a DOS file suitable for "cat FILE > mvproas" */
  3231. /* which is what the "loadcurrent()" function does */
  3232. /* The filename is "X:\driver\path\setting#.pas", where "#" is 0-3, allowing */
  3233. /* four different settings to be maintained */
  3234.  
  3235. #define USEMIXERGET 1
  3236. #if USEMIXERGET
  3237. FILE *fout;
  3238.  
  3239. subsavecurrent(char *cmdstring)
  3240. {
  3241.     if (*cmdstring)
  3242.         {
  3243.         fprintf(fout, "%s\n", cmdstring);
  3244.         }
  3245.  
  3246.     return(0);
  3247. }
  3248.  
  3249. savecurrent(int num)
  3250. {
  3251.     char pathname[128];
  3252.  
  3253.     if (!getdriverpath(pathname))
  3254.         return(0);
  3255.  
  3256.     if (strlen(pathname) > 3)
  3257.         strcat(pathname, "\\");
  3258.     strcat(pathname, filename);
  3259.     putnuminname(pathname, num);
  3260.  
  3261.     fout= fopen(pathname, "w");
  3262.     if (fout == NULL)
  3263.           return(0);
  3264.  
  3265.     MixerGetSettings(subsavecurrent);
  3266.  
  3267.     fclose(fout);
  3268.  
  3269.     return(0);
  3270. }
  3271.  
  3272. #else
  3273.  
  3274. savecurrent(int num)
  3275. {
  3276.     int o, d, c, s;
  3277.     int okay;
  3278.     FILE *fout;
  3279.     char pathname[128];
  3280.     char cmdstring[128];
  3281.  
  3282.  
  3283.     if (!getdriverpath(pathname))
  3284.         return(0);
  3285.  
  3286.     if (strlen(pathname) > 3)
  3287.         strcat(pathname, "\\");
  3288.     strcat(pathname, filename);
  3289.     putnuminname(pathname, num);
  3290.  
  3291.     fout= fopen(pathname, "w");
  3292.     if (fout == NULL)
  3293.           return(0);
  3294.  
  3295.     /* get LEFT/RIGHT VOLUME */
  3296.     for (c= 0; *channel[c]; c++)
  3297.         {
  3298.         strcpy(cmdstring, words[WORD_GET]);
  3299.         strcat(cmdstring, volume[0]);
  3300.         strcat(cmdstring, channel[c]);
  3301.         strcat(cmdstring, words[WORD_LEVEL]);
  3302.         clrbuf(MVResponse, 80);
  3303.         SendTextOut(cmdstring);
  3304.         fprintf(fout, "S%s%s%s%s\n", &cmdstring[1], words[WORD_TO], MVResponse, words[WORD_PERCENT]);
  3305.         }
  3306.  
  3307.     /* get OFF/ON, INPUT/OUTPUT and LEFT/RIGHT and FM/INT/EXT/SPEAKER/MIC */
  3308.     for (o= 0; *onoff[o]; o++)
  3309.         for (d= 0; *direct[d]; d++)
  3310.             for (c= 0; *channel[c]; c++)
  3311.                 for (s= 0; *source[s]; s++)
  3312.                     {
  3313.                     char *val;
  3314.  
  3315.                     strcpy(cmdstring, words[WORD_GET]);        /* GET */
  3316.                     strcat(cmdstring, direct[d]);                /* INPUT/OUTPUT */
  3317.                     strcat(cmdstring, words[WORD_MIXER]);    /* MIXER */
  3318.                     strcat(cmdstring, channel[c]);            /* LEFT/RIGHT */
  3319.                     strcat(cmdstring, source[s]);                /* FM/INT/EXT/SPEAKER/MIC */
  3320.                     clrbuf(MVResponse, 80);                        
  3321.                     SendTextOut(cmdstring);
  3322.  
  3323.                     /* if is ON and want ON or is OFF and want OFF, print */
  3324.                     if (val= isonoroff(channel[c][0], *onoff[o]))
  3325.                         {
  3326.                         fprintf(fout, "S%s%s", &cmdstring[1], words[WORD_TO]);
  3327.                         while (!isspace(*val))
  3328.                             {
  3329.                             fputc(*val, fout);
  3330.                             val++;
  3331.                             }
  3332.                         fprintf(fout, "%s\n", words[WORD_PERCENT]);
  3333.                         }
  3334.                     }
  3335.  
  3336.     /* get ON/OFF, INPUT/OUTPUT for PCM/INPUT */
  3337.     for (o= 0; *onoff[o]; o++)
  3338.         for (d= 0; *direct[d]; d++)
  3339.             for (c= 0; *channel[c]; c++)
  3340.                 {
  3341.                 char *val;
  3342.  
  3343.                 strcpy(cmdstring, words[WORD_GET]);
  3344.                 strcat(cmdstring, direct[d]);
  3345.                 strcat(cmdstring, words[WORD_MIXER]);
  3346.                 strcat(cmdstring, channel[c]);
  3347.                 strcat(cmdstring, output[d]);
  3348.                 clrbuf(MVResponse, 80);
  3349.                 SendTextOut(cmdstring);
  3350.  
  3351.                 if (val= isonoroff(channel[c][0], *onoff[o]))
  3352.                     {
  3353.                     fprintf(fout, "S%s%s", &cmdstring[1], words[WORD_TO]);
  3354.                     while (!isspace(*val))
  3355.                         {
  3356.                         fputc(*val, fout);
  3357.                         val++;
  3358.                         }
  3359.                     fprintf(fout, "%s\n", words[WORD_PERCENT]);
  3360.                     }
  3361.                 }
  3362.  
  3363.     /* get BASS/TREBLE/ENHANCED */
  3364.     for (c= 0; *levels[c]; c++)
  3365.         {
  3366.         strcpy(cmdstring, words[WORD_GET]);
  3367.         strcat(cmdstring, volume[0]);
  3368.         strcat(cmdstring, levels[c]);
  3369.         clrbuf(MVResponse, 80);
  3370.         SendTextOut(cmdstring);
  3371.         fprintf(fout, "S%s%s", &cmdstring[1], words[WORD_TO]);
  3372.         switch (*MVResponse)
  3373.             {
  3374.             case '+': fprintf(fout, "%s\n", words[WORD_ON]); break;
  3375.             case '-': fprintf(fout, "%s\n", words[WORD_OFF]); break;
  3376.             default: fprintf(fout, "%s%s\n", MVResponse, words[WORD_PERCENT]);
  3377.             }
  3378.         }
  3379.  
  3380.     /* get REALSOUND */
  3381.     for (c= 0; *buttons[c]; c++)
  3382.         {
  3383.         strcpy(cmdstring, words[WORD_GET]);
  3384.         strcat(cmdstring, buttons[c]);
  3385.         clrbuf(MVResponse, 80);
  3386.         SendTextOut(cmdstring);
  3387.         fprintf(fout, "S%s%s", &cmdstring[1], words[WORD_TO]);
  3388.         switch(*MVResponse)
  3389.             {
  3390.             case '+': fprintf(fout, "%s\n", words[WORD_ON]); break;
  3391.             case '-': fprintf(fout, "%s\n", words[WORD_OFF]); break;
  3392.             }
  3393.         }
  3394.  
  3395.     strcpy(cmdstring, words[WORD_GET]);
  3396.     strcat(cmdstring, crossch[0]);
  3397.     clrbuf(MVResponse, 80);
  3398.     SendTextOut(cmdstring);
  3399.         {
  3400.         int s= 0;
  3401.         int t= 0;
  3402.         int i= 0;
  3403.  
  3404.         for (s= 0; *channel[s]; s++)
  3405.             for (t= 0; *channel[t]; t++)
  3406.                 {
  3407.                 fprintf(fout, "S%s%s%s%s%s", &cmdstring[1], channel[s], words[WORD_TO], channel[t], words[WORD_TO]);
  3408.                 while (isspace(MVResponse[i])) i++;
  3409.                 switch (MVResponse[i++])
  3410.                     {
  3411.                     case '+': fprintf(fout, "%s\n", words[WORD_ON]); break;
  3412.                     case '-': fprintf(fout, "%s\n", words[WORD_OFF]); break;
  3413.                     }
  3414.                 }
  3415.         }
  3416.  
  3417.     fclose(fout);
  3418.  
  3419. }
  3420.  
  3421. #endif
  3422.  
  3423. /* load setting #num from file "setting#.pas" */
  3424. /* open the file, read each line and send it to mvproas */
  3425. /* if the file does not exist, save the current settings and then proceed */
  3426. /* The file contains mvproas strings, so "cat setting#.pas > mvproas" works */
  3427.  
  3428. loadcurrent(int num)
  3429. {
  3430.     int okay;
  3431.     FILE *finp;
  3432.     char pathname[128];
  3433.     char cmdstring[128];
  3434.  
  3435.     if (!getdriverpath(pathname))
  3436.         return(0);
  3437.  
  3438.     if (strlen(pathname) > 3)
  3439.         strcat(pathname, "\\");
  3440.     strcat(pathname, filename);
  3441.     putnuminname(pathname, num);
  3442.  
  3443.     finp= fopen(pathname, "r");
  3444.     if (finp == NULL)
  3445.         {
  3446.         savecurrent(num);
  3447.         finp= fopen(pathname, "r");
  3448.         if (finp == NULL)
  3449.             return(0);
  3450.         }
  3451.  
  3452.     while ((fgets(cmdstring, 127, finp)) != NULL)
  3453.         SendTextOut(cmdstring);
  3454.  
  3455.     fclose(finp);
  3456.  
  3457. }
  3458.  
  3459. /*The GET commands and parameters are:
  3460.        GET {LEFT or RIGHT} [FM     ]
  3461.        GET {LEFT or RIGHT} [PCM    ]
  3462.        GET {LEFT or RIGHT} [INT    ]
  3463.        GET {LEFT or RIGHT} [EXT    ]
  3464.        GET {LEFT or RIGHT} [SPEAKER]
  3465.        GET {LEFT or RIGHT} [MIC    ]
  3466.        GET [BASS]                   
  3467.        GET [TREBLE]                 
  3468.        GET {LEFT or RIGHT} [VOLUME ]
  3469.        GET [MUTE]
  3470.        GET [ENHANCED]
  3471.        GET [REALSOUND]
  3472.        GET [CROSSCHANNEL]
  3473. The following demonstrates several ways to GET volume, button, or mixer levels:
  3474.        GET FM
  3475.        GET VOLUME
  3476.        GET MUTE
  3477.        GET CROSSCHANNEL
  3478.        GET REAL
  3479. */
  3480.  
  3481.