home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / MM1 / SOUNDUTILS / mm1_tracker.lzh / TRACKER4.6 / Amiga / ui.c < prev    next >
Text File  |  1994-11-24  |  16KB  |  633 lines

  1. /* amiga/ui.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* $Id: ui.c,v 1.20 1994/06/22 21:54:12 Espie Exp Espie $
  6.  * $Log: ui.c,v $
  7.  * Revision 1.20  1994/06/22  21:54:12  Espie
  8.  * Split across other files.
  9.  * File requester !
  10.  * Added pause gadget.
  11.  * Uncentralized event handling using event management functions.
  12.  * Changed name to ui_win, added Show gadget.
  13.  * better coding for gadgets.
  14.  * Nasty bug with info: did not close the file properly.
  15.  * Fully working asynchronous interface.
  16.  * User feedback.
  17.  * Added missing autoinit
  18.  * Removed some typecasts.
  19.  * info facility.
  20.  * scroll post-synchronized output.
  21.  * notice.
  22.  * Cursor handling.
  23.  * Used of discard_buffer for premature ending.
  24.  * Mostly working.
  25.  * Just dies with a guru.
  26.  * Plus timing problems at start.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32.  
  33. #include <proto/intuition.h>
  34. #include <proto/gadtools.h>
  35. #include <proto/exec.h>
  36. #include <dos/dos.h>
  37. #include <intuition/intuitionbase.h>
  38.  
  39. #include "defs.h"
  40. #include "extern.h"
  41. #include "amiga/amiga.h"
  42. #include "tags.h"
  43. #include "prefs.h"
  44.  
  45. ID("$Id: ui.c,v 1.20 1994/06/22 21:54:12 Espie Exp Espie $")
  46.  
  47. XT unsigned int inhibit_output;
  48.  
  49. LOCAL void init_ui(void);
  50. LOCAL void do_set_current(VALUE current);
  51. LOCAL void handle_ui_window(GENERIC nothing);
  52.  
  53. LOCAL void (*INIT)(void) = init_ui;
  54.  
  55.  
  56. /* These two variables memorize where we actually are in
  57.  * the current song
  58.  */
  59. LOCAL int current_pattern;
  60.  
  61. #define SMALL_DELAY 3         /* in seconds */
  62.  
  63. /* And these when stuff last changed */
  64. LOCAL ULONG pattern_change_seconds, pattern_change_micros,
  65. song_change_seconds, song_change_micros;
  66.  
  67.  
  68. /* The basic user interface (a simple window) */
  69.  
  70. struct IntuitionBase *IntuitionBase = 0;
  71. struct GfxBase *GfxBase = 0;
  72. LOCAL struct Library *GadtoolsBase = 0;
  73. LOCAL struct Window *ui_win;
  74.  
  75. void set_busy_pointer(BOOL maybe)
  76.    {
  77.    if (IntuitionBase->LibNode.lib_Version < 39)
  78.       return;
  79.    if (ui_win)
  80.       SetWindowPointer(ui_win, WA_BusyPointer, maybe, WA_PointerDelay, TRUE, TAG_DONE, 0);
  81.    }
  82.  
  83. /* for asynchronous easy requests */
  84. LOCAL struct Window *notice_win = 0;
  85.  
  86.    /* for computing length */
  87. LOCAL struct IntuiText it;
  88.  
  89. #define SHIFT 4
  90. #define SPACEX 10
  91. #define SPACEY 4
  92.  
  93. #define WINDOW_TITLE "Experiment IV "        /* the space in case the font is italic */
  94.  
  95. LOCAL struct NewGadget template =
  96.    {
  97.    0, 0,
  98.    0, 0,
  99.    NULL,
  100.    0,
  101.    0,       /* gadget ID */
  102.    0,
  103.    NULL,
  104.    NULL
  105.    };
  106.  
  107. LOCAL struct NewMenu menu_template[] =
  108.    {
  109.    {NM_TITLE,  "Project",        0, 0, 0, 0},
  110.       {NM_ITEM,   "Load song...",   0, 0, 0, (void *)4},
  111.       {NM_ITEM,   "About...",       0, 0, 0, (void *)1},
  112.       {NM_ITEM,   "Quit",           0, 0, 0, (void *)2},
  113.    {NM_TITLE,  "Settings",       0, 0, 0, 0},
  114.          /* WARNING: check item_number if you add menu entries */
  115.       {NM_ITEM,   "PAL",            0, CHECKIT, 6, (void *)50},
  116.       {NM_ITEM,   "NTSC",           0, CHECKIT, 5, (void *)60},
  117.       {NM_ITEM,   "Custom",         0, CHECKIT, 3, (void *)3},
  118.    {NM_END,    0,                0, 0, 0, 0}
  119.    };
  120.  
  121. LOCAL struct Menu *menu = 0;
  122.  
  123. LOCAL APTR vi;
  124. LOCAL struct Screen *pub = 0;
  125. LOCAL struct Gadget *glist, *title_gad, *pattern_gad, *total_gad;
  126.  
  127. /* we precisely have seven gadgets */
  128. #define MAX_GADGET 6
  129.  
  130. /* all labelled with strings */
  131. LOCAL char *label[MAX_GADGET + 1] =
  132.    {
  133.    "|<",
  134.    "<<",
  135.    "//",
  136.    ">>", 
  137.    ">|",
  138.    "?",
  139.    "000",
  140.    };
  141.  
  142. #define G_NEXT 4
  143. #define G_RESTART_PREVIOUS 0
  144. #define G_REWIND 1
  145. #define G_FF 3
  146. #define G_SHOW 5
  147. #define G_PAUSE 2
  148. LOCAL struct ext_message *restart_msg = NULL;
  149.  
  150. LOCAL void cleanup_ui()
  151.    {
  152.    if (restart_msg)
  153.       {
  154.       send(restart_msg, TYPE_UNPAUSE);
  155.       restart_msg = 0;
  156.       }
  157.    if (ui_win)
  158.       {
  159.       remove_signal_handler(ui_win->UserPort->mp_SigBit);
  160.       SetWindowTitles(ui_win, 0, 0);
  161.       ClearMenuStrip(ui_win);
  162.       CloseWindow(ui_win);
  163.       ui_win = 0;
  164.       }
  165.    if (menu)
  166.       FreeMenus(menu);
  167.    if (glist)
  168.       FreeGadgets(glist);
  169.    if (vi)
  170.       FreeVisualInfo(vi);
  171.    if (pub)
  172.       UnlockPubScreen(NULL, pub);
  173.    while (notice_win)
  174.       await_events();
  175.    if (GfxBase)
  176.       CloseLibrary(GfxBase);
  177.    if (IntuitionBase)
  178.       CloseLibrary(IntuitionBase);
  179.    if (GadtoolsBase)
  180.       CloseLibrary(GadtoolsBase);
  181.    }
  182.    
  183.  
  184. LOCAL void init_ui(void)
  185.    {
  186.    struct Gadget *gad;
  187.    int i;
  188.    int max_width;
  189.    int width, height;
  190.    UWORD zoom[4];
  191.  
  192.    at_end(cleanup_ui);
  193.    IntuitionBase = OpenLibrary("intuition.library", 37);
  194.    if (!IntuitionBase)
  195.       end_all("No Intuition");
  196.    GadtoolsBase = OpenLibrary("gadtools.library", 37);
  197.    if (!GadtoolsBase)
  198.       end_all("No gadtools");
  199.    GfxBase = OpenLibrary("graphics.library", 37);
  200.    if (!GfxBase)
  201.       end_all("No graphics");
  202.    pub = LockPubScreen(NULL);
  203.    if (!pub)
  204.       end_all("No pubscreen");
  205.    vi = GetVisualInfo(pub, TAG_END);
  206.    if (!vi)
  207.       end_all("No VI");
  208.       {
  209.       int item_number;
  210.  
  211.       switch(get_pref_scalar(PREF_SPEED))
  212.          {
  213.       case 50:
  214.          item_number = 5; break;
  215.       case 60:
  216.          item_number = 6; break;
  217.       default:
  218.          item_number = 7; break;
  219.          }
  220.       menu_template[item_number].nm_Flags |= CHECKED;
  221.       }
  222.    menu = CreateMenus(menu_template, GTMN_FrontPen, BARDETAILPEN, TAG_END);
  223.    if (!menu)
  224.       end_all("No menus");
  225.    if (!LayoutMenus(menu, vi, TAG_END))
  226.       end_all("Menus badly formed");
  227.       
  228.       /* now to create the gadgets */
  229.       /* Compute max width/height according to the font */
  230.    it.ITextFont = pub->Font;
  231.    template.ng_TextAttr = pub->Font;
  232.    
  233.    max_width = 0;
  234.    for (i = 0; i < MAX_GADGET + 1; i++)
  235.       {
  236.       it.IText = label[i];  
  237.       width = IntuiTextLength(&it);
  238.       if (width > max_width)
  239.          max_width = width;
  240.       }
  241.     
  242.    max_width += SPACEX;
  243.    template.ng_Width = max_width;     
  244.    template.ng_Height = pub->Font->ta_YSize + SPACEY;
  245.  
  246.       /* set up Top/Left Edge of initial gadget according to Wbar */
  247.    template.ng_TopEdge = pub->WBorTop + 1 + 2 * template.ng_Height + SHIFT;
  248.    template.ng_LeftEdge = pub->WBorLeft + SHIFT; 
  249.  
  250.    gad = CreateContext(&glist);
  251.    if (!gad)
  252.       end_all("No context");
  253.    template.ng_VisualInfo = vi;
  254.       /* lay out gadgets */
  255.    for (i = 0; i < MAX_GADGET; i++)
  256.       {
  257.       template.ng_GadgetText = label[i];
  258.       gad = CreateGadget(BUTTON_KIND, gad, &template, TAG_END);
  259.       if (!gad)
  260.          end_all("Bad gadget");
  261.       template.ng_LeftEdge += template.ng_Width + SHIFT;
  262.       template.ng_GadgetID++;
  263.       }
  264.    width = template.ng_LeftEdge + pub->WBorRight;
  265.    height = template.ng_TopEdge + template.ng_Height + pub->WBorBottom + SHIFT;
  266.  
  267.       /* zoom box */
  268.    zoom[0] = ~0;
  269.    zoom[1] = ~0;
  270.    zoom[2] = width;
  271.    zoom[3] = pub->WBorTop + 1 + pub->Font->ta_YSize;
  272.  
  273.       /* title gadget */     
  274.    template.ng_GadgetText = "";
  275.    template.ng_Width = width - SHIFT - pub->WBorLeft - pub->WBorRight;
  276.    template.ng_Width -= 2 * max_width;
  277.    template.ng_TopEdge = pub->WBorTop + 1 + template.ng_Height + SHIFT;
  278.    template.ng_LeftEdge = SHIFT + pub->WBorLeft;
  279.    title_gad = gad = CreateGadget(TEXT_KIND, gad, &template, TAG_END);
  280.    if (!gad)
  281.       end_all("Bad gadget");
  282.       
  283.       /* pattern gadget */
  284.    template.ng_LeftEdge += template.ng_Width + SHIFT;
  285.    template.ng_Width = max_width;
  286.    pattern_gad = gad = CreateGadget(NUMBER_KIND, gad, &template, TAG_END);
  287.    if (!gad)
  288.       end_all("Bad gadget");
  289.  
  290.       /* total pattern */
  291.    template.ng_GadgetText = "/";
  292.    template.ng_LeftEdge += template.ng_Width + SHIFT;
  293.    total_gad = gad = CreateGadget(NUMBER_KIND, gad, &template, TAG_END);
  294.    if (!gad)
  295.       end_all("Bad gadget");
  296.    ui_win = OpenWindowTags(NULL, 
  297.       WA_Title, WINDOW_TITLE,
  298.       WA_Width, width,
  299.       WA_Height, height,
  300.       WA_MinWidth, zoom[2],
  301.       WA_MaxWidth, width,
  302.       WA_MinHeight, zoom[3],
  303.       WA_MaxHeight, height,
  304.       WA_AutoAdjust, TRUE,
  305.       WA_MouseQueue, 35,   /* we can't always answer messages */
  306.       WA_DepthGadget, TRUE,
  307.       WA_CloseGadget, TRUE,
  308.       WA_DragBar, TRUE,
  309.       WA_Zoom, zoom,
  310.       WA_Gadgets, glist,
  311.       WA_IDCMP, IDCMP_CLOSEWINDOW | BUTTONIDCMP | TEXTIDCMP | 
  312.                 IDCMP_REFRESHWINDOW | IDCMP_MENUPICK,
  313.       WA_NewLookMenus, TRUE,
  314.       WA_PubScreen, pub,
  315.       TAG_DONE, 0);
  316.    if (!ui_win)
  317.       end_all("No window");
  318.    GT_RefreshWindow(ui_win, NULL);  
  319.    SetMenuStrip(ui_win, menu);
  320.  
  321.    install_signal_handler(ui_win->UserPort->mp_SigBit, handle_ui_window, 0);
  322.    
  323.    /* build up scroll buffer stuff */
  324.    }
  325.  
  326. struct Screen *obtain_pubscreen(void)
  327.    {
  328.    INIT_ONCE;
  329.    
  330.    return pub;
  331.    }
  332.  
  333. /* Max number of input messages we can remember */
  334. #define MAX_INPUT 20
  335. LOCAL struct tag result[MAX_INPUT +1];
  336. LOCAL int i = 0;
  337.  
  338. LOCAL void handle_ui_window(GENERIC nothing)
  339.    {
  340.    struct IntuiMessage *msg;
  341.    UWORD number;
  342.    struct MenuItem *item;
  343.    int id;
  344.    VALUE temp;
  345.    
  346.    while((msg = GT_GetIMsg(ui_win->UserPort)) && i < MAX_INPUT)
  347.       switch(msg->Class)
  348.          {
  349.       case IDCMP_CLOSEWINDOW:
  350.          GT_ReplyIMsg(msg);
  351.          set_break();
  352.          break;
  353.       case IDCMP_MENUPICK:
  354.          number = msg->Code;
  355.          while (number != MENUNULL)
  356.             {
  357.             item = ItemAddress(menu, msg->Code);
  358.             switch((int)GTMENUITEM_USERDATA(item))
  359.                {
  360.             case 1:
  361.                notice(
  362. "Tracker 4.5  \n\
  363.       by Marc Espie (Marc.Espie@ens.fr)\n\n\
  364. This is a giftware program\n\
  365. If you want, you can send me some money\n\
  366. My address is:\n\
  367.       Espie Marc\n\
  368.       60 rue du 4 septembre\n\
  369.       87100 Limoges\n\
  370.       France\n\n\
  371. For the most recent version:\n\
  372.       ftp Aminet or nic.funet.fi");
  373.                break;
  374.             case 2:
  375.                item = 0;
  376.                set_break();
  377.                break;
  378.             case 4:
  379.                launch_requester();
  380.                break;
  381.             case 50:
  382.             case 60:
  383.                result[i].type = UI_SET_BPM;
  384.                result[i++].data.scalar = (int)GTMENUITEM_USERDATA(item);
  385.                set_pref_scalar(PREF_SPEED, (int)GTMENUITEM_USERDATA(item));
  386.                break;
  387.             default:
  388.                break;
  389.                }
  390.             number = item->NextSelect;
  391.             }
  392.          GT_ReplyIMsg(msg);
  393.          break;
  394.       case IDCMP_REFRESHWINDOW:
  395.          GT_ReplyIMsg(msg);
  396.          GT_BeginRefresh(ui_win);
  397.          GT_EndRefresh(ui_win, TRUE);
  398.          break;
  399.       case IDCMP_GADGETUP:
  400.          id = ((struct Gadget *)msg->IAddress)->GadgetID;
  401.          switch(id)
  402.             {
  403.          case G_NEXT:
  404.             result[i++].type = UI_NEXT_SONG;
  405.             break;
  406.          case G_RESTART_PREVIOUS:
  407.             if (msg->Seconds < song_change_seconds + SMALL_DELAY ||
  408.                 (msg->Seconds == song_change_seconds + SMALL_DELAY && 
  409.                 msg->Micros <= song_change_micros) )
  410.                 {
  411.                 result[i++].type = UI_PREVIOUS_SONG;
  412.                 break;
  413.                 }
  414.             else
  415.                {
  416.                result[i++].type = UI_RESTART;
  417.                song_change_seconds = msg->Seconds;
  418.                song_change_micros = msg->Micros;
  419.                }
  420.             break;
  421.          case G_REWIND:
  422.             result[i].type = UI_JUMP_TO_PATTERN;
  423.             result[i].data.scalar = current_pattern;
  424.             if (msg->Seconds < pattern_change_seconds + SMALL_DELAY ||
  425.                 (msg->Seconds == pattern_change_seconds + SMALL_DELAY && 
  426.                 msg->Micros <= pattern_change_micros) )
  427.                 result[i].data.scalar--;
  428.                    /* give some immediate feedback to the user */
  429.             temp.scalar = result[i].data.scalar;
  430.             do_set_current(temp);
  431.                 i++;
  432.             break;
  433.          case G_FF:
  434.             result[i].type = UI_JUMP_TO_PATTERN;
  435.             result[i].data.scalar = current_pattern + 1;
  436.                   /* give some immediate feedback to the user */
  437.             temp.scalar = result[i].data.scalar;
  438.             do_set_current(temp);
  439.             i++;
  440.             break;
  441.          case G_SHOW:
  442.             set_pref_scalar(PREF_SHOW, TRUE);
  443.             break;
  444.          case G_PAUSE:
  445.             if (restart_msg)
  446.                {
  447.                send(restart_msg, TYPE_UNPAUSE);
  448.                restart_msg = 0;
  449.                }
  450.             else
  451.                {
  452.                struct ext_message *msg;
  453.                
  454.                msg = obtain_message();
  455.                restart_msg = obtain_message();
  456.                send(msg, TYPE_PAUSE);
  457.                }
  458.             }
  459.          GT_ReplyIMsg(msg);
  460.          break;
  461.       default:
  462.          GT_ReplyIMsg(msg);
  463.          }
  464.    }
  465.  
  466.  
  467. void requested_file(struct amiganame *name)
  468.    {
  469.    result[i].data.pointer = name;
  470.    result[i++].type = UI_LOAD_SONG;
  471.    }
  472.  
  473.    
  474. struct tag *get_ui()
  475.    {
  476.  
  477.    INIT_ONCE
  478.  
  479.    if (checkbrk())
  480.       result[i++].type = UI_QUIT;
  481.    
  482.    result[i].type = TAG_END;
  483.    
  484.    i = 0;
  485.    return result;
  486.    }
  487.  
  488.  
  489. void song_title(char *s)
  490.    {
  491.    static char title[25];
  492.  
  493.    INIT_ONCE;
  494.  
  495.    strncpy(title, s, 25);
  496.    if (ui_win)
  497.       GT_SetGadgetAttrs(title_gad, ui_win, 0, GTTX_Text, title, TAG_END);
  498.    /* stamp the time we changed the song */
  499.    CurrentTime(&song_change_seconds, &song_change_micros);
  500.    }
  501.  
  502. void status(char *s)   
  503.    {
  504.    INIT_ONCE;
  505.    
  506.    SetWindowTitles(ui_win, s ? s : WINDOW_TITLE, -1);
  507.    }
  508.  
  509. /* hook to change current pattern */
  510. LOCAL void do_set_current(VALUE p)
  511.    {
  512.    if (!inhibit_output)
  513.       {
  514.       INIT_ONCE;
  515.       if (ui_win)
  516.          GT_SetGadgetAttrs(pattern_gad, ui_win, 0, GTNM_Number, p.scalar, TAG_END);
  517.       }
  518.    current_pattern = p.scalar;
  519.    /* stamp the time we changed the pattern */
  520.    CurrentTime(&pattern_change_seconds, &pattern_change_micros);
  521.    }
  522.  
  523. /* hook to change current pattern total */
  524. LOCAL void do_set_total(VALUE p)
  525.     {
  526.     INIT_ONCE;
  527.    if (ui_win)
  528.       GT_SetGadgetAttrs(total_gad, ui_win, 0, GTNM_Number, p.scalar, TAG_END);
  529.     }
  530.  
  531. void display_pattern(int current, int total, int real)
  532.    {
  533.    struct ext_message *msg;
  534.  
  535.    INIT_ONCE 
  536.  
  537.    msg = obtain_message();
  538.     msg->data.hook.func = do_set_total;
  539.    msg->data.hook.p.scalar = total;
  540.    send(msg, TYPE_SYNC_DO);
  541.  
  542.    msg = obtain_message();
  543.     msg->data.hook.func = do_set_current;
  544.    msg->data.hook.p.scalar = current;
  545.    send(msg, TYPE_SYNC_DO);
  546.    }
  547.  
  548.  
  549.  
  550.  
  551. /***
  552.  ***
  553.  ***    notice() pseudo-system call.
  554.  ***    mostly used to report errors
  555.  ***
  556.  ***    The only difficulty comes from the fact
  557.  ***    that we may be called under any kind of environment
  558.  ***
  559.  ***/
  560.  
  561. #ifdef USE_ARQ
  562. #include "arq.h"
  563. /* arq 1.78 doesn't notice BuildEasyRequest().
  564.    I need to contact Martin Laubach about it
  565.        FidoNet: 2:310/3.14 
  566.        Usenet:  mjl@alison.at (home) 
  567.                                mjl@auto.tuwien.ac.at (work) 
  568.                 {cbmvax!cbmehq,mcsun!tuvie}!cbmvie!alison!mjl 
  569.  
  570.        Peter, the graphics and animation wizard, can be reached
  571.      2:310/42 in FidoNet.  
  572.  */
  573.  
  574. LOCAL struct ExtEasyStruct es =
  575.    {
  576.    0,
  577.    0,
  578.    ARQ_ID_INFO,
  579.    0,
  580.    ARQ_MAGIC,
  581.    0, 0, 0,
  582.    sizeof(struct EasyStruct),
  583.    0,
  584.    "Notice\xa0",
  585.    NULL,
  586.    "Proceed"
  587.    };
  588. LOCAL struct EasyStruct *esp = & (es.Easy);
  589. #else
  590. LOCAL struct EasyStruct es = 
  591.    {
  592.    sizeof(struct EasyStruct),
  593.    0,
  594.    "Notice",
  595.    NULL,
  596.    "Proceed"
  597.    };
  598. LOCAL struct EasyStruct *esp = &es;
  599. #endif
  600.  
  601.  
  602. void handle_notice(struct Window *w)
  603.    {
  604.    if (SysReqHandler(w, 0, FALSE) != -2)
  605.       {
  606.       remove_signal_handler(w->UserPort->mp_SigBit);
  607.       FreeSysRequest(w);
  608.       notice_win = 0;
  609.       }
  610.    }
  611.  
  612. void notice(char *s)
  613.    {
  614.    INIT_ONCE;
  615.    
  616.    if (!IntuitionBase)
  617.       {
  618.       fprintf(stderr, s);
  619.       fputc('\n', stderr);
  620.       }
  621.    else
  622.       {
  623.          /* wait for previous notice to go away */
  624.       while (notice_win)
  625.          await_events();
  626.       
  627.       esp->es_TextFormat = s;
  628.       notice_win = BuildEasyRequest(0, esp, NULL, NULL);
  629.       install_signal_handler(notice_win->UserPort->mp_SigBit, handle_notice, notice_win);
  630.       }
  631.    }
  632.  
  633.