home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1998 #5 / AmigaPlus_CD-ROM_Nr.5-98.iso / pd / musik / playmf / fireworks / source / fireworks.c < prev    next >
C/C++ Source or Header  |  1998-04-05  |  68KB  |  2,870 lines

  1.  
  2. /*-------------------------------------------------*/
  3. /* fireworks.c - graphical MIDI note visualisation */
  4. /*          ® 1998 by Christian Buchner            */
  5. /*-------------------------------------------------*/
  6.  
  7. #include "fireworks.h"
  8. #include "fireworks_protos.h"
  9. #include "fwmodes.h"
  10.  
  11. #define PREF_VERSION 1
  12.  
  13.  
  14. struct Task *MyTask;    /* this task */
  15. BOOL WBMode = FALSE;    /* Workbench or not? */
  16.  
  17.                         /* for MIDI timestamping */
  18. extern struct EClockVal stampeclock;
  19.  
  20.                         /* Globals for Watchdog timer */
  21.                         /* (from timer.c) */
  22.  
  23. extern struct Interrupt VertBlank;
  24. extern BOOL Watch;
  25. extern ULONG IdleCount;
  26.  
  27.  
  28.  
  29. /* Function Prototypes */
  30.  
  31. LONG ShellInterface(void);
  32. LONG WBInterface(struct Process *MyProc);
  33.  
  34. BOOL WindowLayout(struct Globals *glob, WORD *minw, WORD *minh, WORD *maxw, WORD *maxh);
  35.  
  36. LONG Fireworks(struct Prefs *pref);
  37. void MainLoop(struct Globals *glob, struct Prefs *pref);
  38.  
  39. BOOL OpenGUI(struct Globals *glob, struct Prefs *pref);
  40. void TitleWindow(struct Globals *glob, UBYTE *Text, ...);
  41. BOOL SelectScreenMode(struct Globals *glob, struct Prefs *pref, struct ScreenModeRequester **srq);
  42. void CloseGUI(struct Globals *glob, struct Prefs *pref);
  43.  
  44. void InitPrefs(struct Prefs *pref);
  45. BOOL LoadPrefs(struct Prefs *pref);
  46. BOOL SavePrefs(struct Globals *glob, struct Prefs *pref, UBYTE *EnvName);
  47.  
  48. void InitGlobals(struct Globals *glob);
  49.  
  50. void AsyncSelectMIDILink(struct Globals *glob, struct Prefs *pref);
  51. void AsyncSelectScreenMode(struct Globals *glob, struct Prefs *pref);
  52. void AsyncSelectImage(struct Globals *glob, struct Prefs *pref);
  53. void AsyncSelectAndPlay(struct Globals *glob, struct Prefs *pref);
  54.  
  55. BOOL InitOrUpdateGraphics(struct Globals *glob, struct Prefs *pref);
  56. void FreeGraphics(struct Globals *glob);
  57. struct Screen *GetScreen(struct Globals *glob);
  58.  
  59. void LoadImage(struct Globals *glob, struct Prefs *pref);
  60. BOOL SelectImage(struct Globals *glob, struct Prefs *pref, struct FileRequester **fr, UBYTE *filebuffer, ULONG MaxSize);
  61.  
  62. BOOL SelectMIDI(struct Globals *glob, struct Prefs *pref, struct FileRequester **fr, UBYTE *filebuffer, ULONG MaxSize);
  63. void PlayMIDI(struct Globals *glob, struct Prefs *pref);
  64. void StopMIDI(struct Globals *glob, struct Prefs *pref);
  65.  
  66.  
  67.  
  68. /* Palette and Sprite data structures */
  69.  
  70. ULONG ScreenPalette[] =
  71. {
  72.     ((2L<<16) | 0),
  73.     
  74.     0x00000000, 0x00000000, 0x00000000,
  75.     0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA,
  76.     
  77.     ((0L<<16) | 0)
  78. };
  79.  
  80.  
  81. UWORD PenArray[] =
  82. {
  83.     1, // DETAILPEN
  84.     0, // BLOCKPEN
  85.     1, // TEXTPEN
  86.     1, // SHINEPEN
  87.     1, // SHADOWPEN
  88.     1, // FILLPEN
  89.     0, // FILLTEXTPEN
  90.     0, // BACKGROUNDPEN
  91.     1, // HIGHLIGHTTEXTPEN
  92.     1, // BARDETAILPEN
  93.     0, // BARBLOCKPEN
  94.     0, // BARTRIMPEN
  95. };
  96.  
  97.  
  98. UBYTE PenColors[NUMPENS][3] =
  99. {
  100.     0x00, 0x00, 0x00,            /* Black background */
  101.     0xff, 0xff, 0xff,            /* white sparks/glitter */
  102.     
  103.     255,  64,  64,            /* Chan  1 */
  104.     255, 137,  64,            /* Chan  2 */
  105.     255, 207,  64,            /* Chan  3 */
  106.     230, 255,  64,            /* Chan  4 */
  107.     159, 255,  64,            /* Chan  5 */
  108.      86, 255,  64,            /* Chan  6 */
  109.      64, 255, 112,            /* Chan  7 */
  110.      64, 255, 185,            /* Chan  8 */
  111.      64, 255, 255,            /* Chan  9 */
  112.      64, 185, 255,            /* Chan 10 */
  113.      64, 112, 255,            /* Chan 11 */
  114.      86,  64, 255,            /* Chan 12 */
  115.     159,  64, 255,            /* Chan 13 */
  116.     230,  64, 255,            /* Chan 14 */
  117.     255,  64, 207,            /* Chan 15 */
  118.     255,  64, 137,            /* Chan 16 */
  119. };
  120.  
  121.  
  122. UWORD chip WaitPointer[] =
  123. {
  124.     0x0000, 0x0000,
  125.  
  126.     0x0400, 0x07C0,
  127.     0x0000, 0x07C0,
  128.     0x0100, 0x0380,
  129.     0x0000, 0x07E0,
  130.     0x07C0, 0x1FF8,
  131.     0x1FF0, 0x3FEC,
  132.     0x3FF8, 0x7FDE,
  133.     0x3FF8, 0x7FBE,
  134.     0x7FFC, 0xFF7F,
  135.     0x7EFC, 0xFFFF,
  136.     0x7FFC, 0xFFFF,
  137.     0x3FF8, 0x7FFE,
  138.     0x3FF8, 0x7FFE,
  139.     0x1FF0, 0x3FFC,
  140.     0x07C0, 0x1FF8,
  141.     0x0000, 0x07E0,
  142.  
  143.     0x0000, 0x0000,        /* reserved, must be NULL */
  144. };
  145.  
  146. UWORD chip NoPointer[] =
  147. {
  148.     0x0000, 0x0000,
  149.  
  150.     0x0000, 0x0000,
  151.     0x0000, 0x0000,
  152.     0x0000, 0x0000,
  153.     0x0000, 0x0000,
  154.     0x0000, 0x0000,
  155.     0x0000, 0x0000,
  156.     0x0000, 0x0000,
  157.     0x0000, 0x0000,
  158.     0x0000, 0x0000,
  159.     0x0000, 0x0000,
  160.     0x0000, 0x0000,
  161.     0x0000, 0x0000,
  162.     0x0000, 0x0000,
  163.     0x0000, 0x0000,
  164.     0x0000, 0x0000,
  165.     0x0000, 0x0000,
  166.  
  167.     0x0000, 0x0000,        /* reserved, must be NULL */
  168. };
  169.  
  170.  
  171. /* Array of random numbers (0 or 1) */
  172.  
  173. UBYTE randomarray33[256];
  174.  
  175.  
  176. /* Some defines */
  177.  
  178. /* the opposite of noteon() */
  179. #define noteoff(m) ( voicemsg(m,MS_NoteOff) || (voicemsg(m,MS_NoteOn) && (!(m)->mm_Data2)) )
  180.  
  181. #define offsetof(s, m)  (size_t)(&(((s *)0)->m))
  182. #define MIN(a,b)    ((a) <= (b) ? (a) : (b))
  183. #define elementsof(a)  ((sizeof(a) / sizeof(a[0])))
  184.  
  185.  
  186. /* Intuition Menu structures */
  187.  
  188. enum
  189. {
  190.     Menu_Ignore1,
  191.     Menu_Link,
  192.     Menu_Hooks,
  193.     Menu_Save,
  194.     Menu_Ignore2,
  195.     Menu_About,
  196.     Menu_Ignore3,
  197.     Menu_Quit,
  198.     Menu_Ignore4,
  199.     Menu_Kill,
  200.     Menu_Load,
  201.     Menu_Tile,
  202.     Menu_Ignore5,
  203.     Menu_Screenmode,
  204.     Menu_Fullscreen,
  205.     Menu_Titlebar,
  206.     Menu_Mouse,
  207.     Menu_Ignore6,
  208.     Menu_Mode1,
  209.     Menu_Mode2,
  210.     Menu_Mode3,
  211.     Menu_Ignore7,
  212.     Menu_Sens1,
  213.     Menu_Sens2,
  214.     Menu_Sens3,
  215.     Menu_Ignore8,
  216.     Menu_Double,
  217.     Menu_Sparks,
  218.     Menu_Ignore9,
  219.     Menu_Release,
  220.     Menu_Ignore10,
  221.     Menu_Play,
  222.     Menu_Stop,
  223.     Menu_Ignore11,
  224.     Menu_Init1,
  225.     Menu_Init2,
  226.     Menu_Init3,
  227.     Menu_Init4,
  228.     Menu_Init5,
  229.     Menu_Ignore12,
  230.     Menu_Timestamp,
  231.     Menu_Ignore13,
  232. };
  233.  
  234.  
  235. #define M1 (1<<0)
  236. #define M2 (1<<1)
  237. #define M3 (1<<2)
  238.  
  239. #define S1 (1<<4)
  240. #define S2 (1<<5)
  241. #define S3 (1<<6)
  242.  
  243. #define I1 (1<<5)
  244. #define I2 (1<<6)
  245. #define I3 (1<<7)
  246. #define I4 (1<<8)
  247. #define I5 (1<<9)
  248.  
  249. struct NewMenu FWNewMenu[]=
  250. {
  251.     /* nm_Type    nm_Label            nm_CommKey    nm_Flags            nm_MutualExclude    nm_UserData */
  252.     NM_TITLE,    "Project",            NULL,        0,                    0,                    (APTR)Menu_Ignore1,
  253.     NM_ITEM,    "MIDI Link...",        "L",        0,                    0,                    (APTR)Menu_Link,
  254.     NM_ITEM,    "ASL Hooks",        "A",        CHECKIT|MENUTOGGLE,    0,                    (APTR)Menu_Hooks,
  255.     NM_ITEM,    "Save Config",        "C",        0,                    0,                    (APTR)Menu_Save,
  256.     NM_ITEM,    NM_BARLABEL,        NULL,        0,                    0,                    (APTR)Menu_Ignore2,
  257.     NM_ITEM,    "About",            "?",        0,                    0,                    (APTR)Menu_About,
  258.     NM_ITEM,    NM_BARLABEL,        NULL,        0,                    0,                    (APTR)Menu_Ignore3,
  259.     NM_ITEM,    "Quit",                "Q",        0,                    0,                    (APTR)Menu_Quit,
  260.     NM_TITLE,    "Window",            NULL,        0,                    0,                    (APTR)Menu_Ignore4,
  261.     NM_ITEM,    "Remove Backdrop",    "R",        0,                    0,                    (APTR)Menu_Kill,
  262.     NM_ITEM,    "Load Backdrop...",    "B",        0,                    0,                    (APTR)Menu_Load,
  263.     NM_ITEM,    "Tile Backdrop",    "T",        CHECKIT|MENUTOGGLE,    0,                    (APTR)Menu_Tile,
  264.     NM_ITEM,    NM_BARLABEL,        NULL,        0,                    0,                    (APTR)Menu_Ignore5,
  265.     NM_ITEM,    "Set Screenmode...","M",        0,                    0,                    (APTR)Menu_Screenmode,
  266.     NM_ITEM,    "Full Screen",        "F",        CHECKIT|MENUTOGGLE,    0,                    (APTR)Menu_Fullscreen,
  267.     NM_ITEM,    "Hide Titlebar",    "H",        CHECKIT|MENUTOGGLE,    0,                    (APTR)Menu_Titlebar,
  268.     NM_ITEM,    "Hide Mouseptr",    "I",        CHECKIT|MENUTOGGLE,    0,                    (APTR)Menu_Mouse,
  269.     NM_TITLE,    "Rendering",        NULL,        0,                    0,                    (APTR)Menu_Ignore6,
  270.     NM_ITEM,    "Laser Mode",        "1",        CHECKIT,            (   M2|M3),            (APTR)Menu_Mode1,
  271.     NM_ITEM,    "Pixel Mode",        "2",        CHECKIT,            (M1|   M3),            (APTR)Menu_Mode2,
  272.     NM_ITEM,    "Fountain Mode",    "3",        CHECKIT,            (M1|M2   ),            (APTR)Menu_Mode3,
  273.     NM_ITEM,    NM_BARLABEL,        NULL,        0,                    0,                    (APTR)Menu_Ignore7,
  274.     NM_ITEM,    "Sensitivity Max",    "X",        CHECKIT,            (   S2|S3),            (APTR)Menu_Sens1,
  275.     NM_ITEM,    "Sensitivity Med",    "Y",        CHECKIT,            (S1|   S3),            (APTR)Menu_Sens2,
  276.     NM_ITEM,    "Sensitivity Low",    "Z",        CHECKIT,            (S1|S2   ),            (APTR)Menu_Sens3,
  277.     NM_ITEM,    NM_BARLABEL,        NULL,        0,                    0,                    (APTR)Menu_Ignore8,
  278.     NM_ITEM,    "Double Strength",    "D",        CHECKIT|MENUTOGGLE,    0,                    (APTR)Menu_Double,
  279.     NM_ITEM,    "Sparks",            "+",        CHECKIT|MENUTOGGLE,    0,                    (APTR)Menu_Sparks,
  280.     NM_TITLE,    "MIDI",                NULL,        0,                    0,                    (APTR)Menu_Ignore9,
  281.     NM_ITEM,    "Release Notes",    "N",        0,                    0,                    (APTR)Menu_Release,
  282.     NM_ITEM,    NM_BARLABEL,        NULL,        0,                    0,                    (APTR)Menu_Ignore10,
  283.     NM_ITEM,    "Play MIDI file...","P",        0,                    0,                    (APTR)Menu_Play,
  284.     NM_ITEM,    "Stop playing",        "S",        0,                    0,                    (APTR)Menu_Stop,
  285.     NM_ITEM,    NM_BARLABEL,        NULL,        0,                    0,                    (APTR)Menu_Ignore11,
  286.     NM_ITEM,    "Normal Init",        NULL,        CHECKIT,            (   I2|I3|I4|I5),    (APTR)Menu_Init1,
  287.     NM_ITEM,    "GM Reset",            NULL,        CHECKIT,            (I1|   I3|I4|I5),    (APTR)Menu_Init2,
  288.     NM_ITEM,    "GS Reset",            NULL,        CHECKIT,            (I1|I2|   I4|I5),    (APTR)Menu_Init3,
  289.     NM_ITEM,    "XG Reset",            NULL,        CHECKIT,            (I1|I2|I3   |I5),    (APTR)Menu_Init4,
  290.     NM_ITEM,    "MT32 Emu",            NULL,        CHECKIT,            (I1|I2|I3|I4   ),    (APTR)Menu_Init5,
  291.     NM_ITEM,    NM_BARLABEL,        NULL,        0,                    0,                    (APTR)Menu_Ignore12,
  292.     NM_ITEM,    "Timestamping",        "E",        CHECKIT|MENUTOGGLE,    0,                    (APTR)Menu_Timestamp,
  293.     NM_END,        NULL,                NULL,        0,                    0,                    (APTR)Menu_Ignore13,
  294. };
  295.  
  296.  
  297.  
  298.  
  299. /*--------------*/
  300. /* Startup code */
  301. /*--------------*/
  302.  
  303. LONG __saveds mymain(void)
  304. {
  305.     LONG ReturnCode;
  306.     
  307.     struct    Process *MyProc;
  308.     
  309.     SysBase = *((struct ExecBase**)(0x4));
  310.     
  311.     MyProc = (struct Process*) FindTask(NULL);
  312.     
  313.     if (!MyProc->pr_CLI)
  314.     {
  315.         WBMode = TRUE;
  316.         ReturnCode = WBInterface(MyProc);
  317.     }
  318.     else
  319.     {
  320.         ReturnCode = ShellInterface();
  321.     }
  322.     
  323.     return(ReturnCode);
  324. }
  325.  
  326.  
  327.  
  328. /*---------------------*/
  329. /* Workbench Interface */
  330. /*---------------------*/
  331.  
  332. LONG WBInterface(struct Process *MyProc)
  333. {
  334.     struct WBStartup *wbmsg;
  335.     
  336.     LONG ReturnCode = RETURN_ERROR;
  337.     
  338.     WaitPort(&MyProc->pr_MsgPort);
  339.     
  340.     if (wbmsg = (struct WBStartup*)GetMsg(&MyProc->pr_MsgPort))
  341.     {
  342.         if (OpenLibs())
  343.         {
  344.             BPTR OldDir;
  345.             struct Prefs *pref;
  346.             
  347.             OldDir = CurrentDir(wbmsg->sm_ArgList->wa_Lock);
  348.             
  349.             if (!(pref = AllocVec(sizeof(struct Prefs),MEMF_ANY|MEMF_CLEAR)))
  350.             {
  351.                 Message("No memory for prefs!",NULL);
  352.             }
  353.             else
  354.             {
  355.                 InitPrefs(pref);
  356.                 LoadPrefs(pref);
  357.                 
  358.                 ReturnCode = Fireworks(pref);
  359.                 
  360.                 FreeVec(pref);
  361.             }
  362.             
  363.             CurrentDir(OldDir);
  364.             
  365.             CloseLibs();
  366.         }
  367.         Forbid();
  368.         ReplyMsg((struct Message*)wbmsg);
  369.     }
  370.     return(ReturnCode);
  371. }
  372.  
  373.  
  374.  
  375. /*-----------------*/
  376. /* Shell Interface */
  377. /*-----------------*/
  378.  
  379. LONG  ShellInterface(void)
  380. {
  381.     LONG ReturnCode = RETURN_ERROR;
  382.     BPTR lock;
  383.     BPTR OldDir;
  384.     
  385.     if (OpenLibs())
  386.     {
  387.         if (!(lock = Lock("PROGDIR:", SHARED_LOCK)))
  388.         {
  389.             Message("Unable to locate program directory.",NULL);
  390.         }
  391.         else
  392.         {
  393.             /* CLI argument parsing */
  394.             
  395.             struct    ArgArray
  396.             {
  397.                 UBYTE *aa_Link;
  398.                 ULONG *aa_Mode;
  399.                 ULONG *aa_Sensitivity;
  400.                 ULONG *aa_WinX;
  401.                 ULONG *aa_WinY;
  402.                 ULONG *aa_WinW;
  403.                 ULONG *aa_WinH;
  404.                 UBYTE *aa_Image;
  405.                 ULONG  aa_Tile;
  406.                 ULONG  aa_Fullscreen;
  407.                 ULONG  aa_Double;
  408.                 ULONG  aa_Sparks;
  409.                 ULONG  aa_GM;
  410.                 ULONG  aa_GS;
  411.                 ULONG  aa_XG;
  412.                 ULONG  aa_MT32;
  413.                 ULONG  aa_NoHooks;
  414.                 ULONG  aa_NoTS;
  415.             } AA;
  416.             
  417.             static UBYTE    *Template = "L=LINK/K,M=MODE/K/N,S=SENSITIVITY/K/N,WX=WINX/K/N,WY=WINY/K/N,WW=WINW/K/N,WH=WINH/K/N,I=IMAGE/K,T=TILE/S,FS=FULLSCREEN/S,D=DOUBLE/S,SP=SPARKS/S,GM/S,GS/S,XG/S,MT32/S,NH=NOHOOKS/S,NTS=NOTIMESTAMPING/S";
  418.             struct RDArgs *RDArgs;
  419.             
  420.             struct Prefs *pref;
  421.             
  422.             ReturnCode = RETURN_FAIL;
  423.             
  424.             OldDir = CurrentDir(lock);
  425.             
  426.             if (!(pref = AllocVec(sizeof(struct Prefs),MEMF_ANY|MEMF_CLEAR)))
  427.             {
  428.                 Message("No memory for prefs!",NULL);
  429.             }
  430.             else
  431.             {
  432.                 InitPrefs(pref);
  433.                 LoadPrefs(pref);
  434.                 
  435.                 memset(&AA, 0, sizeof(struct ArgArray));
  436.                 if (RDArgs=ReadArgs(Template, (LONG *)&AA, 0))
  437.                 {
  438.                     BOOL fault = FALSE;
  439.                     UWORD opts;
  440.                     
  441.                     if (AA.aa_Link)
  442.                     {
  443.                         strncpy(pref->Link, AA.aa_Link, sizeof(pref->Link));
  444.                         pref->Link[sizeof(pref->Link)-1] = 0;
  445.                     }
  446.                     if (AA.aa_Mode)
  447.                     {
  448.                         LONG mode = (*AA.aa_Mode) - 1;
  449.                         if (mode >=0 && mode < NUM_FWMODES) pref->FWMode = mode;
  450.                         else
  451.                             Message("Mode out of range! There are currently modes 1-%ld available.", NULL, NUM_FWMODES);
  452.                             fault = TRUE;
  453.                     }
  454.                     if (AA.aa_Sensitivity)
  455.                     {
  456.                         LONG sens = (*AA.aa_Sensitivity);
  457.                         switch(sens)
  458.                         {
  459.                             case 1: pref->Sensitivity=100; break;
  460.                             case 2: pref->Sensitivity= 75; break;
  461.                             case 3: pref->Sensitivity= 50; break;
  462.                             default:
  463.                                 Message("Sensitivity out of range! Allowed range is 1-3.", NULL);
  464.                                 fault = TRUE;
  465.                                 break;
  466.                         }
  467.                     }
  468.                     if (AA.aa_WinX) pref->WinX= *AA.aa_WinX;
  469.                     if (AA.aa_WinY) pref->WinY= *AA.aa_WinY;
  470.                     if (AA.aa_WinW) pref->WinW= *AA.aa_WinW;
  471.                     if (AA.aa_WinH) pref->WinH= *AA.aa_WinH;
  472.                     if (AA.aa_Image)
  473.                     {
  474.                         strncpy(pref->Image, AA.aa_Image, sizeof(pref->Image));
  475.                         pref->Image[sizeof(pref->Image)-1] = 0;
  476.                     }
  477.                     if (AA.aa_Tile) pref->Flags |= PREFF_TILE;
  478.                     if (AA.aa_Fullscreen) pref->Flags |= PREFF_FULLSCREEN;
  479.                     if (AA.aa_Double) pref->Flags |= PREFF_DOUBLE;
  480.                     if (AA.aa_Sparks) pref->Flags |= PREFF_SPARKS;
  481.                     if (AA.aa_NoHooks) pref->Flags &= ~(PREFF_ASLHOOKS);
  482.                     if (AA.aa_NoTS) pref->Flags &= ~(PREFF_TIMESTAMP);
  483.                     
  484.                     opts = 0;
  485.                     if (AA.aa_GM  ) {opts++; pref->Flags |= PREFF_GM  ;};
  486.                     if (AA.aa_GS  ) {opts++; pref->Flags |= PREFF_GS  ;};
  487.                     if (AA.aa_XG  ) {opts++; pref->Flags |= PREFF_XG  ;};
  488.                     if (AA.aa_MT32) {opts++; pref->Flags |= PREFF_MT32;};
  489.                     if (opts>1)
  490.                     {
  491.                         Message("Please specify only one of GM, GS, XG and MT32.", NULL);
  492.                         fault = TRUE;
  493.                     }
  494.                     
  495.                     if (!fault)
  496.                     {
  497.                         ReturnCode = Fireworks(pref);
  498.                     }
  499.                     
  500.                     FreeArgs(RDArgs);
  501.                 }
  502.                 else
  503.                 {
  504.                     PrintFault(IoErr(),"Fireworks");
  505.                 }
  506.                 
  507.                 FreeVec(pref);
  508.             }
  509.             
  510.             CurrentDir(OldDir);
  511.             
  512.             UnLock(lock);
  513.         }
  514.         CloseLibs();
  515.     }
  516.     return(ReturnCode);
  517. }
  518.  
  519.  
  520.  
  521. /*-----------------------------*/
  522. /* GUI and MIDI initialisation */
  523. /*-----------------------------*/
  524.  
  525. LONG Fireworks(struct Prefs *pref)
  526. {
  527.     LONG ReturnCode = RETURN_FAIL;
  528.     
  529.     struct Globals *glob;
  530.     
  531.     BYTE OldPri;
  532.     
  533.     MyTask = FindTask(NULL);
  534.     
  535.     if (!(glob = AllocVec(sizeof(struct Globals), MEMF_ANY|MEMF_CLEAR)))
  536.     {
  537.         Message("No memory for globals!",NULL);
  538.     }
  539.     else
  540.     {
  541.         InitGlobals(glob);
  542.         
  543.         if (OpenGUI(glob,pref))
  544.         {
  545.             if (!((glob->NotePool = CreatePool(MEMF_ANY,8192,4096))))
  546.             {
  547.                 Message("No memory for NotePool!",NULL);
  548.             }
  549.             else
  550.             {
  551.                 if (!(glob->midi = CreateMidi(
  552.                     MIDI_Name, "Fireworks",
  553.                     MIDI_TimeStamp, &stampeclock.ev_lo,
  554.                     MIDI_RecvSignal, SIGBREAKB_CTRL_E,
  555.                     MIDI_MsgQueue,   2000,
  556.                     MIDI_ErrFilter, CMEF_All,
  557.                     TAG_DONE)))
  558.                 {
  559.                     Message("Cannot create MIDI port!",NULL);
  560.                 }
  561.                 else
  562.                 {
  563.                     if (!(glob->link = AddMidiLink(glob->midi, MLTYPE_Receiver,
  564.                         MLINK_Name, "Fireworks Link",
  565.                         MLINK_Location, pref->Link,
  566.                         MLINK_EventMask, CMF_Note|CMF_Mode,
  567.                         MLINK_Comment,  "Fireworks [Input]",
  568.                         TAG_DONE)))
  569.                     {
  570.                         Message("Cannot create link to MIDI interface '%s'",NULL,pref->Link);
  571.                     }
  572.                     else
  573.                     {
  574.                         TitleWindow(glob, "Fireworks [%s] [idle]", pref->Link);
  575.                         
  576.                         if (!(glob->treq = OpenTimer()))
  577.                         {
  578.                             
  579.                         }
  580.                         else
  581.                         {
  582.                             OldPri = MyTask->tc_Node.ln_Pri;
  583.                             
  584.                             MainLoop(glob, pref);
  585.                             
  586.                             WaitAsync(glob);
  587.                             
  588.                             ReturnCode = RETURN_OK;
  589.                             
  590.                             SetTaskPri(MyTask, OldPri);
  591.                             
  592.                             CloseTimer(glob->treq);
  593.                             glob->treq=NULL;
  594.                         }
  595.                         RemoveMidiLink(glob->link);
  596.                         glob->link = NULL;
  597.                     }
  598.                     DeleteMidi(glob->midi);
  599.                     glob->midi = NULL;
  600.                 }
  601.                 DeletePool(glob->NotePool);
  602.                 glob->NotePool = NULL;
  603.             }
  604.             CloseGUI(glob, pref);
  605.         }
  606.         
  607.         if (glob->ImageFR)
  608.         {
  609.             FreeAslRequest(glob->ImageFR);
  610.             glob->ImageFR = NULL;
  611.         }
  612.         
  613.         if (glob->MIDIFR)
  614.         {
  615.             FreeAslRequest(glob->MIDIFR);
  616.             glob->MIDIFR = NULL;
  617.         }
  618.         
  619.         if (glob->ScreenModeRQ)
  620.         {
  621.             FreeAslRequest(glob->ScreenModeRQ);
  622.             glob->ScreenModeRQ = NULL;
  623.         }
  624.         
  625.         FreeVec(glob);
  626.     }
  627.     return(ReturnCode);
  628. }
  629.  
  630.  
  631.  
  632. /*--------------------*/
  633. /* Set Prefs defaults */
  634. /*--------------------*/
  635.  
  636. void InitPrefs(struct Prefs *pref)
  637. {
  638.     memset(pref, 0, sizeof(struct Prefs));
  639.     strcpy(pref->Header, "Fireworks");
  640.     pref->Version = PREF_VERSION;
  641.     strcpy(pref->Link,"out.0");
  642.     pref->FWMode = ParabolicMode2;
  643.     pref->Sensitivity = 100;
  644.     pref->Flags = PREFF_BACKDROP | PREFF_ASLHOOKS | PREFF_TIMESTAMP;
  645.     pref->WinX = 100;
  646.     pref->WinY = 200;
  647.     pref->WinW = 256;
  648.     pref->WinH = 256;
  649.     strcpy(pref->Image,"PROGDIR:Backdrop.Pic");
  650.     pref->ScreenMode = -1L;
  651.     pref->AutoScroll = FALSE;
  652. }
  653.  
  654.  
  655. /*------------*/
  656. /* Load Prefs */
  657. /*------------*/
  658.  
  659. BOOL LoadPrefs(struct Prefs *pref)
  660. {
  661.     BOOL Success = FALSE;
  662.     UBYTE *name = "ENV:MIDI/Fireworks.prefs";
  663.     BPTR file;
  664.     
  665.     if (file = Open(name, MODE_OLDFILE))
  666.     {
  667.         if (Read(file, pref, sizeof(struct Prefs)) != -1)
  668.         {
  669.             if (stricmp(pref->Header, "Fireworks"))
  670.             {
  671.                 Message("'%s' is not a Fireworks preferences file. Using defaults.", NULL, name);
  672.             }
  673.             else
  674.             {
  675.                 if (pref->Version != PREF_VERSION)
  676.                 {
  677.                     Message("'%s' preferences version is not supported. Using defaults.", NULL, name);
  678.                 }
  679.                 else
  680.                 {
  681.                     Success = TRUE;
  682.                 }
  683.             }
  684.         }
  685.         if (!Success) InitPrefs(pref);
  686.         
  687.         Close(file);
  688.     }
  689.     return(Success);
  690. }
  691.  
  692.  
  693. /*------------*/
  694. /* Save Prefs */
  695. /*------------*/
  696.  
  697. BOOL SavePrefs(struct Globals *glob, struct Prefs *pref, UBYTE *EnvName)
  698. {
  699.     BOOL Success = FALSE;
  700.     BPTR OldDir=NULL;
  701.     BPTR EnvLock=NULL;
  702.     BPTR MIDILock=NULL;
  703.     BPTR FH;
  704.     UBYTE *FileName = "Fireworks.prefs";
  705.     UBYTE *MIDIName = "MIDI";
  706.     
  707.     pref->WinX = glob->Window->LeftEdge;
  708.     pref->WinY = glob->Window->TopEdge;
  709.     pref->WinW = glob->ww;
  710.     pref->WinH = glob->wh;
  711.     
  712.     if (EnvLock=Lock(EnvName,ACCESS_READ))
  713.     {
  714.         OldDir=CurrentDir(EnvLock);
  715.         
  716.         if (!(MIDILock=Lock(MIDIName,ACCESS_READ)))
  717.         {
  718.             MIDILock=CreateDir(MIDIName);
  719.         }
  720.         if (MIDILock)
  721.         {
  722.             CurrentDir(MIDILock);
  723.             
  724.             Success=TRUE;
  725.         }
  726.     }
  727.     
  728.     if (Success)
  729.     {
  730.         Success=FALSE;
  731.         
  732.         if (FH=Open(FileName,MODE_NEWFILE))
  733.         {
  734.             if (Write(FH,pref,sizeof(struct Prefs))==sizeof(struct Prefs))
  735.             {
  736.                 Success=TRUE;
  737.             }
  738.             Close(FH);
  739.         }
  740.     }
  741.     
  742.     if (OldDir)  CurrentDir(OldDir);
  743.     if (MIDILock) UnLock(MIDILock);
  744.     if (EnvLock) UnLock(EnvLock);
  745.     
  746.     return(Success);
  747. }
  748.  
  749.  
  750.  
  751.  
  752. /*--------------------*/
  753. /* Initialize globals */
  754. /*--------------------*/
  755.  
  756. void InitGlobals(struct Globals *glob)
  757. {
  758.     UWORD i;
  759.     
  760.     for (i=0; i<NUMPENS; i++) glob->PenArray[i] = -1L;
  761. }
  762.  
  763.  
  764.  
  765. /*-------------------------------*/
  766. /* Open the GUI (Screen, Window) */
  767. /*-------------------------------*/
  768.  
  769. BOOL OpenGUI(struct Globals *glob, struct Prefs *pref)
  770. {
  771.     BOOL Success = FALSE;
  772.     
  773.     struct Screen *wbscr;
  774.     
  775.     WORD minw, minh;
  776.     WORD maxw, maxh;
  777.     
  778.     UWORD mode, sens, init;
  779.     
  780.     glob->Screen = NULL;
  781.     
  782.     if (!(glob->AppPort = CreateMsgPort()))
  783.     {
  784.         Message("Failed to create AppMsg port.", NULL);
  785.     }
  786.     else
  787.     {
  788.         if (pref->Flags & PREFF_FULLSCREEN)
  789.         {
  790.             if (pref->ScreenMode == -1L)
  791.             {
  792.                 if (!SelectScreenMode(glob, pref, &glob->ScreenModeRQ))
  793.                 {
  794.                     pref->Flags &= ~(PREFF_FULLSCREEN);
  795.                 }
  796.             }
  797.         }
  798.         
  799.         if (pref->Flags & PREFF_FULLSCREEN)
  800.         {
  801.             if (pref->ScreenMode != -1L)
  802.             {
  803.                 struct Screen *scr;
  804.                 
  805.                 /* maybe screen couldn't be closed before (visitor window) */
  806.                 if (glob->OpenedScreen) CloseScreen(glob->OpenedScreen);
  807.                 
  808.                 if (!(scr = OpenScreenTags(NULL,
  809.                     SA_DisplayID, pref->ScreenMode,
  810.                     SA_Width, (ULONG)pref->ScreenWidth,
  811.                     SA_Height, (ULONG)pref->ScreenHeight,
  812.                     SA_Depth, (ULONG)pref->ScreenDepth,
  813.                     SA_Overscan, (ULONG)pref->OverscanType,
  814.                     SA_AutoScroll, (ULONG)pref->AutoScroll,
  815.                     SA_SharePens, (ULONG)TRUE,
  816.                     SA_Interleaved, (ULONG)TRUE,
  817.                     SA_PubName, "Fireworks",
  818.                     SA_Colors32, ScreenPalette,
  819.                     SA_Pens, PenArray,
  820.                     TAG_DONE )))
  821.                 {
  822.                     Message("Unable to open selected screen!",NULL);
  823.                 }
  824.                 else
  825.                 {
  826.                     glob->Screen = glob->OpenedScreen = scr;
  827.                     
  828.                     if (glob->LockedScreen)
  829.                     {
  830.                         UnlockPubScreen(NULL, glob->LockedScreen);
  831.                         glob->LockedScreen = NULL;
  832.                     }
  833.                 }
  834.             }
  835.         }
  836.         else
  837.         {
  838.             if (!glob->LockedScreen)
  839.             {
  840.                 glob->LockedScreen = GetScreen(glob);
  841.             }
  842.             glob->Screen = glob->LockedScreen;
  843.         }
  844.         
  845.         if (glob->Screen)
  846.         {
  847.             if (!(glob->VisualInfo = GetVisualInfo(glob->Screen, TAG_DONE)))
  848.             {
  849.                 Message("No visual info!",NULL);
  850.             }
  851.             else
  852.             {
  853.                 glob->ww = pref->WinW;
  854.                 glob->wh = pref->WinH;
  855.                 
  856.                 if (!(WindowLayout(glob, &minw, &minh, &maxw, &maxh )))
  857.                 {
  858.                     Message("Couldn't layout window!",NULL);
  859.                 }
  860.                 else
  861.                 {
  862.                     if (pref->Flags & PREFF_FULLSCREEN)
  863.                     {
  864.                         ULONG height;
  865.                         ULONG BDrop;
  866.                         
  867.                         if (pref->Flags & PREFF_HDTITLEBAR)
  868.                         {
  869.                             height = pref->ScreenHeight;
  870.                             BDrop = FALSE;
  871.                         }
  872.                         else
  873.                         {
  874.                             height = pref->ScreenHeight-(glob->Screen->BarHeight+1);
  875.                             BDrop = FALSE;
  876.                         }
  877.                         
  878.                         glob->Window = OpenWindowTags( NULL,
  879.                                 WA_PubScreen, glob->Screen,
  880.                                 WA_Left, 0,
  881.                                 WA_Top, glob->Screen->BarHeight+1,
  882.                                 WA_Width, pref->ScreenWidth,
  883.                                 WA_Height, height,
  884.                                 WA_Backdrop, BDrop,
  885.                                 WA_Borderless, TRUE,
  886.                                 WA_Activate, TRUE,
  887.                                 WA_IDCMP, IDCMP_MENUPICK|IDCMP_REFRESHWINDOW,
  888.                                 WA_SimpleRefresh, TRUE,
  889.                                 WA_NewLookMenus, TRUE,
  890.                                 TAG_DONE );
  891.                     }
  892.                     else
  893.                     {
  894.                         glob->Window = OpenWindowTags( NULL,
  895.                                 WA_PubScreen, glob->Screen,
  896.                                 WA_Title, "Fireworks",
  897.                                 WA_Left, pref->WinX,
  898.                                 WA_Top, pref->WinY,
  899.                                 WA_InnerWidth, (ULONG)glob->ww,
  900.                                 WA_InnerHeight, (ULONG)glob->wh,
  901.                                 WA_GimmeZeroZero, TRUE,
  902.                                 WA_DepthGadget, TRUE,
  903.                                 WA_SizeGadget, TRUE,
  904.                                 WA_SizeBBottom, TRUE,
  905.                                 WA_CloseGadget, TRUE,
  906.                                 WA_DragBar, TRUE,
  907.                                 WA_Activate, TRUE,
  908.                                 WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_NEWSIZE|IDCMP_MENUPICK|IDCMP_REFRESHWINDOW,
  909.                                 WA_SimpleRefresh, TRUE,
  910.                                 WA_NewLookMenus, TRUE,
  911.                                 TAG_DONE );
  912.                     }
  913.                     
  914.                     if (!glob->Window)
  915.                     {
  916.                         Message("Couldn't open window!",NULL);
  917.                     }
  918.                     else
  919.                     {
  920.                         glob->ProcWindow = ((struct Process*)MyTask)->pr_WindowPtr;
  921.                         ((struct Process*)MyTask)->pr_WindowPtr = glob->Window;
  922.                         
  923.                         if ( wbscr = LockPubScreen("Workbench") )
  924.                         {
  925.                             if (glob->Screen == wbscr)
  926.                             {
  927.                                 glob->AppWindow = AddAppWindow( 1, NULL, glob->Window, glob->AppPort, TAG_DONE);
  928.                             }
  929.                             
  930.                             UnlockPubScreen( NULL, wbscr );
  931.                         }
  932.                         
  933.                         glob->ww = glob->Window->Width  - glob->Window->BorderLeft-glob->Window->BorderRight ;
  934.                         glob->wh = glob->Window->Height - glob->Window->BorderTop -glob->Window->BorderBottom;
  935.                         
  936.                         glob->Window->MinWidth  = minw + glob->Window->BorderLeft+glob->Window->BorderRight;
  937.                         glob->Window->MinHeight = minh + glob->Window->BorderTop +glob->Window->BorderBottom;
  938.                         glob->Window->MaxWidth  = maxw + glob->Window->BorderLeft+glob->Window->BorderRight;
  939.                         glob->Window->MaxHeight = maxh + glob->Window->BorderTop +glob->Window->BorderBottom;
  940.                         
  941.                         if (!(InitOrUpdateGraphics(glob,pref)))
  942.                         {
  943.                             Message("Failed to initialize graphics!",NULL);
  944.                         }
  945.                         else
  946.                         {
  947.                             BltBitMapRastPort(glob->PaintBitMap, 0, 0, glob->Window->RPort, 0, 0, glob->ww, glob->wh, 0xc0);
  948.                             
  949.                             if (pref->Flags & PREFF_BACKDROP)
  950.                                 if (pref->Image) LoadImage(glob,pref);
  951.                             
  952.                             if (pref->Flags & PREFF_ASLHOOKS)
  953.                                 FWNewMenu[Menu_Hooks].nm_Flags |= CHECKED;
  954.                             else
  955.                                 FWNewMenu[Menu_Hooks].nm_Flags &= (~CHECKED);
  956.                             
  957.                             if (pref->Flags & PREFF_TILE)
  958.                                 FWNewMenu[Menu_Tile].nm_Flags |= CHECKED;
  959.                             else
  960.                                 FWNewMenu[Menu_Tile].nm_Flags &= (~CHECKED);
  961.                             
  962.                             if (pref->Flags & PREFF_FULLSCREEN)
  963.                                 FWNewMenu[Menu_Fullscreen].nm_Flags |= CHECKED;
  964.                             else
  965.                                 FWNewMenu[Menu_Fullscreen].nm_Flags &= (~CHECKED);
  966.                             
  967.                             if (pref->Flags & PREFF_HDTITLEBAR)
  968.                                 FWNewMenu[Menu_Titlebar].nm_Flags |= CHECKED;
  969.                             else
  970.                                 FWNewMenu[Menu_Titlebar].nm_Flags &= (~CHECKED);
  971.                             
  972.                             if (pref->Flags & PREFF_HDMOUSEPTR)
  973.                                 FWNewMenu[Menu_Mouse].nm_Flags |= CHECKED;
  974.                             else
  975.                                 FWNewMenu[Menu_Mouse].nm_Flags &= (~CHECKED);
  976.                             
  977.                             if (pref->Flags & PREFF_DOUBLE)
  978.                                 FWNewMenu[Menu_Double].nm_Flags |= CHECKED;
  979.                             else
  980.                                 FWNewMenu[Menu_Double].nm_Flags &= (~CHECKED);
  981.                             
  982.                             if (pref->Flags & PREFF_SPARKS)
  983.                                 FWNewMenu[Menu_Sparks].nm_Flags |= CHECKED;
  984.                             else
  985.                                 FWNewMenu[Menu_Sparks].nm_Flags &= (~CHECKED);
  986.                             
  987.                             for (mode = 0; mode < NUM_FWMODES ; mode++)
  988.                             {
  989.                                 if (pref->FWMode == mode)
  990.                                     FWNewMenu[Menu_Mode1+mode].nm_Flags |= CHECKED;
  991.                                 else
  992.                                     FWNewMenu[Menu_Mode1+mode].nm_Flags &= (~CHECKED);
  993.                             }
  994.                             
  995.                             for (sens = 1; sens <= 3 ; sens++)
  996.                             {
  997.                                 if (((sens == 1) && (pref->Sensitivity == 100)) ||
  998.                                     ((sens == 2) && (pref->Sensitivity ==  75)) ||
  999.                                     ((sens == 3) && (pref->Sensitivity ==  50)))
  1000.                                     FWNewMenu[Menu_Sens1+sens-1].nm_Flags |= CHECKED;
  1001.                                 else
  1002.                                     FWNewMenu[Menu_Sens1+sens-1].nm_Flags &= (~CHECKED);
  1003.                             }
  1004.                             
  1005.                             for (init = 0; init <= 4 ; init++)
  1006.                             {
  1007.                                 BOOL set = FALSE;
  1008.                                 
  1009.                                 switch(init)
  1010.                                 {
  1011.                                     case 0:
  1012.                                         if (!(pref->Flags&(PREFF_GM|PREFF_GS|PREFF_XG|PREFF_MT32)))
  1013.                                             set = TRUE;
  1014.                                         break;
  1015.                                     case 1:
  1016.                                         if (pref->Flags & PREFF_GM)
  1017.                                             set = TRUE;
  1018.                                         break;
  1019.                                     case 2:
  1020.                                         if (pref->Flags & PREFF_GS)
  1021.                                             set = TRUE;
  1022.                                         break;
  1023.                                     case 3:
  1024.                                         if (pref->Flags & PREFF_XG)
  1025.                                             set = TRUE;
  1026.                                         break;
  1027.                                     case 4:
  1028.                                         if (pref->Flags & PREFF_MT32)
  1029.                                             set = TRUE;
  1030.                                         break;
  1031.                                 }
  1032.                                 
  1033.                                 if (set)
  1034.                                     FWNewMenu[Menu_Init1+init].nm_Flags |= CHECKED;
  1035.                                 else
  1036.                                     FWNewMenu[Menu_Init1+init].nm_Flags &= ~(CHECKED);
  1037.                             }
  1038.                             
  1039.                             if (pref->Flags & PREFF_TIMESTAMP)
  1040.                                 FWNewMenu[Menu_Timestamp].nm_Flags |= CHECKED;
  1041.                             else
  1042.                                 FWNewMenu[Menu_Timestamp].nm_Flags &= (~CHECKED);
  1043.                             
  1044.                             if (!(glob->Menu=(struct Menu *)CreateMenus(FWNewMenu, TAG_DONE)))
  1045.                             {
  1046.                                 Message("Failed to create intuition menu.",NULL);
  1047.                             }
  1048.                             else
  1049.                             {
  1050.                                 LayoutMenus(glob->Menu, glob->VisualInfo, GTMN_NewLookMenus, TRUE, TAG_DONE);
  1051.                                 SetMenuStrip(glob->Window, glob->Menu);
  1052.                                 
  1053.                                 Success = TRUE;
  1054.                             }
  1055.                         }
  1056.                     }
  1057.                 }
  1058.             }
  1059.         }
  1060.     }
  1061.     if (!Success) CloseGUI(glob, pref);
  1062.     
  1063.     return(Success);
  1064. }
  1065.  
  1066.  
  1067.  
  1068. /*----------------------*/
  1069. /* Set the window title */
  1070. /*----------------------*/
  1071.  
  1072. void TitleWindow(struct Globals *glob, UBYTE *Text, ...)
  1073. {
  1074.     va_list Arg;
  1075.     va_start(Arg,Text);
  1076.     
  1077.     VSPrintf(glob->WTitle, Text, Arg);
  1078.     
  1079.     if (glob->OpenedScreen)
  1080.     {
  1081.         SetWindowTitles(glob->Window, (UBYTE*) ~0, glob->WTitle);
  1082.     }
  1083.     else
  1084.     {
  1085.         SetWindowTitles(glob->Window, glob->WTitle, (UBYTE*) ~0);
  1086.     }
  1087.     
  1088.     va_end(Arg);
  1089. }
  1090.  
  1091.  
  1092.  
  1093. /*---------------------------*/
  1094. /* Choose desired screenmode */
  1095. /*---------------------------*/
  1096.  
  1097. BOOL SelectScreenMode(struct Globals *glob, struct Prefs *pref, struct ScreenModeRequester **srq)
  1098. {
  1099.     BOOL Result = FALSE;
  1100.     
  1101.     ULONG InitialDisplayID = pref->ScreenMode;
  1102.     UWORD InitialDisplayDepth = pref->ScreenDepth;
  1103.     UWORD InitialDisplayWidth = pref->ScreenWidth;
  1104.     UWORD InitialDisplayHeight = pref->ScreenHeight;
  1105.     ULONG InitialOverscanType = pref->OverscanType;
  1106.     BOOL InitialAutoScroll = pref->AutoScroll;
  1107.     
  1108.     if (InitialDisplayID == -1L)
  1109.     {
  1110.         struct DimensionInfo dims;
  1111.         
  1112.         if ((InitialDisplayID = BestModeID(
  1113.             BIDTAG_NominalWidth, 320,
  1114.             BIDTAG_NominalHeight, 240,
  1115.             BIDTAG_Depth, 8,
  1116.             TAG_DONE )) == INVALID_ID)
  1117.         {
  1118.             InitialDisplayID = LORES_KEY;
  1119.         }
  1120.         
  1121.         InitialOverscanType = OSCAN_TEXT;
  1122.         InitialAutoScroll = TRUE;
  1123.         
  1124.         if (GetDisplayInfoData(NULL, (UBYTE*)&dims, sizeof(dims), DTAG_DIMS, InitialDisplayID) < sizeof(dims))
  1125.         {
  1126.             InitialDisplayDepth = 8;
  1127.             InitialDisplayWidth = 320;
  1128.             InitialDisplayHeight = 240;
  1129.         }
  1130.         else
  1131.         {
  1132.             InitialDisplayDepth  = dims.MaxDepth;
  1133.             InitialDisplayWidth  = (dims.TxtOScan.MaxX-dims.TxtOScan.MinX) + 1;
  1134.             InitialDisplayHeight = (dims.TxtOScan.MaxY-dims.TxtOScan.MinY) + 1;
  1135.         }
  1136.     }
  1137.     
  1138.     if (!(*srq))
  1139.     {
  1140.         if (!((*srq) = AllocAslRequestTags(ASL_ScreenModeRequest,
  1141.             ASLSM_TitleText, "Select screen mode",
  1142.             TAG_DONE)))
  1143.         {
  1144.             Message("Unable to allocate ASL screenmode requester.",NULL);
  1145.         }
  1146.     }
  1147.     
  1148.     if (*srq)
  1149.     {
  1150.         Result = AslRequestTags(*srq,
  1151.             ASLSM_Screen, GetScreen(glob),
  1152.             ASLSM_DoWidth, TRUE,
  1153.             ASLSM_DoHeight, TRUE,
  1154.             ASLSM_DoDepth, TRUE,
  1155.             ASLSM_DoOverscanType, TRUE,
  1156.             ASLSM_DoAutoScroll, TRUE,
  1157.             ASLSM_InitialDisplayID, InitialDisplayID,
  1158.             ASLSM_InitialDisplayWidth, InitialDisplayWidth,
  1159.             ASLSM_InitialDisplayHeight, InitialDisplayHeight,
  1160.             ASLSM_InitialDisplayDepth, InitialDisplayDepth,
  1161.             ASLSM_InitialOverscanType, InitialOverscanType,
  1162.             ASLSM_InitialAutoScroll, InitialAutoScroll,
  1163.             TAG_DONE);
  1164.         
  1165.         if (Result)
  1166.         {
  1167.             pref->ScreenMode=(*srq)->sm_DisplayID;
  1168.             pref->ScreenWidth=(*srq)->sm_DisplayWidth;
  1169.             pref->ScreenHeight=(*srq)->sm_DisplayHeight;
  1170.             pref->ScreenDepth=(*srq)->sm_DisplayDepth;
  1171.             pref->OverscanType=(*srq)->sm_OverscanType;
  1172.             pref->AutoScroll=(*srq)->sm_AutoScroll;
  1173.         }
  1174.     }
  1175.     return(Result);
  1176. }
  1177.  
  1178.  
  1179.  
  1180. /*--------------------------------*/
  1181. /* Close the GUI (Screen, Window) */
  1182. /*--------------------------------*/
  1183.  
  1184. void CloseGUI(struct Globals *glob, struct Prefs *pref)
  1185. {
  1186.     if (glob->Window)
  1187.     {
  1188.         if (glob->Menu)
  1189.         {
  1190.             ClearMenuStrip(glob->Window);
  1191.             
  1192.             FreeMenus(glob->Menu);
  1193.             glob->Menu = NULL;
  1194.         }
  1195.         
  1196.         FreeGraphics(glob);
  1197.         
  1198.         ((struct Process*)MyTask)->pr_WindowPtr=glob->ProcWindow;
  1199.         glob->ProcWindow = NULL;
  1200.         
  1201.         if (glob->LockedScreen)
  1202.         {
  1203.             pref->WinX = glob->Window->LeftEdge;
  1204.             pref->WinY = glob->Window->TopEdge;
  1205.             pref->WinW = glob->ww;
  1206.             pref->WinH = glob->wh;
  1207.         }
  1208.         
  1209.         if (glob->AppWindow)
  1210.         {
  1211.             RemoveAppWindow(glob->AppWindow);
  1212.             glob->AppWindow = NULL;
  1213.         }
  1214.         
  1215.         CloseWindow(glob->Window);
  1216.         glob->Window = NULL;
  1217.     }
  1218.     
  1219.     if (glob->Screen)
  1220.     {
  1221.         if (glob->VisualInfo)
  1222.         {
  1223.             FreeVisualInfo(glob->VisualInfo);
  1224.             glob->VisualInfo = NULL;
  1225.         }
  1226.         
  1227.         if (glob->LockedScreen)
  1228.         {
  1229.             UnlockPubScreen(NULL, glob->LockedScreen);
  1230.             glob->LockedScreen = NULL;
  1231.         }
  1232.         
  1233.         if (glob->OpenedScreen)
  1234.         {
  1235.             if (CloseScreen(glob->OpenedScreen))
  1236.                 glob->OpenedScreen = NULL;
  1237.         }
  1238.         
  1239.         glob->Screen = NULL;
  1240.     }
  1241.     
  1242.     if (glob->AppPort)
  1243.     {
  1244.         struct Message *msg;
  1245.         
  1246.         while(msg=GetMsg(glob->AppPort)) ReplyMsg(msg);
  1247.         
  1248.         DeleteMsgPort(glob->AppPort);
  1249.         glob->AppPort = NULL;
  1250.     }
  1251. }
  1252.  
  1253.  
  1254.  
  1255. /*-------------------------*/
  1256. /* Set Busy/Normal Pointer */
  1257. /*-------------------------*/
  1258.  
  1259. void BusyPointer(struct Globals *glob, struct Prefs *pref)
  1260. {
  1261.     SetPointer(glob->Window, WaitPointer, 16, 16, -6, 0);
  1262. }
  1263.  
  1264.  
  1265. void NormalPointer(struct Globals *glob, struct Prefs *pref)
  1266. {
  1267.     if ((pref->Flags & PREFF_FULLSCREEN) &&
  1268.         (pref->Flags & PREFF_HDMOUSEPTR))
  1269.         SetPointer(glob->Window, NoPointer, 16, 16, -6, 0);
  1270.     else
  1271.         ClearPointer(glob->Window);
  1272. }
  1273.  
  1274.  
  1275.  
  1276. /*-----------------------------*/
  1277. /* Calculate window dimensions */
  1278. /*-----------------------------*/
  1279.  
  1280. BOOL WindowLayout(struct Globals *glob, WORD *minw, WORD *minh, WORD *maxw, WORD *maxh)
  1281. {
  1282.     BOOL Success = TRUE;
  1283.     
  1284.     *minw=64;
  1285.     *minh=64;
  1286.     
  1287.     *maxw=1024;
  1288.     *maxh=1024;
  1289.     
  1290.     if (glob->ww < *minw) glob->ww = *minw;
  1291.     if (glob->wh < *minh) glob->wh = *minh;
  1292.     
  1293.     if (glob->ww > *maxw) glob->ww = *maxw;
  1294.     if (glob->wh > *maxh) glob->wh = *maxh;
  1295.     
  1296.     return(Success);
  1297. }
  1298.  
  1299.  
  1300.  
  1301. /*-----------------*/
  1302. /* Main event loop */
  1303. /*-----------------*/
  1304.  
  1305. UWORD NoteArray[128];
  1306. UBYTE ChanUse[16];
  1307.  
  1308. void MainLoop(struct Globals *glob, struct Prefs *pref)
  1309. {
  1310.     UWORD Mask = 0xffff;
  1311.     
  1312.     UWORD i;
  1313.     
  1314.     BOOL Active;
  1315.     APTR fwdata;
  1316.     
  1317.     ULONG signals;
  1318.     ULONG gotsignals;
  1319.     struct IntuiMessage *imsg;
  1320.     ULONG Cl;
  1321.     UWORD Co;
  1322.     APTR IA;
  1323.     
  1324.     ULONG timersig = (1L << glob->treq->tr_node.io_Message.mn_ReplyPort->mp_SigBit);
  1325.     ULONG appsig   = (1L << glob->AppPort->mp_SigBit);
  1326.     ULONG winsig   = (1L << glob->Window->UserPort->mp_SigBit);
  1327.     BOOL TimerActive;
  1328.     
  1329.     UBYTE Err;
  1330.     
  1331.     srand(GetTimeDelta());
  1332.     for (i=0; i<256; i++)
  1333.     {
  1334.         randomarray33[i] = ((rand()%100)<33) ? 1 : 0;
  1335.     }
  1336.     
  1337.     Active=TRUE;
  1338.     glob->GUIRefresh=FALSE;
  1339.     glob->LinkRefresh=FALSE;
  1340.     
  1341.     memset(NoteArray,0,sizeof(NoteArray));
  1342.     memset(ChanUse  ,0,sizeof(ChanUse  ));
  1343.     
  1344.     Watch = FALSE;
  1345.     AddIntServer(INTB_VERTB, &VertBlank);
  1346.     
  1347.     glob->ww = glob->Window->Width  - glob->Window->BorderLeft-glob->Window->BorderRight ;
  1348.     glob->wh = glob->Window->Height - glob->Window->BorderTop -glob->Window->BorderBottom;
  1349.     
  1350.     if (!(fwdata = (FWDefinitions[pref->FWMode].InitFireworks)(glob, pref)))
  1351.     {
  1352.         Message("Unable to initialize fireworks.", "Oh no");
  1353.     }
  1354.     else
  1355.     {
  1356.         signals = winsig | appsig | timersig | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_E;
  1357.         
  1358.         TimerActive = FALSE;
  1359.         SetTaskPri(MyTask, HIGHPRI);
  1360.         
  1361.         while(Active)
  1362.         {
  1363.             if (glob->GUIRefresh)
  1364.             {
  1365.                 BOOL SaveWatch = Watch;
  1366.                 Watch = FALSE;
  1367.                 
  1368.                 CloseGUI(glob, pref);
  1369.                 
  1370.                 if (!OpenGUI(glob, pref))
  1371.                 {
  1372.                     pref->Flags &= (~PREFF_FULLSCREEN);
  1373.                     
  1374.                     if (!OpenGUI(glob, pref))
  1375.                     {
  1376.                         Active = FALSE;
  1377.                         break;
  1378.                     }
  1379.                 }
  1380.                 
  1381.                 TitleWindow(glob, "Fireworks [%s]%s", pref->Link, TimerActive ? "" : " [idle]");
  1382.                 
  1383.                 winsig = (1L << glob->Window->UserPort->mp_SigBit);
  1384.                 signals = winsig | appsig | timersig | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_E;
  1385.                 
  1386.                 if (fwdata) (FWDefinitions[pref->FWMode].RethinkWindow)(fwdata);
  1387.                 
  1388.                 glob->GUIRefresh = FALSE;
  1389.                 
  1390.                 Watch=SaveWatch;
  1391.             }
  1392.             
  1393.             if (glob->LinkRefresh)
  1394.             {
  1395.                 struct MidiLink *newlink;
  1396.                 
  1397.                 if (!(newlink = AddMidiLink(glob->midi, MLTYPE_Receiver,
  1398.                     MLINK_Name, "VU Meter Link",
  1399.                     MLINK_Location, pref->Link,
  1400.                     MLINK_EventMask, CMF_Note|CMF_Mode,
  1401.                     MLINK_Comment,  "Fireworks [Input]",
  1402.                     TAG_DONE)))
  1403.                 {
  1404.                     Message("Cannot create link to MIDI interface '%s'",NULL,pref->Link);
  1405.                 }
  1406.                 else
  1407.                 {
  1408.                     RemoveMidiLink( glob->link );
  1409.                     FlushMidi ( glob->midi );
  1410.                     
  1411.                     glob->link = newlink;
  1412.                     
  1413.                     TitleWindow(glob, "Fireworks [%s]%s", pref->Link, TimerActive ? "" : " [idle]");
  1414.                     
  1415.                     memset(NoteArray,0,sizeof(NoteArray));
  1416.                     memset(ChanUse  ,0,sizeof(ChanUse  ));
  1417.                     
  1418.                     if (fwdata) (FWDefinitions[pref->FWMode].FreeNoteData)(fwdata);
  1419.                 }
  1420.                 
  1421.                 glob->LinkRefresh = FALSE;
  1422.             }
  1423.             
  1424.             gotsignals = Wait(signals);
  1425.             
  1426.             if (gotsignals & winsig)
  1427.             {
  1428.                 while(Active && (imsg=(struct IntuiMessage*)GetMsg(glob->Window->UserPort)))
  1429.                 {
  1430.                     Cl=imsg->Class;
  1431.                     Co=imsg->Code;
  1432.                     IA=imsg->IAddress;
  1433.                     ReplyMsg((struct Message*)imsg);
  1434.                     
  1435.                     if (Cl==IDCMP_CLOSEWINDOW)
  1436.                     {
  1437.                         if (AskAsync(glob))
  1438.                         {
  1439.                             Active = FALSE;
  1440.                             break;
  1441.                         }
  1442.                         else
  1443.                             AsyncMessage(glob,CloseTask, "Cannot quit yet. Please close all open requesters.","I will");
  1444.                     }
  1445.                     
  1446.                     if (Cl==IDCMP_NEWSIZE)
  1447.                     {
  1448.                         BOOL SaveWatch = Watch;
  1449.                         Watch = FALSE;
  1450.                         
  1451.                         glob->ww = pref->WinW = glob->Window->Width  - glob->Window->BorderLeft-glob->Window->BorderRight ;
  1452.                         glob->wh = pref->WinH = glob->Window->Height - glob->Window->BorderTop -glob->Window->BorderBottom;
  1453.                         
  1454.                         if (!(InitOrUpdateGraphics(glob, pref)))
  1455.                         {
  1456.                             Message("Failed to update graphics!",NULL);
  1457.                         }
  1458.                         
  1459.                         if (glob->PaintBitMap)
  1460.                         {
  1461.                             BltBitMapRastPort(glob->PaintBitMap, 0, 0, glob->Window->RPort, 0, 0, glob->ww, glob->wh, 0xc0);
  1462.                         }
  1463.                         else EraseRect(glob->Window->RPort, 0, 0, (glob->ww)-1, (glob->wh)-1);
  1464.                         
  1465.                         if (fwdata) (FWDefinitions[pref->FWMode].RethinkWindow)(fwdata);
  1466.                         
  1467.                         Watch = SaveWatch;
  1468.                     }
  1469.                     
  1470.                     if (Cl==IDCMP_REFRESHWINDOW)
  1471.                     {
  1472.                         BeginRefresh( glob->Window );
  1473.                         
  1474.                         if (glob->PaintBitMap)
  1475.                         {
  1476.                             BltBitMapRastPort(glob->PaintBitMap, 0, 0, glob->Window->RPort, 0, 0, glob->ww, glob->wh, 0xc0);
  1477.                         }
  1478.                         else EraseRect(glob->Window->RPort, 0, 0, (glob->ww)-1, (glob->wh)-1);
  1479.                         
  1480.                         EndRefresh( glob->Window, TRUE );
  1481.                     }
  1482.                     
  1483.                     if (Cl==IDCMP_MENUPICK)
  1484.                     {
  1485.                         BOOL SaveWatch = Watch;
  1486.                         
  1487.                         struct MenuItem *n;
  1488.                         ULONG pick;
  1489.                         
  1490.                         Watch = FALSE;
  1491.                         
  1492.                         while( (Co != MENUNULL) && Active)
  1493.                         {
  1494.                             n = ItemAddress( glob->Window->MenuStrip, (ULONG)Co );
  1495.                             pick = (ULONG) GTMENUITEM_USERDATA( n );
  1496.                             
  1497.                             switch(pick)
  1498.                             {
  1499.                                 case Menu_Link:
  1500.                                 {
  1501.                                     AsyncSelectMIDILink(glob, pref);
  1502.                                 }
  1503.                                 break;
  1504.                                 
  1505.                                 case Menu_Hooks:
  1506.                                 {
  1507.                                     if (n->Flags & CHECKED)
  1508.                                         pref->Flags |= PREFF_ASLHOOKS;
  1509.                                     else
  1510.                                     {
  1511.                                         pref->Flags &= (~PREFF_ASLHOOKS);
  1512.                                         
  1513.                                         /* Damn, there is no (legal) way */
  1514.                                         /* to clear the filter function */
  1515.                                         /* of an existing ASL requester */
  1516.                                         
  1517.                                         if (glob->ImageFR)
  1518.                                         {
  1519.                                             FreeAslRequest(glob->ImageFR);
  1520.                                             glob->ImageFR = NULL;
  1521.                                         }
  1522.                                         
  1523.                                         if (glob->MIDIFR)
  1524.                                         {
  1525.                                             FreeAslRequest(glob->MIDIFR);
  1526.                                             glob->MIDIFR = NULL;
  1527.                                         }
  1528.                                     }
  1529.                                 }
  1530.                                 break;
  1531.                                 
  1532.                                 case Menu_Save:
  1533.                                 {
  1534.                                     if ((!SavePrefs(glob, pref,"ENVARC:")) ||
  1535.                                         (!SavePrefs(glob, pref,"ENV:")))
  1536.                                         AsyncMessage(glob,SaveTask, "Failed to save configuration!", NULL);
  1537.                                 }
  1538.                                 break;
  1539.                                 
  1540.                                 case Menu_About:
  1541.                                 {
  1542.                                     AsyncMessage(glob,AboutTask, "Fireworks\n© 1998 by Christian Buchner\nflowerp@eikon.e-technik.tu-muenchen.de","Cool");
  1543.                                 }
  1544.                                 break;
  1545.                                 
  1546.                                 case Menu_Quit:
  1547.                                 {
  1548.                                     if (AskAsync(glob))
  1549.                                         Active = FALSE;
  1550.                                     else
  1551.                                         AsyncMessage(glob,CloseTask, "Cannot quit yet. Please close all open requesters.","I will");
  1552.                                 }
  1553.                                 break;
  1554.                                 
  1555.                                 case Menu_Kill:
  1556.                                 {
  1557.                                     pref->Flags &= (~PREFF_BACKDROP);
  1558.                                     
  1559.                                     if (glob->dto)
  1560.                                     {
  1561.                                         SetAPen(glob->Window->RPort, glob->PenArray[Backgroundpen]);
  1562.                                         RectFill(glob->Window->RPort, 0, 0, (glob->ww)-1, (glob->wh)-1);
  1563.                                         
  1564.                                         DisposeDTObject(glob->dto);
  1565.                                         glob->dto = NULL;
  1566.                                         
  1567.                                         if (!(InitOrUpdateGraphics(glob,pref)))
  1568.                                         {
  1569.                                             Message("Failed to update graphics!",NULL);
  1570.                                         }
  1571.                                         
  1572.                                         if (glob->PaintBitMap)
  1573.                                         {
  1574.                                             BltBitMapRastPort(glob->PaintBitMap, 0, 0, glob->Window->RPort, 0, 0, glob->ww, glob->wh, 0xc0);
  1575.                                         }
  1576.                                         else EraseRect(glob->Window->RPort, 0, 0, (glob->ww)-1, (glob->wh)-1);
  1577.                                     }
  1578.                                 }
  1579.                                 break;
  1580.                                 
  1581.                                 case Menu_Load:
  1582.                                 {
  1583.                                     AsyncSelectImage(glob, pref);
  1584.                                 }
  1585.                                 break;
  1586.                                 
  1587.                                 case Menu_Tile:
  1588.                                 {
  1589.                                     if (n->Flags & CHECKED)
  1590.                                         pref->Flags |= PREFF_TILE;
  1591.                                     else
  1592.                                         pref->Flags &= (~PREFF_TILE);
  1593.                                     
  1594.                                     if (!(InitOrUpdateGraphics(glob,pref)))
  1595.                                     {
  1596.                                         Message("Failed to update graphics!",NULL);
  1597.                                     }
  1598.                                     
  1599.                                     if (glob->PaintBitMap)
  1600.                                     {
  1601.                                         BltBitMapRastPort(glob->PaintBitMap, 0, 0, glob->Window->RPort, 0, 0, glob->ww, glob->wh, 0xc0);
  1602.                                     }
  1603.                                     else EraseRect(glob->Window->RPort, 0, 0, (glob->ww)-1, (glob->wh)-1);
  1604.                                 }
  1605.                                 break;
  1606.                                 
  1607.                                 case Menu_Screenmode:
  1608.                                 {
  1609.                                     AsyncSelectScreenMode(glob, pref);
  1610.                                 }
  1611.                                 break;
  1612.                                 
  1613.                                 case Menu_Fullscreen:
  1614.                                 {
  1615.                                     if (n->Flags & CHECKED)
  1616.                                     {
  1617.                                         if (pref->ScreenMode == -1L)
  1618.                                         {
  1619.                                             n->Flags &= (~CHECKED);
  1620.                                             AsyncSelectScreenMode(glob, pref);
  1621.                                         }
  1622.                                         else
  1623.                                         {
  1624.                                             pref->Flags |= PREFF_FULLSCREEN;
  1625.                                             glob->GUIRefresh = TRUE;
  1626.                                         }
  1627.                                     }
  1628.                                     else
  1629.                                     {
  1630.                                         glob->GUIRefresh = TRUE;
  1631.                                         pref->Flags &= (~PREFF_FULLSCREEN);
  1632.                                     }
  1633.                                 }
  1634.                                 break;
  1635.                                 
  1636.                                 case Menu_Titlebar:
  1637.                                 {
  1638.                                     if (n->Flags & CHECKED)
  1639.                                     {
  1640.                                         if (!(pref->Flags & PREFF_HDTITLEBAR))
  1641.                                             glob->GUIRefresh = TRUE;
  1642.                                         
  1643.                                         pref->Flags |= PREFF_HDTITLEBAR;
  1644.                                     }
  1645.                                     else
  1646.                                     {
  1647.                                         if (pref->Flags & PREFF_HDTITLEBAR)
  1648.                                             glob->GUIRefresh = TRUE;
  1649.                                         
  1650.                                         pref->Flags &= ~(PREFF_HDTITLEBAR);
  1651.                                     }
  1652.                                 }
  1653.                                 break;
  1654.                                 
  1655.                                 case Menu_Mouse:
  1656.                                 {
  1657.                                     if (n->Flags & CHECKED)
  1658.                                     {
  1659.                                         pref->Flags |= PREFF_HDMOUSEPTR;
  1660.                                         NormalPointer(glob, pref);
  1661.                                     }
  1662.                                     else
  1663.                                     {
  1664.                                         pref->Flags &= ~(PREFF_HDMOUSEPTR);
  1665.                                         NormalPointer(glob, pref);
  1666.                                     }
  1667.                                 }
  1668.                                 break;
  1669.                                 
  1670.                                 case Menu_Mode1:
  1671.                                 case Menu_Mode2:
  1672.                                 case Menu_Mode3:
  1673.                                 {
  1674.                                     if (n->Flags & CHECKED)
  1675.                                     {
  1676.                                         UWORD NewMode = pick - Menu_Mode1;
  1677.                                         if (NewMode != pref->FWMode)
  1678.                                         {
  1679.                                             if (fwdata)
  1680.                                             {
  1681.                                                 (FWDefinitions[pref->FWMode].ExitFireworks)(fwdata);
  1682.                                                 fwdata = NULL;
  1683.                                             }
  1684.                                             
  1685.                                             pref->FWMode = NewMode;
  1686.                                             
  1687.                                             if (!(fwdata = (FWDefinitions[pref->FWMode].InitFireworks)(glob, pref)))
  1688.                                             {
  1689.                                                 Message("Unable to initialize fireworks.", "Oh no");
  1690.                                                 n->Flags &= (~CHECKED);
  1691.                                             }
  1692.                                         }
  1693.                                     }
  1694.                                 }
  1695.                                 break;
  1696.                                 
  1697.                                 case Menu_Sens1:
  1698.                                 case Menu_Sens2:
  1699.                                 case Menu_Sens3:
  1700.                                 {
  1701.                                     if (n->Flags & CHECKED)
  1702.                                     {
  1703.                                         UWORD sens = pick - Menu_Sens1 + 1;
  1704.                                         switch(sens)
  1705.                                         {
  1706.                                             case 1: pref->Sensitivity=100; break;
  1707.                                             case 2: pref->Sensitivity= 75; break;
  1708.                                             case 3: pref->Sensitivity= 50; break;
  1709.                                         }
  1710.                                     }
  1711.                                 }
  1712.                                 break;
  1713.                                 
  1714.                                 case Menu_Double:
  1715.                                 {
  1716.                                     if (n->Flags & CHECKED)
  1717.                                         pref->Flags |= PREFF_DOUBLE;
  1718.                                     else
  1719.                                         pref->Flags &= (~PREFF_DOUBLE);
  1720.                                 }
  1721.                                 break;
  1722.                                 
  1723.                                 case Menu_Sparks:
  1724.                                 {
  1725.                                     if (n->Flags & CHECKED)
  1726.                                         pref->Flags |= PREFF_SPARKS;
  1727.                                     else
  1728.                                         pref->Flags &= (~PREFF_SPARKS);
  1729.                                 }
  1730.                                 break;
  1731.                                 
  1732.                                 case Menu_Release:
  1733.                                 {
  1734.                                     memset(NoteArray,0,sizeof(NoteArray));
  1735.                                     memset(ChanUse  ,0,sizeof(ChanUse  ));
  1736.                                     
  1737.                                     if (fwdata) (FWDefinitions[pref->FWMode].TimePassed)(fwdata);
  1738.                                     if (fwdata) (FWDefinitions[pref->FWMode].ReleaseNotes)(fwdata, 0);
  1739.                                 }
  1740.                                 break;
  1741.                                 
  1742.                                 case Menu_Play:
  1743.                                 {
  1744.                                     AsyncSelectAndPlay(glob, pref);
  1745.                                 };
  1746.                                 break;
  1747.                                 
  1748.                                 case Menu_Stop:
  1749.                                 {
  1750.                                     StopMIDI(glob,pref);
  1751.                                 }
  1752.                                 break;
  1753.                                 
  1754.                                 case Menu_Init1:
  1755.                                 case Menu_Init2:
  1756.                                 case Menu_Init3:
  1757.                                 case Menu_Init4:
  1758.                                 case Menu_Init5:
  1759.                                 {
  1760.                                     if (n->Flags & CHECKED)
  1761.                                     {
  1762.                                         UWORD init = pick - Menu_Init1;
  1763.                                         pref->Flags &= (~(PREFF_GM|PREFF_GS|PREFF_XG|PREFF_MT32));
  1764.                                         
  1765.                                         switch(init)
  1766.                                         {
  1767.                                             case 1: pref->Flags |= PREFF_GM;
  1768.                                                 break;
  1769.                                             case 2: pref->Flags |= PREFF_GS;
  1770.                                                 break;
  1771.                                             case 3: pref->Flags |= PREFF_XG;
  1772.                                                 break;
  1773.                                             case 4: pref->Flags |= PREFF_MT32;
  1774.                                                 break;
  1775.                                         }
  1776.                                     }
  1777.                                 }
  1778.                                 break;
  1779.                                 
  1780.                                 case Menu_Timestamp:
  1781.                                 {
  1782.                                     if (n->Flags & CHECKED)
  1783.                                         pref->Flags |= PREFF_TIMESTAMP;
  1784.                                     else
  1785.                                         pref->Flags &= (~PREFF_TIMESTAMP);
  1786.                                 }
  1787.                                 break;
  1788.                                 
  1789.                             }
  1790.                             
  1791.                             Co = n->NextSelect;
  1792.                         }
  1793.                         
  1794.                         Watch = SaveWatch;
  1795.                     }
  1796.                 }
  1797.             }
  1798.             
  1799.             if (Active && (gotsignals & SIGBREAKF_CTRL_E))
  1800.             {
  1801.                 MidiMsg msg;
  1802.                 
  1803.                 if (fwdata) (FWDefinitions[pref->FWMode].TimePassed)(fwdata);
  1804.                 
  1805.                 while (GetMidi(glob->midi,&msg))
  1806.                 {
  1807.                     LONG reltime = 0;
  1808.                     
  1809.                     if (pref->Flags & PREFF_TIMESTAMP)
  1810.                     {
  1811.                         reltime = HowOldIsTimestamp(msg.mm_Time);
  1812.                         if (reltime < 0) reltime = 0;
  1813.                     }
  1814.                     
  1815.                     if (noteon(&msg))
  1816.                     {
  1817.                         UBYTE chn  = msg.mm_Status & MS_ChanBits;
  1818.                         UWORD note = msg.mm_Data1;
  1819.                         UWORD cmsk = 1<<chn;
  1820.                         
  1821.                         // if ((Mask & cmsk) && !((NoteArray[note] & Mask)))
  1822.                         // {
  1823.                         // }
  1824.                         
  1825.                         if (!(NoteArray[note] & cmsk))
  1826.                         {
  1827.                             /* Channel wird benutzt */
  1828.                             ChanUse[chn]++;
  1829.                             
  1830.                             NoteArray[note] |= cmsk;
  1831.                             
  1832.                             /* Note angeschlagen */
  1833.                             
  1834.                             if (fwdata) (FWDefinitions[pref->FWMode].NoteOn)(fwdata, chn, note, msg.mm_Data2, reltime);
  1835.                         }
  1836.                         
  1837.                     }
  1838.                     else
  1839.                     {
  1840.                         if (noteoff(&msg))
  1841.                         {
  1842.                             UBYTE chn  = msg.mm_Status & MS_ChanBits;
  1843.                             UWORD note = msg.mm_Data1;
  1844.                             UWORD cmsk = 1<<chn;
  1845.                             
  1846.                             if (NoteArray[note] & cmsk)
  1847.                             {
  1848.                                 /* Channel wird nicht mehr benutzt */
  1849.                                 ChanUse[chn]--;
  1850.                                 
  1851.                                 NoteArray[note] &= (~cmsk);
  1852.                                 
  1853.                                 /* Note losgelassen */
  1854.                                 
  1855.                                 if (fwdata) (FWDefinitions[pref->FWMode].NoteOff)(fwdata, chn, note, reltime);
  1856.                             }
  1857.                             
  1858.                             // if ((Mask & cmsk) && (!(NoteArray[note] & Mask)))
  1859.                             // {
  1860.                             // }
  1861.                         }
  1862.                         else
  1863.                         {
  1864.                             if (modemsg(&msg))
  1865.                             {
  1866.                                 UBYTE chn  = msg.mm_Status & MS_ChanBits;
  1867.                                 UBYTE mode = msg.mm_Data1;
  1868.                                 UWORD note;
  1869.                                 UWORD cmsk = 1<<chn;
  1870.                                 
  1871.                                 if (mode == MM_AllOff)
  1872.                                 {
  1873.                                     for (note=0;note<128;note++)
  1874.                                     {
  1875.                                         if (NoteArray[note] & cmsk)
  1876.                                         {
  1877.                                             /* Channel wird nicht mehr benuzt */
  1878.                                             ChanUse[chn]--;
  1879.                                             
  1880.                                             if (fwdata) (FWDefinitions[pref->FWMode].NoteOff)(fwdata, chn, note, reltime);
  1881.                                             
  1882.                                             NoteArray[note] &= (~cmsk);
  1883.                                         }
  1884.                                         
  1885.                                         // if ((Mask & cmsk) && (!(NoteArray[note] & Mask)))
  1886.                                         // {
  1887.                                         // }
  1888.                                     }
  1889.                                 }
  1890.                             }
  1891.                         }
  1892.                     }
  1893.                 }
  1894.                 
  1895.                 if (Err = GetMidiErr(glob->midi))
  1896.                 {
  1897.                     if (Err & CMEF_MsgErr)            AsyncMessage(glob,ErrTask, "MIDI Error: MsgErr!",NULL);
  1898.                     if (Err & CMEF_BufferFull)        AsyncMessage(glob,ErrTask, "MIDI Error: BufferFull!",NULL);
  1899.                     if (Err & CMEF_SysExFull)        AsyncMessage(glob,ErrTask, "MIDI Error: SysExFull!",NULL);
  1900.                     if (Err & CMEF_ParseMem)        AsyncMessage(glob,ErrTask, "MIDI Error: ParseMem!",NULL);
  1901.                     if (Err & CMEF_RecvErr)            AsyncMessage(glob,ErrTask, "MIDI Error: RecvErr!",NULL);
  1902.                     if (Err & CMEF_RecvOverflow)    AsyncMessage(glob,ErrTask, "MIDI Error: RecvOverflow!",NULL);
  1903.                     if (Err & CMEF_SysExTooBig)        AsyncMessage(glob,ErrTask, "MIDI Error: SysExTooBig!",NULL);
  1904.                 }
  1905.                 
  1906.                 /* (re-)start timer if it isn't running */
  1907.                 if (!TimerActive)
  1908.                 {
  1909.                     /* but only if there is something to display */
  1910.                     if (fwdata) if (!(FWDefinitions[pref->FWMode].IsIdle)(fwdata))
  1911.                     {
  1912.                         glob->treq->tr_node.io_Command = TR_ADDREQUEST;
  1913.                         glob->treq->tr_time.tv_secs  = 0;
  1914.                         glob->treq->tr_time.tv_micro = 1000000 / FPS;
  1915.                         SendIO((struct IORequest*)glob->treq);
  1916.                         TimerActive = TRUE;
  1917.                         Watch = TRUE;
  1918.                         
  1919.                         TitleWindow(glob, "Fireworks [%s]", pref->Link);
  1920.                     }
  1921.                 }
  1922.             }
  1923.             
  1924.             if (Active && (gotsignals & timersig))
  1925.             {
  1926.                 BOOL idle = TRUE;
  1927.                 
  1928.                 IdleCount = 0;
  1929.                 
  1930.                 if (fwdata) (FWDefinitions[pref->FWMode].TimePassed)(fwdata);
  1931.                 if (fwdata) idle = (FWDefinitions[pref->FWMode].IsIdle)(fwdata);
  1932.                 
  1933.                 if (!idle)
  1934.                 {
  1935.                     glob->treq->tr_node.io_Command = TR_ADDREQUEST;
  1936.                     glob->treq->tr_time.tv_secs  = 0;
  1937.                     glob->treq->tr_time.tv_micro = 1000000 / FPS;
  1938.                     SendIO((struct IORequest*)glob->treq);
  1939.                 }
  1940.                 
  1941.                 if ((glob->BGBitMap) && (glob->PaintBitMap))
  1942.                 {
  1943.                     BltBitMapRastPort(glob->BGBitMap, 0, 0, &glob->PaintRP, 0, 0, glob->ww, glob->wh, 0xc0);
  1944.                     
  1945.                     if (fwdata) (FWDefinitions[pref->FWMode].DrawFireworks)(fwdata, Mask);
  1946.                     
  1947.                     BltBitMapRastPort(glob->PaintBitMap, 0, 0, glob->Window->RPort, 0, 0, glob->ww, glob->wh, 0xc0);
  1948.                 }
  1949.                 
  1950.                 if (idle)
  1951.                 {
  1952.                     TimerActive = FALSE;
  1953.                     Watch = FALSE;
  1954.                     SetTaskPri(MyTask, HIGHPRI);
  1955.                     
  1956.                     TitleWindow(glob, "Fireworks [%s] [idle]", pref->Link);
  1957.                 }
  1958.                 else
  1959.                 {
  1960.                     /* reset task priority if it has
  1961.                        been modified by the watchdog */
  1962.                     if (MyTask->tc_Node.ln_Pri != NORMPRI)
  1963.                     {
  1964.                         SetTaskPri(MyTask, NORMPRI);
  1965.                     }
  1966.                 }
  1967.             }
  1968.             
  1969.             if (Active && (gotsignals & appsig))
  1970.             {
  1971.                 struct AppMessage *appm;
  1972.                 
  1973.                 while(appm = (struct AppMessage*)GetMsg(glob->AppPort))
  1974.                 {
  1975.                     if (appm->am_Type == AMTYPE_APPWINDOW)
  1976.                     {
  1977.                         BOOL SaveWatch = Watch;
  1978.                         struct WBArg *arg = appm->am_ArgList;
  1979.                         ULONG i;
  1980.                         
  1981.                         Watch = FALSE;
  1982.                         
  1983.                         for (i=0 ; i < appm->am_NumArgs ; i++, arg++)
  1984.                         {
  1985.                             BOOL IsPicture = FALSE;
  1986.                             BOOL IsMIDI = FALSE;
  1987.                             
  1988.                             BPTR OldDir;
  1989.                             BPTR lock;
  1990.                             
  1991.                             OldDir = CurrentDir(arg->wa_Lock);
  1992.                             
  1993.                             if (lock = Lock(arg->wa_Name, SHARED_LOCK))
  1994.                             {
  1995.                                 struct DataType *dtn;
  1996.                                 
  1997.                                 if (dtn = ObtainDataTypeA (DTST_FILE, (APTR) lock, NULL))
  1998.                                 {
  1999.                                     if (dtn->dtn_Header->dth_GroupID == GID_PICTURE)
  2000.                                     {
  2001.                                         if (NameFromLock(lock, pref->Image, sizeof(pref->Image)))
  2002.                                         {
  2003.                                             IsPicture = TRUE;
  2004.                                         }
  2005.                                     }
  2006.                                     ReleaseDataType (dtn);
  2007.                                 }
  2008.                                 
  2009.                                 if (!IsPicture)
  2010.                                 {
  2011.                                     BPTR dupedlock;
  2012.                                     BPTR file;
  2013.                                     
  2014.                                     if (dupedlock = DupLock(lock))
  2015.                                     {
  2016.                                         if (file = OpenFromLock(dupedlock))
  2017.                                         {
  2018.                                             UBYTE header[20];
  2019.                                             
  2020.                                             if (Read(file, header, sizeof(header)) == sizeof(header))
  2021.                                             {
  2022.                                                 if ( ((header[0] == 'M') &&
  2023.                                                       (header[1] == 'T') &&
  2024.                                                       (header[2] == 'h') &&
  2025.                                                       (header[3] == 'd'))
  2026.                                                     
  2027.                                                     ||
  2028.                                                     
  2029.                                                      ((header[0] == 'X') &&
  2030.                                                       (header[1] == 'P') &&
  2031.                                                       (header[2] == 'K') &&
  2032.                                                       (header[3] == 'F') &&
  2033.                                                       (header[16]== 'M') &&
  2034.                                                       (header[17]== 'T') &&
  2035.                                                       (header[18]== 'h') &&
  2036.                                                       (header[19]== 'd')) )
  2037.                                                 {
  2038.                                                     if (NameFromLock(lock, pref->MIDIFile, sizeof(pref->MIDIFile)))
  2039.                                                     {
  2040.                                                         IsMIDI = TRUE;
  2041.                                                     }
  2042.                                                 }
  2043.                                             }
  2044.                                             Close(file);
  2045.                                         } else UnLock(dupedlock);
  2046.                                     }
  2047.                                 }
  2048.                                 UnLock(lock);
  2049.                             }
  2050.                             CurrentDir(OldDir);
  2051.                             
  2052.                             if (IsPicture) LoadImage(glob, pref);
  2053.                             else
  2054.                                 if (IsMIDI) PlayMIDI(glob, pref);
  2055.                                 else
  2056.                                     AsyncMessage(glob,DropTask, "Please drop only picture objects or MIDI files\ninto the Fireworks window.","Sorry");
  2057.                         }
  2058.                         Watch = SaveWatch;
  2059.                     }
  2060.                     ReplyMsg((struct Message*)appm);
  2061.                 }
  2062.             }
  2063.             
  2064.             if (gotsignals & SIGBREAKF_CTRL_C)
  2065.             {
  2066.                 if (AskAsync(glob))
  2067.                 {
  2068.                     Active = FALSE;
  2069.                     Watch = FALSE;
  2070.                 }
  2071.                 else
  2072.                     AsyncMessage(glob,CloseTask, "Cannot quit yet. Please close all open requesters.","I will");
  2073.             }
  2074.         }
  2075.         
  2076.         RemIntServer(INTB_VERTB, &VertBlank);
  2077.         
  2078.         if (TimerActive)
  2079.         {
  2080.             AbortIO((struct IORequest*)glob->treq);
  2081.             WaitIO((struct IORequest*)glob->treq);
  2082.         }
  2083.         
  2084.         if (fwdata)
  2085.         {
  2086.             (FWDefinitions[pref->FWMode].ExitFireworks)(fwdata);
  2087.             fwdata = NULL;
  2088.         }
  2089.     }
  2090. }
  2091.  
  2092.  
  2093.  
  2094. /*-----------------------------------*/
  2095. /* Asynchronously select a MIDI link */
  2096. /*-----------------------------------*/
  2097.  
  2098. void SyncSelectMIDILink(struct Globals *glob, struct Prefs *pref, APTR UserData)
  2099. {
  2100.     APTR listreq;
  2101.     
  2102.     if (!(listreq = AllocListRequest(
  2103.         LISTREQ_Screen, GetScreen(glob),
  2104.         LISTREQ_TitleText, "Select input link",
  2105.         TAG_DONE )))
  2106.     {
  2107.         Message("Couldn't allocate a list requester.",NULL);
  2108.     }
  2109.     else
  2110.     {
  2111.         if (SelectCluster( listreq, pref->Link, sizeof(pref->Link), TAG_DONE ))
  2112.         {
  2113.             if (strcmp((glob->link)->ml_Location->mcl_Node.ln_Name,pref->Link))
  2114.             {
  2115.                 glob->LinkRefresh = TRUE;
  2116.                 Signal(MyTask, SIGBREAKF_CTRL_E);    /* wake up main task */
  2117.             }
  2118.         }
  2119.         FreeListRequest(listreq);
  2120.     }
  2121. }
  2122.  
  2123. void AsyncSelectMIDILink(struct Globals *glob, struct Prefs *pref)
  2124. {
  2125.     if (!StartAsyncTask(glob, pref, "Fireworks MIDI link selection task", LinkTask, &SyncSelectMIDILink, NULL, 0))
  2126.     {
  2127.         SyncSelectMIDILink(glob, pref, NULL);
  2128.     }
  2129. }
  2130.  
  2131.  
  2132.  
  2133. /*------------------------------------*/
  2134. /* Asynchronously select a screenmode */
  2135. /*------------------------------------*/
  2136.  
  2137. void SyncSelectScreenMode(struct Globals *glob, struct Prefs *pref, APTR UserData)
  2138. {
  2139.     if (SelectScreenMode(glob, pref, &glob->ScreenModeRQ))
  2140.     {
  2141.         pref->Flags |= PREFF_FULLSCREEN;
  2142.         glob->GUIRefresh = TRUE;
  2143.         Signal(MyTask, SIGBREAKF_CTRL_E);    /* wake up main task */
  2144.     }
  2145. }
  2146.  
  2147. void AsyncSelectScreenMode(struct Globals *glob, struct Prefs *pref)
  2148. {
  2149.     if (!StartAsyncTask(glob, pref, "Fireworks ScreenMode selection task", ScreenTask, &SyncSelectScreenMode, NULL, 0))
  2150.     {
  2151.         SyncSelectScreenMode(glob, pref, NULL);
  2152.     }
  2153. }
  2154.  
  2155.  
  2156.  
  2157. /*---------------------------------------------------*/
  2158. /* Asynchronously select an image and notify program */
  2159. /*---------------------------------------------------*/
  2160.  
  2161. void AsyncSelectImageFunction(struct Globals *glob, struct Prefs *pref, APTR UserData)
  2162. {
  2163.     BOOL Success = FALSE;
  2164.     UBYTE *filename;
  2165.     UBYTE *ptr, save;
  2166.     BPTR dirlock;
  2167.     ULONG msglen;
  2168.     struct AppMessage *appm,*got;
  2169.     struct WBArg *argument;
  2170.     UBYTE *name;
  2171.     
  2172.     struct Process *MyProc = (struct Process*)FindTask(NULL);
  2173.     
  2174.     if (SelectImage(glob, pref, &glob->ImageFR, pref->Image, sizeof(pref->Image)))
  2175.     {
  2176.         pref->Flags |= PREFF_BACKDROP;
  2177.         
  2178.         /* now fake an AppMessage to notify program of image change */
  2179.         
  2180.         filename = FilePart(pref->Image);
  2181.         
  2182.         ptr = PathPart(pref->Image);
  2183.         save = *ptr;
  2184.         *ptr = 0;
  2185.         
  2186.         if (dirlock = Lock(pref->Image, SHARED_LOCK))
  2187.         {
  2188.             *ptr = save;
  2189.             msglen = sizeof(struct AppMessage)+sizeof(struct WBArg)+strlen(filename)+1;
  2190.             
  2191.             if (appm = AllocVec(msglen,MEMF_ANY|MEMF_CLEAR))
  2192.             {
  2193.                 argument = (struct WBArg*)(appm+1);
  2194.                 name = (UBYTE*)(argument+1);
  2195.                 
  2196.                 appm->am_Message.mn_Length = msglen;
  2197.                 appm->am_Message.mn_ReplyPort = &MyProc->pr_MsgPort;
  2198.                 
  2199.                 appm->am_Type = AMTYPE_APPWINDOW;
  2200.                 appm->am_NumArgs = 1;
  2201.                 appm->am_ArgList = argument;
  2202.                 
  2203.                 argument->wa_Lock = dirlock;
  2204.                 argument->wa_Name = name;
  2205.                 
  2206.                 strcpy(name, filename);
  2207.                 
  2208.                 PutMsg(glob->AppPort, (struct Message*)appm);
  2209.                 
  2210.                 got = NULL;
  2211.                 while (got != appm)
  2212.                 {
  2213.                     WaitPort(&MyProc->pr_MsgPort);
  2214.                     got = (struct AppMessage*)GetMsg(&MyProc->pr_MsgPort);
  2215.                 }
  2216.                 
  2217.                 FreeVec(appm);
  2218.                 
  2219.                 Success = TRUE;
  2220.             }
  2221.             UnLock(dirlock);
  2222.         }
  2223.         else *ptr = save;
  2224.     }
  2225. }
  2226.  
  2227. void AsyncSelectImage(struct Globals *glob, struct Prefs *pref)
  2228. {
  2229.     if (!(StartAsyncTask(glob, pref, "Fireworks Backdrop selection task", ImageTask, &AsyncSelectImageFunction, NULL, 0)))
  2230.     {
  2231.         if (SelectImage(glob, pref, &glob->ImageFR, pref->Image, sizeof(pref->Image)))
  2232.         {
  2233.             pref->Flags |= PREFF_BACKDROP;
  2234.             LoadImage(glob,pref);
  2235.         }
  2236.     }
  2237. }
  2238.  
  2239.  
  2240.  
  2241. /*------------------------------------------*/
  2242. /* Asynchronously select & play a MIDI file */
  2243. /*------------------------------------------*/
  2244.  
  2245. void SelectAndPlay(struct Globals *glob, struct Prefs *pref, APTR UserData)
  2246. {
  2247.     if (SelectMIDI(glob, pref, &glob->MIDIFR, pref->MIDIFile,sizeof(pref->MIDIFile)))
  2248.     {
  2249.         PlayMIDI(glob,pref);
  2250.     }
  2251. }
  2252.  
  2253. void AsyncSelectAndPlay(struct Globals *glob, struct Prefs *pref)
  2254. {
  2255.     if (!StartAsyncTask(glob, pref, "Fireworks MIDI file selection task", PlayTask, &SelectAndPlay, NULL, 0))
  2256.     {
  2257.         SelectAndPlay(glob, pref, NULL);
  2258.     }
  2259. }
  2260.  
  2261.  
  2262.  
  2263. /*----------------------------*/
  2264. /* Initialize/Update Graphics */
  2265. /*----------------------------*/
  2266.  
  2267. BOOL InitOrUpdateGraphics(struct Globals *glob, struct Prefs *pref)
  2268. {
  2269.     BOOL Success = FALSE;
  2270.     
  2271.     if (glob->PaintLayer)
  2272.     {
  2273.         DeleteLayer(0, glob->PaintLayer);
  2274.         glob->PaintLayer = NULL;
  2275.     }
  2276.     
  2277.     if (glob->BGBitMap)
  2278.     {
  2279.         FreeBitMap(glob->BGBitMap);
  2280.         glob->BGBitMap = NULL;
  2281.     }
  2282.     
  2283.     if (glob->PaintBitMap)
  2284.     {
  2285.         FreeBitMap(glob->PaintBitMap);
  2286.         glob->PaintBitMap = NULL;
  2287.     }
  2288.     
  2289.     if (glob->Window)
  2290.     {
  2291.         UWORD i;
  2292.         struct ColorMap *cmap = glob->Window->WScreen->ViewPort.ColorMap;
  2293.         
  2294.         struct BitMap *friend = glob->Window->RPort->BitMap;
  2295.         ULONG depth = GetBitMapAttr(friend, BMA_DEPTH);
  2296.         ULONG flags = GetBitMapAttr(friend, BMA_FLAGS);
  2297.         
  2298.         struct RastPort BGRP;
  2299.         
  2300.         BusyPointer(glob, pref);
  2301.         
  2302.         for (i = 0 ; i < NUMPENS ; i++)
  2303.         {
  2304.             if (glob->PenArray[i] == -1L)
  2305.             {
  2306.                 glob->PenArray[i] = ObtainBestPen(
  2307.                     cmap,
  2308.                     (ULONG)PenColors[i][0]<<24, 
  2309.                     (ULONG)PenColors[i][1]<<24, 
  2310.                     (ULONG)PenColors[i][2]<<24,
  2311.                     OBP_Precision, PRECISION_IMAGE,
  2312.                     TAG_DONE );
  2313.             }
  2314.         }
  2315.         
  2316.         /* Cybergraphics kludge */
  2317.         if ( !(flags & BMF_STANDARD) ) flags |= BMF_MINPLANES;
  2318.         
  2319.         if (glob->BGBitMap = AllocBitMap(glob->ww, glob->wh, depth, flags | BMF_CLEAR, friend))
  2320.         {
  2321.             struct BitMap *ImageBM   = NULL;
  2322.             struct BitMapHeader *bmh = NULL;
  2323.             
  2324.             InitRastPort(&BGRP);
  2325.             BGRP.BitMap = glob->BGBitMap;
  2326.             
  2327.             SetAPen(&BGRP, glob->PenArray[Backgroundpen]);
  2328.             
  2329.             if (glob->dto)
  2330.             {
  2331.                 GetDTAttrs(glob->dto, PDTA_DestBitMap, &ImageBM,
  2332.                                  PDTA_BitMapHeader, &bmh,
  2333.                             TAG_DONE);
  2334.             }
  2335.             
  2336.             if ((!ImageBM) || (!bmh))
  2337.             {
  2338.                 RectFill(&BGRP, 0, 0, (glob->ww)-1, (glob->wh)-1);
  2339.             }
  2340.             else
  2341.             {
  2342.                 UWORD width = bmh->bmh_Width;
  2343.                 UWORD height= bmh->bmh_Height;
  2344.                 
  2345.                 if (pref->Flags & PREFF_TILE)
  2346.                 {
  2347.                     UWORD x,y;
  2348.                     UWORD dow, doh;
  2349.                     
  2350.                     for (y = 0 ; y < glob->wh ; y += doh)
  2351.                     {
  2352.                         doh = height;
  2353.                         
  2354.                         if (y + doh > glob->wh)
  2355.                             doh = glob->wh - y;
  2356.                         
  2357.                         for (x = 0 ; x < glob->ww ; x += dow)
  2358.                         {
  2359.                             dow = width; 
  2360.                             
  2361.                             if (x + dow > glob->ww)
  2362.                                 dow = glob->ww - x;
  2363.                             
  2364.                             BltBitMap(ImageBM, 0, 0, glob->BGBitMap, x, y, dow, doh, 0xc0, 0xff,NULL);
  2365.                         }
  2366.                     }
  2367.                 }
  2368.                 else
  2369.                 {
  2370.                     struct BitScaleArgs bsa;
  2371.                     
  2372.                     bsa.bsa_SrcX        = 0;
  2373.                     bsa.bsa_SrcY        = 0;
  2374.                     bsa.bsa_SrcWidth    = width;
  2375.                     bsa.bsa_SrcHeight    = height;
  2376.                     bsa.bsa_XSrcFactor    = width;
  2377.                     bsa.bsa_YSrcFactor    = height;
  2378.                     bsa.bsa_DestX        = 0;
  2379.                     bsa.bsa_DestY        = 0;
  2380.                     bsa.bsa_DestWidth    = glob->ww;
  2381.                     bsa.bsa_DestHeight    = glob->wh;
  2382.                     bsa.bsa_XDestFactor    = glob->ww;
  2383.                     bsa.bsa_YDestFactor    = glob->wh;
  2384.                     bsa.bsa_SrcBitMap    = ImageBM;
  2385.                     bsa.bsa_DestBitMap    = glob->BGBitMap;
  2386.                     bsa.bsa_Flags        = 0;
  2387.                     bsa.bsa_XDDA        = 0;
  2388.                     bsa.bsa_YDDA        = 0;
  2389.                     bsa.bsa_Reserved1    = 0;
  2390.                     bsa.bsa_Reserved2    = 0;
  2391.                     
  2392.                     BitMapScale(&bsa);
  2393.                 }
  2394.             }
  2395.             
  2396.             if ( glob->PaintBitMap = AllocBitMap(glob->ww, glob->wh, depth, flags | BMF_CLEAR, friend))
  2397.             {
  2398.                 InitRastPort(&glob->PaintRP);
  2399.                 glob->PaintRP.BitMap = glob->PaintBitMap;
  2400.                 
  2401.                 if (!(glob->LInfo)) glob->LInfo = NewLayerInfo();
  2402.                 
  2403.                 if (glob->LInfo)
  2404.                 {
  2405.                     if (glob->PaintLayer = CreateUpfrontLayer(glob->LInfo, glob->PaintBitMap, 0, 0, (glob->ww)-1, (glob->wh)-1, LAYERSMART, NULL))
  2406.                     {
  2407.                         glob->PaintRP.Layer = glob->PaintLayer;
  2408.                         
  2409.                         BltBitMapRastPort(glob->BGBitMap, 0, 0, &glob->PaintRP, 0, 0, glob->ww, glob->wh, 0xc0);
  2410.                         
  2411.                         Success = TRUE;
  2412.                     }
  2413.                 }
  2414.             }
  2415.         }
  2416.         NormalPointer(glob,pref);
  2417.     }
  2418.     
  2419.     if (!Success)
  2420.     {
  2421.         if (glob->PaintLayer)
  2422.         {
  2423.             DeleteLayer(0, glob->PaintLayer);
  2424.             glob->PaintLayer = NULL;
  2425.         }
  2426.         
  2427.         if (glob->BGBitMap)
  2428.         {
  2429.             FreeBitMap(glob->BGBitMap);
  2430.             glob->BGBitMap = NULL;
  2431.         }
  2432.         
  2433.         if (glob->PaintBitMap)
  2434.         {
  2435.             FreeBitMap(glob->PaintBitMap);
  2436.             glob->PaintBitMap = NULL;
  2437.         }
  2438.     }
  2439.     
  2440.     return(Success);
  2441. }
  2442.  
  2443.  
  2444.  
  2445. /*-------------------------*/
  2446. /* Free allocated Graphics */
  2447. /*-------------------------*/
  2448.  
  2449. void FreeGraphics(struct Globals *glob)
  2450. {
  2451.     UWORD i;
  2452.     
  2453.     if (glob->dto)
  2454.     {
  2455.         SetAPen(glob->Window->RPort, glob->PenArray[Backgroundpen]);
  2456.         RectFill(glob->Window->RPort, 0, 0, (glob->ww)-1, (glob->wh)-1);
  2457.         
  2458.         DisposeDTObject(glob->dto);
  2459.         glob->dto = NULL;
  2460.     }
  2461.     
  2462.     if (glob->PaintLayer)
  2463.     {
  2464.         DeleteLayer(0, glob->PaintLayer);
  2465.         glob->PaintLayer = NULL;
  2466.     }
  2467.     
  2468.     if (glob->LInfo)
  2469.     {
  2470.         DisposeLayerInfo(glob->LInfo);
  2471.         glob->LInfo = NULL;
  2472.     }
  2473.     
  2474.     if (glob->BGBitMap)
  2475.     {
  2476.         FreeBitMap(glob->BGBitMap);
  2477.         glob->BGBitMap = NULL;
  2478.     }
  2479.     
  2480.     if (glob->PaintBitMap)
  2481.     {
  2482.         FreeBitMap(glob->PaintBitMap);
  2483.         glob->PaintBitMap = NULL;
  2484.     }
  2485.     
  2486.     if (glob->Window)
  2487.     {
  2488.         struct ColorMap *cmap = glob->Window->WScreen->ViewPort.ColorMap;
  2489.         
  2490.         for (i = 0 ; i < NUMPENS ; i++)
  2491.         {
  2492.             if (glob->PenArray[i] != -1L)
  2493.             {
  2494.                 ReleasePen( cmap, glob->PenArray[i] );
  2495.                 glob->PenArray[i] = -1L;
  2496.             }
  2497.         }
  2498.     }
  2499. }
  2500.  
  2501.  
  2502.  
  2503. /*--------------------*/
  2504. /* Get current screen */
  2505. /*--------------------*/
  2506.  
  2507. struct Screen *GetScreen(struct Globals *glob)
  2508. {
  2509.     struct Window *win;
  2510.     struct Screen *scr = NULL;
  2511.     
  2512.     if (MyTask)
  2513.     {
  2514.         win = ((struct Window*)((struct Process*)MyTask)->pr_WindowPtr);
  2515.         if (win) scr = win->WScreen;
  2516.     }
  2517.     
  2518.     if (!scr)
  2519.     {
  2520.         if (glob->LockedScreen)
  2521.             scr = glob->LockedScreen;
  2522.         else
  2523.             scr = glob->LockedScreen = LockPubScreen(NULL);
  2524.     }
  2525.     
  2526.     return(scr);
  2527. }
  2528.  
  2529.  
  2530.  
  2531. /*----------------------------------*/
  2532. /* Load image using datatypes (V43) */
  2533. /*----------------------------------*/
  2534.  
  2535. void LoadImage(struct Globals *glob, struct Prefs *pref)
  2536. {
  2537.     if (glob->dto)
  2538.     {
  2539.         SetAPen(glob->Window->RPort, glob->PenArray[Backgroundpen]);
  2540.         RectFill(glob->Window->RPort, 0, 0, (glob->ww)-1, (glob->wh)-1);
  2541.         
  2542.         DisposeDTObject(glob->dto);
  2543.         glob->dto = NULL;
  2544.     }
  2545.     
  2546.     BusyPointer(glob, pref);
  2547.     
  2548.     if (glob->dto = (Object *) NewDTObject(pref->Image,
  2549.         DTA_GroupID, GID_PICTURE, 
  2550.         PDTA_DestMode, MODE_V43,
  2551.         PDTA_Remap, TRUE,
  2552.         PDTA_Screen, GetScreen(glob),
  2553.         PDTA_FreeSourceBitMap, TRUE,
  2554.         TAG_DONE) )
  2555.     {
  2556.         SetDTAttrs(glob->dto, NULL, NULL,
  2557.                     PDTA_Remap, TRUE,
  2558.                     PDTA_Screen, GetScreen(glob),
  2559.                     PDTA_FreeSourceBitMap, TRUE,
  2560.                     PDTA_UseFriendBitMap, TRUE,
  2561.                     TAG_DONE );
  2562.         
  2563.         DoMethod( glob->dto, DTM_PROCLAYOUT, NULL, TRUE );
  2564.     }
  2565.     else
  2566.     {
  2567.         LONG errnum=IoErr();
  2568.         UBYTE errstring[80];
  2569.         
  2570.         if (errnum>=DTERROR_UNKNOWN_DATATYPE)
  2571.         {
  2572.             SPrintf(errstring,GetDTString(errnum),pref->Image);
  2573.         }
  2574.         else
  2575.         {
  2576.             Fault(errnum,NULL,errstring,sizeof(errstring));
  2577.         }
  2578.         Message("%s: %s",NULL,pref->Image,errstring);
  2579.     }
  2580.     
  2581.     if (!(InitOrUpdateGraphics(glob,pref)))
  2582.     {
  2583.         Message("Failed to update graphics!",NULL);
  2584.     }
  2585.     
  2586.     if (glob->PaintBitMap)
  2587.     {
  2588.         BltBitMapRastPort(glob->PaintBitMap, 0, 0, glob->Window->RPort, 0, 0, glob->ww, glob->wh, 0xc0);
  2589.     }
  2590.     else EraseRect(glob->Window->RPort, 0, 0, (glob->ww)-1, (glob->wh)-1);
  2591.     
  2592.     NormalPointer(glob, pref);
  2593. }
  2594.  
  2595.  
  2596.  
  2597. /*-------------------------------------------*/
  2598. /* Datatypes hook function for ASL requester */
  2599. /*-------------------------------------------*/
  2600.  
  2601. ULONG __asm __saveds Filter (register __a0 struct Hook *h, register __a2 struct FileRequester *fr, register __a1 struct AnchorPath *ap)
  2602. {
  2603.     struct DataType *dtn;
  2604.     ULONG use = FALSE;
  2605.     UBYTE buffer[300];
  2606.     BPTR lock;
  2607.     
  2608.     if (ap->ap_Info.fib_DirEntryType > 0)
  2609.     {
  2610.         use = TRUE;
  2611.     }
  2612.     else
  2613.     {
  2614.         strncpy (buffer, fr->fr_Drawer, sizeof (buffer));
  2615.         AddPart (buffer, ap->ap_Info.fib_FileName, sizeof (buffer));
  2616.         if (lock = Lock (buffer, ACCESS_READ))
  2617.         {
  2618.             if (dtn = ObtainDataTypeA (DTST_FILE, (APTR) lock, NULL))
  2619.             {
  2620.                 if (dtn->dtn_Header->dth_GroupID == GID_PICTURE)
  2621.                     use = TRUE;
  2622.                 
  2623.                 ReleaseDataType (dtn);
  2624.             }
  2625.             UnLock (lock);
  2626.         }
  2627.     }
  2628.     return (use);
  2629. }
  2630.  
  2631.  
  2632.  
  2633. /*--------------------------------------*/
  2634. /* Select image to load (ASL requester) */
  2635. /*--------------------------------------*/
  2636.  
  2637. BOOL SelectImage(struct Globals *glob, struct Prefs *pref, struct FileRequester **fr, UBYTE *filebuffer, ULONG MaxSize)
  2638. {
  2639.     BOOL Selected=FALSE;
  2640.     
  2641.     UBYTE initialdrawer[200];
  2642.     UBYTE initialfile  [40];
  2643.     
  2644.     struct Hook filter = {NULL, NULL, NULL, NULL, NULL};
  2645.     UBYTE save, *ptr;
  2646.     
  2647.     filter.h_Entry = (HOOKFUNC)Filter;
  2648.     
  2649.     ptr = PathPart(filebuffer);
  2650.     save = *ptr; *ptr = 0;
  2651.     strncpy (initialdrawer,filebuffer,sizeof(initialdrawer));
  2652.     initialdrawer[sizeof(initialdrawer)-1]=0;
  2653.     *ptr = save;
  2654.     strncpy (initialfile, FilePart(filebuffer), sizeof(initialfile));
  2655.     initialfile[sizeof(initialfile)-1]=0;
  2656.     
  2657.     if (!(*fr))
  2658.     {
  2659.         if(!((*fr) = AllocAslRequestTags (ASL_FileRequest,
  2660.                     ASLFR_TitleText,    "Select Picture to load",
  2661.                     ASLFR_PositiveText,    "Load",
  2662.                     ASLFR_RejectIcons,    TRUE,
  2663.                     ASLFR_DoPatterns, TRUE,
  2664.                     TAG_DONE)))
  2665.         {
  2666.             Message("Couldn't allocate asl requester",NULL);
  2667.         }
  2668.     }
  2669.     
  2670.     if (*fr)
  2671.     {
  2672.         Selected = AslRequestTags(*fr,
  2673.             ASLFR_Screen, GetScreen(glob),
  2674.             ASLFR_InitialDrawer, initialdrawer,
  2675.             ASLFR_InitialFile, initialfile,
  2676.             (pref->Flags & PREFF_ASLHOOKS) ? ASLFR_FilterFunc : TAG_IGNORE,    &filter,
  2677.             TAG_DONE);
  2678.         
  2679.         if (Selected)
  2680.         {
  2681.             strncpy (filebuffer, (*fr)->fr_Drawer, MaxSize);
  2682.             AddPart (filebuffer, (*fr)->fr_File,   MaxSize);
  2683.         }
  2684.     }
  2685.     
  2686.     return(Selected);
  2687. }
  2688.  
  2689.  
  2690.  
  2691. /*--------------------------------------*/
  2692. /* MIDI hook function for ASL requester */
  2693. /*--------------------------------------*/
  2694.  
  2695. ULONG __asm __saveds MIDIFilter (register __a0 struct Hook *h, register __a2 struct FileRequester *fr, register __a1 struct AnchorPath *ap)
  2696. {
  2697.     ULONG use = FALSE;
  2698.     
  2699.     UBYTE buffer[300];
  2700.     UBYTE header[20];
  2701.     BPTR file;
  2702.     
  2703.     if (ap->ap_Info.fib_DirEntryType >0)
  2704.         use = TRUE;
  2705.     else
  2706.     {
  2707.         strncpy (buffer, fr->fr_Drawer, sizeof (buffer));
  2708.         AddPart (buffer, ap->ap_Info.fib_FileName, sizeof (buffer));
  2709.         
  2710.         if (file = Open (buffer, MODE_OLDFILE))
  2711.         {
  2712.             if (Read(file,header,sizeof(header)) == sizeof(header))
  2713.             {
  2714.                 if ( ((header[0] == 'M') &&
  2715.                       (header[1] == 'T') &&
  2716.                       (header[2] == 'h') &&
  2717.                       (header[3] == 'd'))
  2718.                     
  2719.                     ||
  2720.                     
  2721.                      ((header[0] == 'X') &&
  2722.                       (header[1] == 'P') &&
  2723.                       (header[2] == 'K') &&
  2724.                       (header[3] == 'F') &&
  2725.                       (header[16]== 'M') &&
  2726.                       (header[17]== 'T') &&
  2727.                       (header[18]== 'h') &&
  2728.                       (header[19]== 'd')) )
  2729.                 {
  2730.                     use = TRUE;
  2731.                 }
  2732.             }
  2733.             Close (file);
  2734.         }
  2735.     }
  2736.     return(use);
  2737. }
  2738.  
  2739.  
  2740.  
  2741. /*----------------------------*/
  2742. /* Select a MIDI file to load */
  2743. /*----------------------------*/
  2744.  
  2745. BOOL SelectMIDI(struct Globals *glob, struct Prefs *pref, struct FileRequester **fr, UBYTE *filebuffer, ULONG MaxSize)
  2746. {
  2747.     BOOL Selected=FALSE;
  2748.     
  2749.     UBYTE initialdrawer[200];
  2750.     UBYTE initialfile  [40];
  2751.     
  2752.     struct Hook filter = {NULL, NULL, NULL, NULL, NULL};
  2753.     UBYTE save, *ptr;
  2754.     
  2755.     filter.h_Entry = (HOOKFUNC)MIDIFilter;
  2756.     
  2757.     ptr = PathPart(filebuffer);
  2758.     save = *ptr; *ptr = 0;
  2759.     strncpy (initialdrawer,filebuffer,sizeof(initialdrawer));
  2760.     initialdrawer[sizeof(initialdrawer)-1]=0;
  2761.     *ptr = save;
  2762.     strncpy (initialfile, FilePart(filebuffer), sizeof(initialfile));
  2763.     initialfile[sizeof(initialfile)-1]=0;
  2764.     
  2765.     if (!(*fr))
  2766.     {
  2767.         if (!((*fr) = AllocAslRequestTags (ASL_FileRequest,
  2768.                     ASLFR_TitleText,    "Select MIDI file to play",
  2769.                     ASLFR_PositiveText,    "Play",
  2770.                     ASLFR_RejectIcons,    TRUE,
  2771.                     ASLFR_DoPatterns, TRUE,
  2772.                     TAG_DONE)))
  2773.         {
  2774.             Message("Couldn't allocate asl requester",NULL);
  2775.         }
  2776.     }
  2777.     
  2778.     if (*fr)
  2779.     {
  2780.         Selected = AslRequestTags(*fr,
  2781.                     ASLFR_Screen, GetScreen(glob),
  2782.                     ASLFR_InitialDrawer, initialdrawer,
  2783.                     ASLFR_InitialFile, initialfile,
  2784.                     (pref->Flags & PREFF_ASLHOOKS) ? ASLFR_FilterFunc : TAG_IGNORE,    &filter,
  2785.                     TAG_DONE);
  2786.         
  2787.         if (Selected)
  2788.         {
  2789.             strncpy (filebuffer, (*fr)->fr_Drawer, MaxSize);
  2790.             AddPart (filebuffer, (*fr)->fr_File,   MaxSize);
  2791.         }
  2792.     }
  2793.     
  2794.     return(Selected);
  2795. }
  2796.  
  2797.  
  2798.  
  2799. /*-----------------------------------*/
  2800. /* Invoke PlayMF to play a MIDI file */
  2801. /*-----------------------------------*/
  2802.  
  2803. void PlayMIDI(struct Globals *glob, struct Prefs *pref)
  2804. {
  2805.     UBYTE CommandString[300];
  2806.     UBYTE *init = "";
  2807.     BPTR lock;
  2808.     BPTR out;
  2809.     BOOL CloseOut = FALSE;
  2810.     
  2811.     if (pref->Flags & PREFF_GM)   init = "GM";
  2812.     if (pref->Flags & PREFF_GS)   init = "GS";
  2813.     if (pref->Flags & PREFF_XG)   init = "XG";
  2814.     if (pref->Flags & PREFF_MT32) init = "MT32";
  2815.     
  2816.     if (lock = Lock("/PlayMF/PlayMF", SHARED_LOCK ))
  2817.     {
  2818.         UnLock(lock);
  2819.         
  2820.         SPrintf(CommandString,"Run >NIL: /PlayMF/PlayMF \42%s\42 LINK=\42%s\42 %s REPLACE", pref->MIDIFile, pref->Link, init);
  2821.     }
  2822.     else
  2823.     {
  2824.         SPrintf(CommandString,"Run >NIL: PlayMF \42%s\42 LINK=\42%s\42 %s REPLACE", pref->MIDIFile, pref->Link, init);
  2825.     }
  2826.     
  2827.     if ((out = Output()) == NULL)
  2828.     {
  2829.         if (out = Open("NIL:", MODE_OLDFILE)) CloseOut = TRUE;
  2830.     }
  2831.     
  2832.     if (!Execute( CommandString, NULL, out))
  2833.     {
  2834.         AsyncMessage(glob,LaunchTask, "Unable to launch PlayMF.\nPlease make sure it is located somewhere in your search path.","Damn");
  2835.     }
  2836.     
  2837.     if (CloseOut) Close(out);
  2838. }
  2839.  
  2840.  
  2841.  
  2842. /*--------------------------*/
  2843. /* Stop PlayMF (if running) */
  2844. /*--------------------------*/
  2845.  
  2846. void StopMIDI(struct Globals *glob, struct Prefs *pref)
  2847. {
  2848.     APTR lock;
  2849.     struct MidiCluster *clust;
  2850.     struct MidiLink *ml;
  2851.     
  2852.     if (lock = LockCAMD(CD_Linkages))
  2853.     {
  2854.         if (clust = FindCluster(pref->Link))
  2855.         {
  2856.             for (ml = (struct MidiLink*)clust->mcl_Senders.lh_Head ;
  2857.                  ml->ml_Node.ln_Succ ;
  2858.                  ml = (struct MidiLink*)ml->ml_Node.ln_Succ )
  2859.             {
  2860.                 if (!stricmp("PlayMF Player", ml->ml_MidiNode->mi_Node.ln_Name))
  2861.                 {
  2862.                     Signal(ml->ml_MidiNode->mi_SigTask, SIGBREAKF_CTRL_C);
  2863.                     break;
  2864.                 }
  2865.             }
  2866.         }
  2867.         UnlockCAMD(lock);
  2868.     }
  2869. }
  2870.