home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 106 / EnigmaAmiga106CD.iso / software / sviluppo / ahisrc / device / requester.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-24  |  47.6 KB  |  1,533 lines

  1. /* $Id: requester.c,v 4.14 1999/05/24 11:06:54 lcs Exp $ */
  2.  
  3. /*
  4.      AHI - Hardware independent audio subsystem
  5.      Copyright (C) 1996-1999 Martin Blom <martin@blom.org>
  6.      
  7.      This library is free software; you can redistribute it and/or
  8.      modify it under the terms of the GNU Library General Public
  9.      License as published by the Free Software Foundation; either
  10.      version 2 of the License, or (at your option) any later version.
  11.      
  12.      This library is distributed in the hope that it will be useful,
  13.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.      Library General Public License for more details.
  16.      
  17.      You should have received a copy of the GNU Library General Public
  18.      License along with this library; if not, write to the
  19.      Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
  20.      MA 02139, USA.
  21. */
  22.  
  23. #include <config.h>
  24. #include <CompilerSpecific.h>
  25.  
  26. #include <math.h>
  27. #include <exec/memory.h>
  28. #include <graphics/rpattr.h>
  29. #include <intuition/gadgetclass.h>
  30. #include <intuition/intuition.h>
  31. #include <intuition/intuitionbase.h>
  32. #include <libraries/gadtools.h>
  33. #include <proto/exec.h>
  34. #include <proto/dos.h>
  35. #include <proto/gadtools.h>
  36. #include <proto/graphics.h>
  37. #include <proto/intuition.h>
  38. #include <proto/utility.h>
  39. #include <clib/ahi_protos.h>
  40. #include <pragmas/ahi_pragmas.h>
  41. #include <proto/ahi_sub.h>
  42. #include <string.h>
  43.  
  44. #include "ahi_def.h"
  45. #include "localize.h"
  46. #include "asmfuncs.h"
  47. #include "modeinfo.h"
  48. #include "debug.h"
  49.  
  50.  
  51. struct AHIAudioModeRequesterExt;
  52.  
  53. static void OpenInfoWindow( struct AHIAudioModeRequesterExt * );
  54. static void CloseInfoWindow( struct AHIAudioModeRequesterExt * );
  55. static void UpdateInfoWindow( struct AHIAudioModeRequesterExt * );
  56.  
  57.  
  58. /******************************************************************************
  59. ** Audio mode requester  ******************************************************
  60. ******************************************************************************/
  61.  
  62. #define MY_IDCMPS (LISTVIEWIDCMP|SLIDERIDCMP|BUTTONIDCMP|IDCMP_SIZEVERIFY|IDCMP_NEWSIZE|IDCMP_REFRESHWINDOW|IDCMP_CLOSEWINDOW|IDCMP_MENUPICK|IDCMP_VANILLAKEY|IDCMP_RAWKEY)
  63. #define MY_INFOIDCMPS (LISTVIEWIDCMP|IDCMP_REFRESHWINDOW|IDCMP_CLOSEWINDOW)
  64.  
  65. #define haveIDCMP   0x0001
  66. #define lockwin     0x0002
  67. #define freqgad     0x0004
  68. #define ownIDCMP    0x0008
  69. #define defaultmode 0x0010
  70.  
  71. static struct TagItem reqboolmap[] =
  72. {
  73.   { AHIR_PrivateIDCMP,   haveIDCMP   },
  74.   { AHIR_SleepWindow,    lockwin     },
  75.   { AHIR_DoMixFreq,      freqgad     },
  76.   { AHIR_DoDefaultMode,  defaultmode },
  77.   { TAG_DONE,            0           }
  78. };
  79.  
  80. #define LASTMODEITEM  1
  81. #define NEXTMODEITEM  2
  82. #define PROPERTYITEM  3
  83. #define RESTOREITEM   4
  84. #define OKITEM        5
  85. #define CANCELITEM    6
  86.  
  87. /* Node for audio mode requester */
  88.  
  89. struct IDnode
  90. {
  91.   struct Node node;
  92.   ULONG       ID;
  93.   char        name[80];
  94. };
  95.  
  96. /* The attribues list */
  97.  
  98. #define ATTRNODES 6
  99.  
  100. struct Attrnode
  101. {
  102.   struct Node node;
  103.   UBYTE       text[80];
  104. };
  105.  
  106.  /* AHIAudioModeRequester extension */
  107. struct AHIAudioModeRequesterExt
  108. {
  109.   struct AHIAudioModeRequester  Req;
  110.   ULONG                         tempAudioID;
  111.   ULONG                         tempFrequency;
  112.   struct Window                *SrcWindow;
  113.   STRPTR                        PubScreenName;
  114.   struct Screen                *Screen;
  115.   ULONG                         Flags;
  116.   struct Hook                  *IntuiMsgFunc;
  117.   struct TextAttr              *TextAttr;
  118.   struct Locale                *Locale;
  119.   STRPTR                        TitleText;
  120.   STRPTR                        PositiveText;
  121.   STRPTR                        NegativeText;
  122.   struct TagItem               *FilterTags;
  123.   struct Hook                  *FilterFunc;
  124.  
  125. //  struct Screen                *PubScreen;
  126.   struct Window                *Window;
  127.   struct Window                *InfoWindow;
  128.   WORD                          gx,gy,gw,gh;
  129.   APTR                          vi;
  130.   struct Gadget                *Gadgets;
  131.   struct Gadget                *InfoGadgets;
  132.   struct Gadget                *InfoListViewGadget;
  133.   struct Gadget                *listviewgadget;
  134.   struct Gadget                *slidergadget;
  135.   struct MinList               *list;
  136.   struct MinList                InfoList;
  137.   struct Menu                  *Menu;
  138.   struct Catalog               *Catalog;
  139.   struct Attrnode               AttrNodes[ATTRNODES];
  140. };
  141.  
  142.  
  143. static struct TextAttr Topaz80 = { "topaz.font", 8, 0, 0, };
  144.  
  145. #define MINSLIDERWIDTH 40
  146.  
  147. #define OKBUTTON      1
  148. #define CANCELBUTTON  2
  149. #define FREQSLIDER    3
  150. #define LISTVIEW      4
  151.  
  152. #define FREQTEXT2     "%lu Hz"
  153. #define FREQLEN2      (5+3) // 5 digits + space + "Hz"
  154.  
  155. static LONG STDARGS SAVEDS IndexToFrequency( struct Gadget *gad, WORD level)
  156. {
  157.   LONG  freq = 0;
  158.   ULONG id;
  159.  
  160.   id = ((struct AHIAudioModeRequesterExt *)gad->UserData)->tempAudioID;
  161.  
  162.   if(id != AHI_DEFAULT_ID)
  163.   {
  164.     AHI_GetAudioAttrs( id, NULL,
  165.                        AHIDB_FrequencyArg, level,
  166.                        AHIDB_Frequency,    (ULONG) &freq,
  167.                        TAG_DONE );
  168.   }
  169.   else
  170.   {
  171.     freq = AHIBase->ahib_Frequency;
  172.   }
  173.   return freq;
  174. }
  175.  
  176. static void FillReqStruct(struct AHIAudioModeRequesterExt *req, struct TagItem *tags)
  177. {
  178. // Check all known tags
  179.   req->SrcWindow=(struct Window *)GetTagData(AHIR_Window,(ULONG)req->SrcWindow,tags);
  180.   req->PubScreenName=(STRPTR)GetTagData(AHIR_PubScreenName,(ULONG)req->PubScreenName,tags);
  181.   req->Screen=(struct Screen *)GetTagData(AHIR_Screen,(ULONG)req->Screen,tags);
  182.   req->IntuiMsgFunc=(struct Hook *)GetTagData(AHIR_IntuiMsgFunc,(ULONG)req->IntuiMsgFunc,tags);
  183.   req->Req.ahiam_UserData=(void *)GetTagData(AHIR_UserData,(ULONG)req->Req.ahiam_UserData,tags);
  184.   req->TextAttr=(struct TextAttr *)GetTagData(AHIR_TextAttr,(ULONG)req->TextAttr,tags);
  185.   req->Locale=(struct Locale *)GetTagData(AHIR_Locale,(ULONG)req->Locale,tags);
  186.   req->TitleText=(STRPTR)GetTagData(AHIR_TitleText,(ULONG)req->TitleText,tags);
  187.   req->PositiveText=(STRPTR)GetTagData(AHIR_PositiveText,(ULONG)req->PositiveText,tags);
  188.   req->NegativeText=(STRPTR)GetTagData(AHIR_NegativeText,(ULONG)req->NegativeText,tags);
  189.   req->Req.ahiam_LeftEdge=GetTagData(AHIR_InitialLeftEdge,req->Req.ahiam_LeftEdge,tags);
  190.   req->Req.ahiam_TopEdge=GetTagData(AHIR_InitialTopEdge,req->Req.ahiam_TopEdge,tags);
  191.   req->Req.ahiam_Width=GetTagData(AHIR_InitialWidth,req->Req.ahiam_Width,tags);
  192.   req->Req.ahiam_Height=GetTagData(AHIR_InitialHeight,req->Req.ahiam_Height,tags);
  193.   req->Req.ahiam_AudioID=GetTagData(AHIR_InitialAudioID,req->Req.ahiam_AudioID,tags);
  194.   req->Req.ahiam_MixFreq=GetTagData(AHIR_InitialMixFreq,req->Req.ahiam_MixFreq,tags);
  195.   req->Req.ahiam_InfoOpened=GetTagData(AHIR_InitialInfoOpened,req->Req.ahiam_InfoOpened,tags);
  196.   req->Req.ahiam_InfoLeftEdge=GetTagData(AHIR_InitialInfoLeftEdge,req->Req.ahiam_InfoLeftEdge,tags);
  197.   req->Req.ahiam_InfoTopEdge=GetTagData(AHIR_InitialInfoTopEdge,req->Req.ahiam_InfoTopEdge,tags);
  198. //  req->Req.ahiam_InfoWidth=GetTagData(AHIR_InitialInfoWidth,req->Req.ahiam_InfoWidth,tags);
  199. //  req->Req.ahiam_InfoHeight=GetTagData(AHIR_InitialInfoHeight,req->Req.ahiam_InfoHeight,tags);
  200.   req->FilterTags=(struct TagItem *)GetTagData(AHIR_FilterTags,(ULONG)req->FilterTags,tags);
  201.   req->FilterFunc=(struct Hook *)GetTagData(AHIR_FilterFunc,(ULONG)req->FilterFunc,tags);
  202.   req->Flags=PackBoolTags(req->Flags,tags,reqboolmap);
  203. }
  204.  
  205. /*
  206. ** Returns the ordinal number of the current audio id.
  207. */
  208.  
  209. static LONG GetSelected(struct AHIAudioModeRequesterExt *req)
  210. {
  211.   struct IDnode *idnode;
  212.   LONG valt=0;
  213.  
  214.   for(idnode=(struct IDnode *)req->list->mlh_Head;
  215.       idnode->node.ln_Succ;
  216.       idnode=(struct IDnode *) idnode->node.ln_Succ)
  217.   {
  218.     if(idnode->ID == req->tempAudioID)
  219.       break;
  220.     else
  221.       valt++;
  222.   }
  223.   if(idnode->node.ln_Succ == NULL)
  224.   {
  225.     valt=~0;
  226.     req->tempAudioID=AHI_INVALID_ID;    // Crashed if this is not done! FIXIT!
  227.   }
  228.   return valt;
  229. }
  230.  
  231. /*
  232. ** Calculates what the current slider level shoud be and how many levels total
  233. */
  234.  
  235. static void GetSliderAttrs(struct AHIAudioModeRequesterExt *req, LONG *levels, LONG *level)
  236. {
  237.   *levels=0;
  238.   *level=0;
  239.   
  240.   AHI_GetAudioAttrs(req->tempAudioID, NULL,
  241.       AHIDB_Frequencies,  (ULONG) levels,
  242.       AHIDB_IndexArg,     (req->tempAudioID == AHI_DEFAULT_ID ? 
  243.                               AHIBase->ahib_Frequency : req->tempFrequency),
  244.       AHIDB_Index,        (ULONG) level,
  245.       TAG_DONE);
  246.  
  247.   if(*level >= *levels)
  248.     *level = *levels-1;
  249.  
  250.   AHI_GetAudioAttrs(req->tempAudioID, NULL,
  251.       AHIDB_FrequencyArg, *level,
  252.       AHIDB_Frequency,    (ULONG) &req->tempFrequency,
  253.       TAG_DONE);
  254. }
  255.  
  256. /*
  257. ** Updates the requester to the current frequency and if 'all'==TRUE, audio mode.
  258. */
  259.  
  260. static void SetSelected(struct AHIAudioModeRequesterExt *req, BOOL all)
  261. {
  262.   LONG  sliderlevels,sliderlevel,selected;
  263.   BOOL  disabled    = FALSE;
  264.   ULONG top         = GTLV_Top;
  265.   ULONG makevisible = GTLV_MakeVisible;
  266.  
  267.   if(all)
  268.   {
  269.     //Set listview
  270.     selected=GetSelected(req);
  271.  
  272.     if( selected == ~0 || GadToolsBase->lib_Version >= 39 )
  273.     {
  274.       top = TAG_IGNORE;
  275.     }
  276.  
  277.     if( selected == ~0 )
  278.     {
  279.       makevisible = TAG_IGNORE;
  280.     }
  281.  
  282.     GT_SetGadgetAttrs(req->listviewgadget, req->Window, NULL,
  283.         top,           selected,
  284.         makevisible,   selected,
  285.         GTLV_Selected, selected,
  286.         TAG_DONE);
  287.   }
  288.  
  289.   //Set slider
  290.   GetSliderAttrs(req,&sliderlevels,&sliderlevel);
  291.  
  292.   if( sliderlevels == 0 || req->tempAudioID == AHI_DEFAULT_ID )
  293.   {
  294.     disabled = TRUE;
  295.   }
  296.  
  297.   GT_SetGadgetAttrs(req->slidergadget, req->Window, NULL,
  298.       GTSL_Max,    sliderlevels-1,
  299.       GTSL_Level,  sliderlevel,
  300.       GA_Disabled, disabled,
  301.       TAG_DONE);
  302.  
  303.   UpdateInfoWindow(req);
  304. }
  305.  
  306.  
  307. /*
  308. ** Positions all gadgets in the requester.
  309. */
  310.  
  311. static BOOL LayOutReq (struct AHIAudioModeRequesterExt *req, struct TextAttr *TextAttr)
  312. {
  313.   struct Gadget *gad;
  314.   struct NewGadget ng;
  315.  
  316.   struct TextAttr *gadtextattr;
  317.   struct TextFont *font;
  318.   LONG   fontwidth,buttonheight,buttonwidth,pixels;
  319.   struct IntuiText intuitext = {1,0,JAM1,0,0,NULL,NULL,NULL};
  320.   LONG  sliderlevels,sliderlevel;
  321.   LONG  selected;
  322.  
  323.   selected=GetSelected(req);
  324.   GetSliderAttrs(req,&sliderlevels,&sliderlevel);
  325.  
  326. // Calculate gadget area
  327.   req->gx=req->Window->BorderLeft+4;
  328.   req->gy=req->Window->BorderTop+2;
  329.   req->gw=req->Window->Width-req->gx-(req->Window->BorderRight+4);
  330.   req->gh=req->Window->Height-req->gy-(req->Window->BorderBottom+2);
  331.  
  332.   if(req->Gadgets)
  333.   {
  334.     RemoveGList(req->Window,req->Gadgets,-1);
  335.     FreeGadgets(req->Gadgets);
  336.     SetAPen(req->Window->RPort,0);
  337.     SetDrMd(req->Window->RPort,JAM1);
  338.     EraseRect(req->Window->RPort, req->Window->BorderLeft, req->Window->BorderTop,
  339.         req->Window->Width-req->Window->BorderRight-1,req->Window->Height-req->Window->BorderBottom-1);
  340.     RefreshWindowFrame(req->Window);
  341.   }
  342.   req->Gadgets=NULL;
  343.   if((gad=CreateContext(&req->Gadgets)))
  344.   {
  345.     if(TextAttr)
  346.       gadtextattr=TextAttr;
  347.     else
  348.       gadtextattr=req->Window->WScreen->Font;
  349.  
  350.     if((font=OpenFont(gadtextattr)))
  351.     {
  352.       fontwidth=font->tf_XSize;
  353.       CloseFont(font);
  354.     }
  355.     else
  356.       return FALSE;
  357.  
  358.     buttonheight=gadtextattr->ta_YSize+6;
  359.     intuitext.ITextFont=gadtextattr;
  360.     intuitext.IText=req->PositiveText;
  361.     buttonwidth=IntuiTextLength(&intuitext);
  362.     intuitext.IText=req->NegativeText;
  363.     pixels=IntuiTextLength(&intuitext);
  364.     buttonwidth=max(pixels,buttonwidth);
  365.     buttonwidth+=4+fontwidth;
  366.  
  367. // Create gadgets and check if they fit
  368.     // Do the two buttons fit?
  369.     if(2*buttonwidth > req->gw)
  370.       return FALSE;
  371.     ng.ng_TextAttr=gadtextattr;
  372.     ng.ng_VisualInfo=req->vi;
  373.     ng.ng_UserData=req;
  374. // OK button
  375.     ng.ng_LeftEdge=req->gx;
  376.     ng.ng_TopEdge=req->gy+req->gh-buttonheight;
  377.     ng.ng_Width=buttonwidth;
  378.     ng.ng_Height=buttonheight;
  379.     ng.ng_GadgetText=req->PositiveText;
  380.     ng.ng_GadgetID=OKBUTTON;
  381.     ng.ng_Flags=PLACETEXT_IN;
  382.     gad=CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);
  383. // Cancel button
  384.     ng.ng_LeftEdge=req->gx+req->gw-ng.ng_Width;
  385.     ng.ng_GadgetText=req->NegativeText;
  386.     ng.ng_GadgetID=CANCELBUTTON;
  387.     gad=CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);
  388. // Frequency
  389.     if(req->Flags & freqgad)
  390.     {
  391.       intuitext.IText = GetString(msgReqFrequency, req->Catalog);
  392.       pixels=IntuiTextLength(&intuitext)+INTERWIDTH;
  393.       if(pixels+MINSLIDERWIDTH+INTERWIDTH+FREQLEN2*fontwidth > req->gw)
  394.         return FALSE;
  395.       ng.ng_Width=req->gw-pixels-INTERWIDTH-FREQLEN2*fontwidth;
  396.       ng.ng_LeftEdge=req->gx+pixels;
  397.       ng.ng_TopEdge-=2+buttonheight;
  398.       ng.ng_GadgetText = GetString(msgReqFrequency, req->Catalog);
  399.       ng.ng_GadgetID=FREQSLIDER;
  400.       ng.ng_Flags=PLACETEXT_LEFT;
  401.       gad=CreateGadget(SLIDER_KIND,gad,&ng,
  402.           GTSL_Min,0,
  403.           GTSL_Max,sliderlevels-1,
  404.           GTSL_Level,sliderlevel,
  405.           GTSL_LevelFormat, (ULONG) FREQTEXT2,
  406.           GTSL_MaxLevelLen,FREQLEN2,
  407.           GTSL_LevelPlace,PLACETEXT_RIGHT,
  408.           GTSL_DispFunc, (ULONG) IndexToFrequency,
  409.           GA_RelVerify,TRUE,
  410.           GA_Disabled,!sliderlevels || (req->tempAudioID == AHI_DEFAULT_ID),
  411.           TAG_DONE);
  412.       req->slidergadget=gad;   // Save for HadleReq()...
  413.     }
  414. // ListView
  415.     if((ng.ng_Height=ng.ng_TopEdge-2-req->gy) < buttonheight)
  416.       return FALSE;
  417.     ng.ng_LeftEdge=req->gx;
  418.     ng.ng_TopEdge=req->gy;
  419.     ng.ng_Width=req->gw;
  420.     ng.ng_GadgetText=NULL,
  421.     ng.ng_GadgetID=LISTVIEW;
  422.     ng.ng_Flags=PLACETEXT_ABOVE;
  423.     gad=CreateGadget(LISTVIEW_KIND,gad,&ng,
  424.         GTLV_ScrollWidth,(fontwidth>8 ? fontwidth*2 : 18),
  425.         GTLV_Labels, (ULONG) req->list,
  426.         GTLV_ShowSelected,NULL,
  427.         ((selected == ~0) || (GadToolsBase->lib_Version >= 39) ? TAG_IGNORE : GTLV_Top),selected,
  428.         (selected == ~0 ? TAG_IGNORE : GTLV_MakeVisible),selected,
  429.         GTLV_Selected,selected,
  430.         TAG_DONE);
  431.     req->listviewgadget=gad;   // Save for HadleReq()...
  432.  
  433.     if(!gad)
  434.       return FALSE;
  435.   }
  436.   else
  437.     return FALSE;
  438.  
  439.   AddGList(req->Window,req->Gadgets,~0,-1,NULL);
  440.   RefreshGList(req->Gadgets,req->Window,NULL,-1);
  441.   GT_RefreshWindow(req->Window,NULL);
  442.  
  443.   return TRUE;
  444. }
  445.  
  446.  
  447.  
  448. /* these functions close an Intuition window
  449.  * that shares a port with other Intuition
  450.  * windows or IPC customers.
  451.  *
  452.  * We are careful to set the UserPort to
  453.  * null before closing, and to free
  454.  * any messages that it might have been
  455.  * sent.
  456.  */
  457.  
  458. /* remove and reply all IntuiMessages on a port that
  459.  * have been sent to a particular window
  460.  * (note that we don't rely on the ln_Succ pointer
  461.  *  of a message after we have replied it)
  462.  */
  463. static void StripIntuiMessages( struct MsgPort *mp, struct Window *win )
  464. {
  465.     struct IntuiMessage *msg;
  466.     struct Node *succ;
  467.  
  468.     msg = (struct IntuiMessage *) mp->mp_MsgList.lh_Head;
  469.  
  470.     while((succ =  msg->ExecMessage.mn_Node.ln_Succ)) {
  471.  
  472.         if( msg->IDCMPWindow ==  win ) {
  473.  
  474.             /* Intuition is about to free this message.
  475.              * Make sure that we have politely sent it back.
  476.              */
  477.             Remove( (struct Node *) msg );
  478.  
  479.             ReplyMsg( (struct Message *) msg );
  480.         }
  481.             
  482.         msg = (struct IntuiMessage *) succ;
  483.     }
  484. }
  485.  
  486. static void CloseWindowSafely( struct Window *win )
  487. {
  488.     /* we forbid here to keep out of race conditions with Intuition */
  489.     Forbid();
  490.  
  491.     /* send back any messages for this window 
  492.      * that have not yet been processed
  493.      */
  494.     StripIntuiMessages( win->UserPort, win );
  495.  
  496.     /* clear UserPort so Intuition will not free it */
  497.     win->UserPort = NULL;
  498.  
  499.     /* tell Intuition to stop sending more messages */
  500.     ModifyIDCMP( win, 0L );
  501.  
  502.     /* turn multitasking back on */
  503.     Permit();
  504.  
  505.     /* and really close the window */
  506.     CloseWindow( win );
  507. }
  508.  
  509. static BOOL HandleReq( struct AHIAudioModeRequesterExt *req )
  510.  
  511. // Returns FALSE if requester was cancelled
  512.  
  513. {
  514.   BOOL done=FALSE,rc=TRUE;
  515.   ULONG class,sec,oldsec=0,micro,oldmicro=0,oldid=AHI_INVALID_ID;
  516.   UWORD code;
  517.   UWORD qual;
  518.   struct Gadget *pgsel;
  519.   struct IntuiMessage *imsg;
  520.   struct IDnode *idnode;
  521.   LONG   sliderlevels,sliderlevel,i,selected;
  522.   struct MenuItem *item;
  523.  
  524.   while(!done)
  525.   {
  526.     Wait(1L << req->Window->UserPort->mp_SigBit);
  527.  
  528.     while ((imsg=GT_GetIMsg(req->Window->UserPort)) != NULL )
  529.     {
  530.  
  531.       if(imsg->IDCMPWindow == req->InfoWindow)
  532.       {
  533.         class = imsg->Class;
  534.         GT_ReplyIMsg(imsg);
  535.  
  536.         switch(class)
  537.         {
  538.         case IDCMP_CLOSEWINDOW:
  539.           CloseInfoWindow(req);
  540.           break;
  541.         case IDCMP_REFRESHWINDOW :
  542.           GT_BeginRefresh(req->InfoWindow);
  543.           GT_EndRefresh(req->InfoWindow,TRUE);
  544.           break;
  545.         }
  546.         continue; // Get next IntuiMessage
  547.       }
  548.  
  549.       else if(imsg->IDCMPWindow != req->Window) // Not my window!
  550.       {
  551.         if(req->IntuiMsgFunc)
  552.           CallHookPkt(req->IntuiMsgFunc,req,imsg);
  553.         // else what to do??? Reply and forget? FIXIT!
  554.         continue;
  555.       }
  556.  
  557.       sec=imsg->Seconds;
  558.       micro=imsg->Micros;
  559.       qual=imsg->Qualifier;
  560.       class=imsg->Class;
  561.       code=imsg->Code;
  562.       pgsel=(struct Gadget *)imsg->IAddress; // pgsel illegal if not gadget
  563.       GT_ReplyIMsg(imsg);
  564.  
  565.       switch ( class )
  566.       {
  567.       case IDCMP_RAWKEY:
  568.         switch (code)
  569.         {
  570.         case 0x4c: // Cursor Up
  571.           selected=GetSelected(req);
  572.           if(selected == ~0)
  573.             selected=0;
  574.           if(selected > 0)
  575.             selected--;
  576.           idnode=(struct IDnode *)req->list->mlh_Head;
  577.           for(i=0;i<selected;i++)
  578.             idnode=(struct IDnode *)idnode->node.ln_Succ;
  579.           req->tempAudioID=idnode->ID;
  580.           SetSelected(req,TRUE);
  581.           break;
  582.         case 0x4d: // Cursor Down
  583.           selected=GetSelected(req);
  584.           selected++; // ~0 => 0
  585.           idnode=(struct IDnode *)req->list->mlh_Head;
  586.           for(i=0;i<selected;i++)
  587.             if(idnode->node.ln_Succ->ln_Succ)
  588.               idnode=(struct IDnode *)idnode->node.ln_Succ;
  589.           req->tempAudioID=idnode->ID;
  590.           SetSelected(req,TRUE);
  591.           break;
  592.         case 0x4e: // Cursor Right
  593.           GetSliderAttrs(req,&sliderlevels,&sliderlevel);
  594.           sliderlevel += (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? 10 :1);
  595.           if(sliderlevel >= sliderlevels)
  596.             sliderlevel=sliderlevels-1;
  597.           AHI_GetAudioAttrs(req->tempAudioID, NULL,
  598.               AHIDB_FrequencyArg,sliderlevel,
  599.               AHIDB_Frequency, (ULONG) &req->tempFrequency,
  600.               TAG_DONE);
  601.           SetSelected(req,FALSE);
  602.           break;
  603.         case 0x4f: // Cursor Left
  604.           GetSliderAttrs(req,&sliderlevels,&sliderlevel);
  605.           sliderlevel -= (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? 10 :1);
  606.           if(sliderlevel < 0)
  607.             sliderlevel=0;
  608.           AHI_GetAudioAttrs(req->tempAudioID, NULL,
  609.               AHIDB_FrequencyArg,sliderlevel,
  610.               AHIDB_Frequency, (ULONG) &req->tempFrequency,
  611.               TAG_DONE);
  612.           SetSelected(req,FALSE);
  613.           break;
  614.         }
  615.         break;
  616.       case IDCMP_GADGETUP :
  617.         switch ( pgsel->GadgetID )
  618.         {
  619.         case OKBUTTON:
  620.           done=TRUE;
  621.           break;
  622.         case CANCELBUTTON:
  623.           done=TRUE;
  624.           rc=FALSE;
  625.           break;
  626.         case FREQSLIDER:
  627.           AHI_GetAudioAttrs(req->tempAudioID, NULL,
  628.               AHIDB_FrequencyArg,code,
  629.               AHIDB_Frequency, (ULONG) &req->tempFrequency,
  630.               TAG_DONE);
  631.           break;
  632.         case LISTVIEW:
  633.           idnode=(struct IDnode *)req->list->mlh_Head;
  634.           for(i=0;i<code;i++)
  635.             idnode=(struct IDnode *)idnode->node.ln_Succ;
  636.           req->tempAudioID=idnode->ID;
  637.           SetSelected(req,FALSE);
  638.           // Test doubleclick and save timestamp
  639.           if( (oldid == req->tempAudioID) && DoubleClick(oldsec,oldmicro,sec,micro))
  640.             done=TRUE;
  641.           oldsec=sec;
  642.           oldmicro=micro;
  643.           oldid=req->tempAudioID;
  644.  
  645.           break;
  646.         }
  647.         break;
  648.  
  649.       case IDCMP_NEWSIZE:
  650.         if(!(LayOutReq(req,req->TextAttr)))
  651.           if(!(LayOutReq(req,&Topaz80)))
  652.           {
  653.             // ERROR! Quit.
  654.             done=TRUE;
  655.             break;
  656.           }
  657.         break;
  658.       case IDCMP_CLOSEWINDOW:
  659.         done=TRUE;
  660.         rc=FALSE;
  661.         break;
  662.       case IDCMP_REFRESHWINDOW :
  663.         GT_BeginRefresh(req->Window);
  664.         GT_EndRefresh(req->Window,TRUE);
  665.         break;
  666.       case IDCMP_SIZEVERIFY:
  667.         break;
  668.       case IDCMP_MENUPICK:
  669.         while((code != MENUNULL) && !done)
  670.         {
  671.           item=ItemAddress(req->Menu, code);
  672.           switch((ULONG)GTMENUITEM_USERDATA(item))
  673.           {
  674.           case LASTMODEITEM:
  675.             selected=GetSelected(req);
  676.             if(selected == ~0)
  677.               selected=0;
  678.             if(selected > 0)
  679.               selected--;
  680.             idnode=(struct IDnode *)req->list->mlh_Head;
  681.             for(i=0;i<selected;i++)
  682.               idnode=(struct IDnode *)idnode->node.ln_Succ;
  683.             req->tempAudioID=idnode->ID;
  684.             SetSelected(req,TRUE);
  685.             break;
  686.           case NEXTMODEITEM:
  687.             selected=GetSelected(req);
  688.             selected++; // ~0 => 0
  689.             idnode=(struct IDnode *)req->list->mlh_Head;
  690.             for(i=0;i<selected;i++)
  691.               if(idnode->node.ln_Succ->ln_Succ)
  692.                 idnode=(struct IDnode *)idnode->node.ln_Succ;
  693.             req->tempAudioID=idnode->ID;
  694.             SetSelected(req,TRUE);
  695.             break;
  696.           case PROPERTYITEM:
  697.             OpenInfoWindow(req);
  698.             break;
  699.           case RESTOREITEM:
  700.             req->tempAudioID=req->Req.ahiam_AudioID;
  701.             req->tempFrequency=req->Req.ahiam_MixFreq;
  702.             SetSelected(req,TRUE);
  703.             break;
  704.           case OKITEM:
  705.             done=TRUE;
  706.             break;
  707.           case CANCELITEM:
  708.             done=TRUE;
  709.             rc=FALSE;
  710.             break;
  711.           }
  712.           code = item->NextSelect;
  713.         }
  714.         break;
  715.       }
  716.     }
  717.   }
  718.  
  719.   if(rc)
  720.   {
  721.     req->Req.ahiam_AudioID = req->tempAudioID;
  722.  
  723.     if(req->tempAudioID != AHI_DEFAULT_ID)
  724.     {
  725.       req->Req.ahiam_MixFreq = req->tempFrequency;
  726.     }
  727.     else
  728.     {
  729.       req->Req.ahiam_MixFreq = AHI_DEFAULT_FREQ;
  730.     }
  731.   }
  732.   return rc;
  733. }
  734.  
  735.  
  736. static void OpenInfoWindow( struct AHIAudioModeRequesterExt *req )
  737. {
  738.   struct Gadget *gad;
  739.   struct NewGadget ng;
  740.  
  741.  
  742.   if(req->InfoWindow == NULL)
  743.   {
  744.     req->InfoWindow=OpenWindowTags(NULL,
  745.       WA_Left,              req->Req.ahiam_InfoLeftEdge,
  746.       WA_Top,               req->Req.ahiam_InfoTopEdge,
  747.       WA_Width,             req->Req.ahiam_InfoWidth,
  748.       WA_Height,            req->Req.ahiam_InfoHeight,
  749.       WA_Title,             (ULONG) GetString(msgReqInfoTitle, req->Catalog),
  750.       WA_CustomScreen,      (ULONG) req->Window->WScreen,
  751.       WA_PubScreenFallBack, TRUE,
  752.       WA_DragBar,           TRUE,
  753.       WA_DepthGadget,       TRUE,
  754.       WA_CloseGadget,       TRUE,
  755.       WA_Activate,          FALSE,
  756.       WA_SimpleRefresh,     TRUE,
  757.       WA_AutoAdjust,        TRUE,
  758.       WA_IDCMP,             0,
  759.       WA_NewLookMenus,      TRUE,
  760.       TAG_DONE);
  761.  
  762.     if(req->InfoWindow)
  763.     {
  764.       req->InfoWindow->UserPort = req->Window->UserPort;
  765.       ModifyIDCMP(req->InfoWindow, MY_INFOIDCMPS);
  766.  
  767.       if((gad = CreateContext(&req->InfoGadgets)))
  768.       {
  769.         ng.ng_TextAttr    = req->TextAttr;
  770.         ng.ng_VisualInfo  = req->vi;
  771.         ng.ng_LeftEdge    = req->InfoWindow->BorderLeft+4;
  772.         ng.ng_TopEdge     = req->InfoWindow->BorderTop+2;
  773.         ng.ng_Width       = req->InfoWindow->Width
  774.                           - (req->InfoWindow->BorderLeft+4)
  775.                           - (req->InfoWindow->BorderRight+4);
  776.         ng.ng_Height      = req->InfoWindow->Height
  777.                           - (req->InfoWindow->BorderTop+2)
  778.                           - (req->InfoWindow->BorderBottom+2);
  779.     
  780.         ng.ng_GadgetText  = NULL;
  781.         ng.ng_GadgetID    = 0;
  782.         ng.ng_Flags       = PLACETEXT_ABOVE;
  783.         gad = CreateGadget(LISTVIEW_KIND, gad, &ng,
  784.             GTLV_ReadOnly,  TRUE,
  785.             TAG_DONE);
  786.         req->InfoListViewGadget = gad;
  787.  
  788.         if(gad)
  789.         {
  790.           AddGList(req->InfoWindow, req->InfoGadgets, ~0, -1, NULL);
  791.           RefreshGList(req->InfoGadgets, req->InfoWindow, NULL, -1);
  792.           GT_RefreshWindow(req->InfoWindow, NULL);
  793.           UpdateInfoWindow(req);
  794.         }
  795.       }
  796.     }
  797.   }
  798. }
  799.  
  800.  
  801. static void UpdateInfoWindow( struct AHIAudioModeRequesterExt *req )
  802. {
  803.   LONG id=0, bits=0, stereo=0, pan=0, hifi=0, channels=0, minmix=0, maxmix=0,
  804.        record=0, fullduplex=0;
  805.   int i;
  806.  
  807.   id = req->tempAudioID;
  808.   if(id == AHI_DEFAULT_ID)
  809.   {
  810.     id = AHIBase->ahib_AudioMode;
  811.   }
  812.   if(req->InfoWindow)
  813.   {
  814.     AHI_GetAudioAttrs(id, NULL,
  815.       AHIDB_Stereo,       (ULONG) &stereo,
  816.       AHIDB_Panning,      (ULONG) &pan,
  817.       AHIDB_HiFi,         (ULONG) &hifi,
  818.       AHIDB_Record,       (ULONG) &record,
  819.       AHIDB_FullDuplex,   (ULONG) &fullduplex,
  820.       AHIDB_Bits,         (ULONG) &bits,
  821.       AHIDB_MaxChannels,  (ULONG) &channels,
  822.       AHIDB_MinMixFreq,   (ULONG) &minmix,
  823.       AHIDB_MaxMixFreq,   (ULONG) &maxmix,
  824.       TAG_DONE);
  825.  
  826.     GT_SetGadgetAttrs(req->InfoListViewGadget, req->InfoWindow, NULL,
  827.         GTLV_Labels, ~0,
  828.         TAG_DONE);
  829.  
  830.     NewList((struct List *) &req->InfoList);
  831.     for(i=0; i<ATTRNODES; i++)
  832.     {
  833.       req->AttrNodes[i].node.ln_Name = req->AttrNodes[i].text;
  834.       req->AttrNodes[i].text[0]      = '\0';
  835.       req->AttrNodes[i].node.ln_Type = NT_USER;
  836.       req->AttrNodes[i].node.ln_Pri  = 0;
  837.     }
  838.  
  839.     i = 0;
  840.     AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
  841.     Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoAudioID, req->Catalog),
  842.         id);
  843.     AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
  844.     Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoResolution, req->Catalog),
  845.         bits, GetString((stereo ?
  846.           (pan ? msgReqInfoStereoPan : msgReqInfoStereo) :
  847.           msgReqInfoMono), req->Catalog));
  848.     AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
  849.     Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoChannels, req->Catalog),
  850.         channels);
  851.     AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
  852.     Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoMixrate, req->Catalog),
  853.         minmix, maxmix);
  854.     if(hifi)
  855.     {
  856.       AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
  857.       Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoHiFi, req->Catalog));
  858.     }
  859.     if(record)
  860.     {
  861.       AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
  862.       Sprintf(req->AttrNodes[i++].text, GetString(
  863.           fullduplex ? msgReqInfoRecordFull : msgReqInfoRecordHalf, req->Catalog));
  864.     }
  865.  
  866.     GT_SetGadgetAttrs(req->InfoListViewGadget, req->InfoWindow, NULL,
  867.         GTLV_Labels, (ULONG) &req->InfoList,
  868.         TAG_DONE);
  869.   }
  870. }
  871.  
  872. static void CloseInfoWindow( struct AHIAudioModeRequesterExt *req )
  873. {
  874.   if(req->InfoWindow)
  875.   {
  876.     req->Req.ahiam_InfoOpened   = TRUE;
  877.     req->Req.ahiam_InfoLeftEdge = req->InfoWindow->LeftEdge;
  878.     req->Req.ahiam_InfoTopEdge  = req->InfoWindow->TopEdge;
  879.     req->Req.ahiam_InfoWidth    = req->InfoWindow->Width;
  880.     req->Req.ahiam_InfoHeight   = req->InfoWindow->Height;
  881.     CloseWindowSafely(req->InfoWindow);
  882.     req->InfoWindow = NULL;
  883.  
  884.   }
  885.   else
  886.   {
  887.     req->Req.ahiam_InfoOpened   = FALSE;
  888.  
  889.   }
  890.  
  891.   FreeGadgets(req->InfoGadgets);
  892.   req->InfoGadgets = NULL;
  893. }
  894.  
  895.  
  896. /******************************************************************************
  897. ** AHI_AllocAudioRequestA *****************************************************
  898. ******************************************************************************/
  899.  
  900. /****** ahi.device/AHI_AllocAudioRequestA ***********************************
  901. *
  902. *   NAME
  903. *       AHI_AllocAudioRequestA -- allocate an audio mode requester.
  904. *       AHI_AllocAudioRequest -- varargs stub for AHI_AllocAudioRequestA()
  905. *
  906. *   SYNOPSIS
  907. *       requester = AHI_AllocAudioRequestA( tags );
  908. *       D0                                  A0
  909. *
  910. *       struct AHIAudioModeRequester *AHI_AllocAudioRequestA(
  911. *           struct TagItem * );
  912. *
  913. *       requester = AHI_AllocAudioRequest( tag1, ... );
  914. *
  915. *       struct AHIAudioModeRequester *AHI_AllocAudioRequest( Tag, ... );
  916. *
  917. *   FUNCTION
  918. *       Allocates an audio mode requester data structure.
  919. *
  920. *   INPUTS
  921. *       tags - A pointer to an optional tag list specifying how to initialize
  922. *           the data structure returned by this function. See the
  923. *           documentation for AHI_AudioRequestA() for an explanation of how
  924. *           to use the currently defined tags.
  925. *
  926. *   RESULT
  927. *       requester - An initialized requester data structure, or NULL on
  928. *           failure. 
  929. *
  930. *   EXAMPLE
  931. *
  932. *   NOTES
  933. *       The requester data structure is READ-ONLY and can only be modified
  934. *       by using tags!
  935. *
  936. *   BUGS
  937. *
  938. *   SEE ALSO
  939. *      AHI_AudioRequestA(), AHI_FreeAudioRequest()
  940. *
  941. ****************************************************************************
  942. *
  943. */
  944.  
  945. struct AHIAudioModeRequester * ASMCALL
  946. AllocAudioRequestA( REG(a0, struct TagItem *tags),
  947.                     REG(a6, struct AHIBase *AHIBase) )
  948. {
  949.   struct AHIAudioModeRequesterExt *req;
  950.  
  951.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  952.   {
  953.     Debug_AllocAudioRequestA(tags);
  954.   }
  955.  
  956.   if((req=AllocVec(sizeof(struct AHIAudioModeRequesterExt),MEMF_CLEAR)))
  957.   {
  958. // Fill in defaults
  959.     req->Req.ahiam_LeftEdge   = 30;
  960.     req->Req.ahiam_TopEdge    = 20;
  961.     req->Req.ahiam_Width      = 318;
  962.     req->Req.ahiam_Height     = 198;
  963.     req->Req.ahiam_AudioID    = AHI_INVALID_ID;
  964.     req->Req.ahiam_MixFreq    = AHIBase->ahib_Frequency;
  965.     req->Req.ahiam_InfoWidth  = 280;
  966.     req->Req.ahiam_InfoHeight = 112;
  967.  
  968.     req->PubScreenName        = (STRPTR) -1;
  969.  
  970.     FillReqStruct(req,tags);
  971.   }
  972.  
  973.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  974.   {
  975.     KPrintF("=>0x%08lx\n",req);
  976.   }
  977.  
  978.   return (struct AHIAudioModeRequester *) req;
  979. }
  980.  
  981.  
  982. /******************************************************************************
  983. ** AHI_AudioRequestA **********************************************************
  984. ******************************************************************************/
  985.  
  986. /****** ahi.device/AHI_AudioRequestA ****************************************
  987. *
  988. *   NAME
  989. *       AHI_AudioRequestA -- get an audio mode from user using an requester.
  990. *       AHI_AudioRequest -- varargs stub for AHI_AudioRequestA()
  991. *
  992. *   SYNOPSIS
  993. *       success = AHI_AudioRequestA( requester, tags );
  994. *       D0                           A0         A1
  995. *
  996. *       BOOL AHI_AudioRequestA( struct AHIAudioModeRequester *,
  997. *           struct TagItem * );
  998. *
  999. *       result = AHI_AudioRequest( requester, tag1, ... );
  1000. *
  1001. *       BOOL AHI_AudioRequest( struct AHIAudioModeRequester *, Tag, ... );
  1002. *
  1003. *   FUNCTION
  1004. *       Prompts the user for an audio mode, based on the modifying tags.
  1005. *       If the user cancels or the system aborts the request, FALSE is
  1006. *       returned, otherwise the requester's data structure reflects the
  1007. *       user input.
  1008. *
  1009. *       Note that tag values stay in effect for each use of the requester
  1010. *       until they are cleared or modified by passing the same tag with a
  1011. *       new value.
  1012. *
  1013. *   INPUTS
  1014. *       requester - Requester structure allocated with
  1015. *           AHI_AllocAudioRequestA(). If this parameter is NULL, this
  1016. *           function will always return FALSE with a dos.library/IoErr()
  1017. *           result of ERROR_NO_FREE_STORE.
  1018. *       tags - Pointer to an optional tag list which may be used to control
  1019. *           features of the requester.
  1020. *
  1021. *   TAGS
  1022. *       Tags used for the requester (they look remarkable similar to the
  1023. *       screen mode requester in ASL, don't they? ;-) )
  1024. *
  1025. *       AHIR_Window (struct Window *) - Parent window of requester. If no
  1026. *           AHIR_Screen tag is specified, the window structure is used to
  1027. *           determine on which screen to open the requesting window.
  1028. *
  1029. *       AHIR_PubScreenName (STRPTR) - Name of a public screen to open on.
  1030. *           This overrides the screen used by AHIR_Window.
  1031. *
  1032. *       AHIR_Screen (struct Screen *) - Screen on which to open the
  1033. *           requester. This overrides the screen used by AHIR_Window or by
  1034. *           AHIR_PubScreenName.
  1035. *
  1036. *       AHIR_PrivateIDCMP (BOOL) - When set to TRUE, this tells AHI to
  1037. *           allocate a new IDCMP port for the requesting window. If not
  1038. *           specified or set to FALSE, and if AHIR_Window is provided, the
  1039. *           requesting window will share AHIR_Window's IDCMP port.
  1040. *
  1041. *       AHIR_IntuiMsgFunc (struct Hook *) - A function to call whenever an
  1042. *           unknown Intuition message arrives at the message port being used
  1043. *           by the requesting window. The function receives the following
  1044. *           parameters:
  1045. *               A0 - (struct Hook *)
  1046. *               A1 - (struct IntuiMessage *)
  1047. *               A2 - (struct AHIAudioModeRequester *)
  1048. *
  1049. *       AHIR_SleepWindow (BOOL) - When set to TRUE, this tag will cause the
  1050. *           window specified by AHIR_Window to be "put to sleep". That is, a
  1051. *           busy pointer will be displayed in the parent window, and no
  1052. *           gadget or menu activity will be allowed. This is done by opening
  1053. *           an invisible Intuition Requester in the parent window.
  1054. *
  1055. *       AHIR_UserData (APTR) - A 32-bit value that is simply copied in the
  1056. *           ahiam_UserData field of the requester structure.
  1057. *
  1058. *       AHIR_TextAttr (struct TextAttr *) - Font to be used for the
  1059. *           requesting window's gadgets and menus. If this tag is not
  1060. *           provided or its value is NULL, the default font of the screen
  1061. *           on which the requesting window opens will be used. This font
  1062. *           must already be in memory as AHI calls OpenFont() and not
  1063. *           OpenDiskFont().
  1064. *
  1065. *       AHIR_Locale (struct Locale *) - Locale to use for the requesting
  1066. *           window. This determines the language used for the requester's
  1067. *           gadgets and menus. If this tag is not provided or its value is
  1068. *           NULL, the system's current default locale will be used.
  1069. *
  1070. *       AHIR_TitleText (STRPTR) - Title to use for the requesting window.
  1071. *           Default is no title.
  1072. *
  1073. *       AHIR_PositiveText (STRPTR) - Label of the positive gadget in the
  1074. *           requester. English default is "OK".
  1075. *
  1076. *       AHIR_NegativeText (STRPTR) - Label of the negative gadget in the
  1077. *           requester. English default is "Cancel".
  1078. *
  1079. *       AHIR_InitialLeftEdge (WORD) - Suggested left edge of requesting
  1080. *           window.
  1081. *
  1082. *       AHIR_InitialTopEdge (WORD) - Suggested top edge of requesting
  1083. *           window.
  1084. *
  1085. *       AHIR_InitialWidth (WORD) - Suggested width of requesting window.
  1086. *
  1087. *       AHIR_InitialHeight (WORD) - Suggested height of requesting window.
  1088. *
  1089. *       AHIR_InitialAudioID (ULONG) - Initial setting of the Mode list view
  1090. *           gadget (ahiam_AudioID). Default is ~0 (AHI_INVALID_ID), which
  1091. *           means that no mode will be selected.
  1092. *
  1093. *       AHIR_InitialMixFreq (ULONG) - Initial setting of the frequency
  1094. *           slider. Default is the lowest frequency supported.
  1095. *
  1096. *       AHIR_InitialInfoOpened (BOOL) - Whether to open the property
  1097. *           information window automatically. Default is FALSE.
  1098. *
  1099. *       AHIR_InitialInfoLeftEdge (WORD) - Initial left edge of information
  1100. *           window.
  1101. *
  1102. *       AHIR_InitialInfoTopEdge (WORD) - Initial top edge of information
  1103. *           window.
  1104. *
  1105. *       AHIR_DoMixFreq (BOOL) - Set this tag to TRUE to cause the requester
  1106. *           to display the frequency slider gadget. Default is FALSE.
  1107. *
  1108. *       AHIR_DoDefaultMode (BOOL) - Set this tag to TRUE to let the user
  1109. *           select the mode she has set in the preferences program. If she
  1110. *           selects this mode,  ahiam_AudioID will be AHI_DEFAULT_ID and
  1111. *           ahiam_MixFreq will be AHI_DEFAULT_FREQ. Note that if you filter
  1112. *           the mode list (see below), you must also check the mode (with
  1113. *           AHI_BestAudioIDA()) before you use it since the user may change 
  1114. *           the meaning of AHI_DEFAULT_MODE anytime, without your knowledge.
  1115. *           Default is FALSE. (V4)
  1116. *
  1117. *       AHIR_FilterFunc (struct Hook *) - A function to call for each mode
  1118. *           encountered. If the function returns TRUE, the mode is included
  1119. *           in the file list, otherwise it is rejected and not displayed. The
  1120. *           function receives the following parameters:
  1121. *               A0 - (struct Hook *)
  1122. *               A1 - (ULONG) mode id
  1123. *               A2 - (struct AHIAudioModeRequester *)
  1124. *
  1125. *       AHIR_FilterTags (struct TagItem *) - A pointer to a tag list used to
  1126. *           filter modes away, like AHIR_FilterFunc does. The tags are the
  1127. *           same as AHI_BestAudioIDA() takes as arguments. See that function
  1128. *           for an explanation of each tag.
  1129. *
  1130. *   RESULT
  1131. *       result - FALSE if the user cancelled the requester or if something
  1132. *           prevented the requester from opening. If TRUE, values in the
  1133. *           requester structure will be set.
  1134. *
  1135. *           If the return value is FALSE, you can look at the result from the
  1136. *           dos.library/IoErr() function to determine whether the requester
  1137. *           was cancelled or simply failed to open. If dos.library/IoErr()
  1138. *           returns 0, then the requester was cancelled, any other value
  1139. *           indicates a failure to open. Current possible failure codes are
  1140. *           ERROR_NO_FREE_STORE which indicates there was not enough memory,
  1141. *           and ERROR_NO_MORE_ENTRIES which indicates no modes were available
  1142. *           (usually because the application filter hook filtered them all
  1143. *           away).
  1144. *
  1145. *   EXAMPLE
  1146. *
  1147. *   NOTES
  1148. *       The requester data structure is READ-ONLY and can only be modified
  1149. *       by using tags!
  1150. *
  1151. *       The mixing/recording frequencies that are presented to the user
  1152. *       may not be the only ones a driver supports, but just a selection.
  1153. *
  1154. *   BUGS
  1155. *
  1156. *   SEE ALSO
  1157. *      AHI_AllocAudioRequestA(), AHI_FreeAudioRequest()
  1158. *
  1159. ****************************************************************************
  1160. *
  1161. */
  1162.  
  1163. ULONG ASMCALL 
  1164. AudioRequestA( REG(a0, struct AHIAudioModeRequester *req_in),
  1165.                REG(a1, struct TagItem *tags ),
  1166.                REG(a6, struct AHIBase *AHIBase) )
  1167. {
  1168.   struct AHIAudioModeRequesterExt *req=(struct AHIAudioModeRequesterExt *)req_in;
  1169.   struct MinList list;
  1170.   struct IDnode *node = NULL, *node2 = NULL;
  1171.   ULONG screenTag=TAG_IGNORE,screenData = NULL ,id=AHI_INVALID_ID;
  1172.   BOOL  rc=TRUE;
  1173.   struct Requester lockreq;
  1174.   BOOL  locksuxs = FALSE;
  1175.   WORD zipcoords[4];
  1176.  
  1177.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  1178.   {
  1179.     Debug_AudioRequestA(req_in,tags);
  1180.   }
  1181.  
  1182.   SetIoErr( 0 );
  1183.  
  1184.   if(!req)
  1185.   {
  1186.     SetIoErr( ERROR_REQUIRED_ARG_MISSING );
  1187.     return FALSE;
  1188.   }
  1189.  
  1190. // Update requester structure
  1191.   FillReqStruct(req,tags);
  1192.   if(req->Req.ahiam_InfoLeftEdge == 0)
  1193.     req->Req.ahiam_InfoLeftEdge=req->Req.ahiam_LeftEdge+16;
  1194.   if(req->Req.ahiam_InfoTopEdge == 0)
  1195.     req->Req.ahiam_InfoTopEdge=req->Req.ahiam_TopEdge+25;
  1196.   req->tempAudioID=req->Req.ahiam_AudioID;
  1197.   req->tempFrequency=req->Req.ahiam_MixFreq;
  1198.  
  1199. // Open the catalog
  1200.  
  1201.   req->Catalog = ExtOpenCatalog(req->Locale, NULL);
  1202.  
  1203.   if(req->PositiveText == NULL)
  1204.     req->PositiveText = GetString(msgReqOK, req->Catalog);
  1205.   if(req->NegativeText == NULL)
  1206.     req->NegativeText = GetString(msgReqCancel, req->Catalog);
  1207.  
  1208.  
  1209. // Scan audio database for modes and create list
  1210.  
  1211.   req->list=&list;
  1212.   NewList((struct List *)req->list);
  1213.   while(AHI_INVALID_ID != (id=AHI_NextAudioID(id)))
  1214.   {
  1215.     // Check FilterTags
  1216.     if(req->FilterTags)
  1217.       if(!TestAudioID(id,req->FilterTags))
  1218.         continue;
  1219.     if(req->FilterFunc)
  1220.       if(!CallHookPkt(req->FilterFunc,req,(APTR)id))
  1221.         continue;
  1222.     // Add mode to list
  1223.     if((node=AllocVec(sizeof(struct IDnode),MEMF_ANY)))
  1224.     {
  1225.       node->node.ln_Type=NT_USER;
  1226.       node->node.ln_Pri=0;
  1227.       node->node.ln_Name=node->name;
  1228.       node->ID=id;
  1229.       Sprintf(node->node.ln_Name, GetString(msgUnknown, req->Catalog),id);
  1230.       AHI_GetAudioAttrs(id, NULL,
  1231.           AHIDB_BufferLen,80,
  1232.           AHIDB_Name, (ULONG) node->node.ln_Name,
  1233.           TAG_DONE);
  1234.       // Insert node alphabetically
  1235.       for(node2=(struct IDnode *)req->list->mlh_Head;node2->node.ln_Succ;node2=(struct IDnode *) node2->node.ln_Succ)
  1236.         if(Stricmp(node->node.ln_Name,node2->node.ln_Name) < 0)
  1237.           break;
  1238.       Insert((struct List *) req->list,(struct Node *)node,node2->node.ln_Pred);
  1239.     }
  1240.   }
  1241.  
  1242. // Add the users prefered mode
  1243.  
  1244.   if((req->Flags & defaultmode) && (AHIBase->ahib_AudioMode != AHI_INVALID_ID)) do
  1245.   {
  1246.     if(req->FilterTags)
  1247.       if(!TestAudioID(AHIBase->ahib_AudioMode,req->FilterTags))
  1248.         continue;
  1249.     if(req->FilterFunc)
  1250.       if(!CallHookPkt(req->FilterFunc,req,(APTR)id))
  1251.         continue;
  1252.  
  1253.     if((node=AllocVec(sizeof(struct IDnode),MEMF_ANY)))
  1254.     {
  1255.       node->node.ln_Type=NT_USER;
  1256.       node->node.ln_Pri=0;
  1257.       node->node.ln_Name=node->name;
  1258.       node->ID = AHI_DEFAULT_ID;
  1259.       Sprintf(node->node.ln_Name, GetString(msgDefaultMode, req->Catalog));
  1260.       AddTail((struct List *) req->list, (struct Node *)node);
  1261.     }
  1262.   } while(FALSE);
  1263.  
  1264.   if(NULL == ((struct IDnode *)req->list->mlh_Head)->node.ln_Succ)
  1265.   {
  1266.     // List is empty, no audio modes!
  1267.     // Return immediately (no nodes to free)
  1268.     SetIoErr(ERROR_NO_MORE_ENTRIES);
  1269.     ExtCloseCatalog(req->Catalog);
  1270.     req->Catalog = FALSE;
  1271.     return FALSE;
  1272.   }
  1273.  
  1274. // Find our sceeen
  1275. //  req->PubScreen=LockPubScreen(req->PubScreenName);
  1276.  
  1277. // Clear ownIDCMP flag
  1278.   req->Flags &= ~ownIDCMP;
  1279.   if(req->Screen)
  1280.   {
  1281.     screenTag=(ULONG)WA_CustomScreen;
  1282.     screenData=(ULONG)req->Screen;
  1283.   }
  1284.   else if(req->PubScreenName != (STRPTR) -1)
  1285.   {
  1286.     screenTag=(ULONG)WA_PubScreenName;
  1287.     screenData=(ULONG)req->PubScreenName;
  1288.   }
  1289.   else if(req->SrcWindow)
  1290.   {
  1291.     screenTag=(ULONG)WA_CustomScreen;
  1292.     screenData=(ULONG)req->SrcWindow->WScreen;
  1293.     if(req->Flags & haveIDCMP)
  1294.       req->Flags |= ownIDCMP;
  1295.   }
  1296.  
  1297.   zipcoords[0]=req->Req.ahiam_LeftEdge;
  1298.   zipcoords[1]=req->Req.ahiam_TopEdge;
  1299.   zipcoords[2]=1;
  1300.   zipcoords[3]=1;
  1301.   req->Window=OpenWindowTags(NULL,
  1302.     WA_Left,req->Req.ahiam_LeftEdge,
  1303.     WA_Top,req->Req.ahiam_TopEdge,
  1304.     WA_Width,req->Req.ahiam_Width,
  1305.     WA_Height,req->Req.ahiam_Height,
  1306.     WA_Zoom, (ULONG) zipcoords,
  1307.     WA_MaxWidth,~0,
  1308.     WA_MaxHeight,~0,
  1309.     WA_Title, (ULONG) req->TitleText,
  1310.     screenTag,screenData,
  1311.     WA_PubScreenFallBack,TRUE,
  1312.     WA_SizeGadget,TRUE,
  1313.     WA_SizeBBottom,TRUE,
  1314.     WA_DragBar,TRUE,
  1315.     WA_DepthGadget,TRUE,
  1316.     WA_CloseGadget,TRUE,
  1317.     WA_Activate,TRUE,
  1318.     WA_SimpleRefresh,TRUE,
  1319.     WA_AutoAdjust,TRUE,
  1320.     WA_IDCMP,(req->Flags & ownIDCMP ? NULL : MY_IDCMPS),
  1321.     WA_NewLookMenus, TRUE,
  1322.     TAG_DONE);
  1323.  
  1324. //  UnlockPubScreen(NULL,req->PubScreen);
  1325.  
  1326.   if(req->Window)
  1327.   {
  1328.     WindowLimits(req->Window,
  1329.       // Topaz80: "Frequency"+INTERWIDTH+MINSLIDERWIDTH+INTERWIDTH+"99999 Hz" gives...
  1330.       (req->Window->BorderLeft+4)+
  1331.       strlen( GetString(msgReqFrequency, req->Catalog))*8+
  1332.       INTERWIDTH+MINSLIDERWIDTH+INTERWIDTH+
  1333.       FREQLEN2*8+
  1334.       (req->Window->BorderRight+4),
  1335.       // Topaz80: 5 lines, freq & buttons gives...
  1336.       (req->Window->BorderTop+2)+(5*8+6)+2+(8+6)+2+(8+6)+(req->Window->BorderBottom+2),
  1337.       0,0);
  1338.  
  1339.     if((req->vi=GetVisualInfoA(req->Window->WScreen, NULL)))
  1340.     {
  1341.       if(!(LayOutReq(req,req->TextAttr)))
  1342.         if(!(LayOutReq(req,&Topaz80)))
  1343.           rc=FALSE;
  1344.  
  1345.       if(rc) // Layout OK?
  1346.       {
  1347.         struct NewMenu reqnewmenu[] =
  1348.         {
  1349.           { NM_TITLE, NULL        , 0 ,0,0,(APTR) 0,            },
  1350.           {  NM_ITEM, NULL        , 0 ,0,0,(APTR) LASTMODEITEM, },
  1351.           {  NM_ITEM, NULL        , 0 ,0,0,(APTR) NEXTMODEITEM, },
  1352.           {  NM_ITEM, NM_BARLABEL , 0 ,0,0,(APTR) 0,            },
  1353.           {  NM_ITEM, NULL        , 0 ,0,0,(APTR) PROPERTYITEM, },
  1354.           {  NM_ITEM, NULL        , 0 ,0,0,(APTR) RESTOREITEM , },
  1355.           {  NM_ITEM, NM_BARLABEL , 0 ,0,0,(APTR) 0,            },
  1356.           {  NM_ITEM, NULL        , 0 ,0,0,(APTR) OKITEM,       },
  1357.           {  NM_ITEM, NULL        , 0 ,0,0,(APTR) CANCELITEM,   },
  1358.           {   NM_END, NULL        , 0 ,0,0,(APTR) 0,            },
  1359.         };
  1360.         static const APTR strings[] =
  1361.         {
  1362.           msgMenuControl,
  1363.           msgMenuLastMode,
  1364.           msgMenuNextMode,
  1365.           msgMenuPropertyList,
  1366.           msgMenuRestore,
  1367.           msgMenuOK,
  1368.           msgMenuCancel,
  1369.         };
  1370.  
  1371.         struct NewMenu *menuptr;
  1372.         APTR           *stringptr;
  1373.         
  1374.         menuptr   = (struct NewMenu *) &reqnewmenu;
  1375.         stringptr = (APTR *) &strings;
  1376.  
  1377.         while(menuptr->nm_Type != NM_END)
  1378.         {
  1379.           if(menuptr->nm_Label == NULL)
  1380.           {
  1381.             menuptr->nm_CommKey = GetString(*stringptr, req->Catalog);
  1382.             menuptr->nm_Label = menuptr->nm_CommKey + 2;
  1383.             stringptr++;
  1384.           }
  1385.           menuptr++;
  1386.         }
  1387.  
  1388.         if(req->Flags & ownIDCMP)
  1389.         {
  1390.           req->Window->UserPort=req->SrcWindow->UserPort;
  1391.           ModifyIDCMP(req->Window,MY_IDCMPS);
  1392.         }
  1393.  
  1394.         if((req->Flags & lockwin) && req->SrcWindow)
  1395.         {
  1396.           InitRequester(&lockreq);
  1397.           locksuxs=Request(&lockreq,req->SrcWindow);
  1398.           if(IntuitionBase->LibNode.lib_Version >= 39)
  1399.             SetWindowPointer(req->SrcWindow,
  1400.                 WA_BusyPointer,TRUE,
  1401.                 TAG_DONE);
  1402.         }
  1403.         
  1404.         // Add menus
  1405.         if((req->Menu=CreateMenus(reqnewmenu, 
  1406.             GTMN_FullMenu, TRUE,
  1407.             GTMN_NewLookMenus, TRUE,
  1408.             TAG_DONE )))
  1409.         {
  1410.           if(LayoutMenus(req->Menu,req->vi, TAG_DONE))
  1411.           {
  1412.             if(SetMenuStrip(req->Window, req->Menu))
  1413.             {
  1414.               if(req->Req.ahiam_InfoOpened)
  1415.               {
  1416.                 OpenInfoWindow(req);
  1417.               }
  1418.  
  1419.               rc=HandleReq(req);
  1420.  
  1421.               CloseInfoWindow(req);
  1422.               ClearMenuStrip(req->Window);
  1423.             }
  1424.           } // else LayoutMenus failed
  1425.           FreeMenus(req->Menu);
  1426.           req->Menu=NULL;
  1427.         } // else CreateMenus failed
  1428.  
  1429.  
  1430.         if((req->Flags & lockwin) && req->SrcWindow)
  1431.         {
  1432.           if(locksuxs)
  1433.             EndRequest(&lockreq,req->SrcWindow);
  1434.           if(IntuitionBase->LibNode.lib_Version >= 39)
  1435.             SetWindowPointer(req->SrcWindow,
  1436.                 WA_BusyPointer,FALSE,
  1437.                 TAG_DONE);
  1438.         }
  1439.  
  1440.         req->Req.ahiam_LeftEdge = req->Window->LeftEdge;
  1441.         req->Req.ahiam_TopEdge  = req->Window->TopEdge;
  1442.         req->Req.ahiam_Width    = req->Window->Width;
  1443.         req->Req.ahiam_Height   = req->Window->Height;
  1444.       } // else LayOutReq failed
  1445.     }
  1446.     else // no vi
  1447.     {
  1448.       SetIoErr(ERROR_NO_FREE_STORE);
  1449.       rc=FALSE;
  1450.     }
  1451.  
  1452.     if(req->Flags & ownIDCMP)
  1453.       CloseWindowSafely(req->Window);
  1454.     else
  1455.       CloseWindow(req->Window);
  1456.     req->Window=NULL;
  1457.     FreeVisualInfo(req->vi);
  1458.     req->vi=NULL;
  1459.     FreeGadgets(req->Gadgets);
  1460.     req->Gadgets=NULL;
  1461.       FreeVec(node);
  1462.   }
  1463.   else // no window
  1464.   {
  1465.     SetIoErr(ERROR_NO_FREE_STORE);
  1466.     rc=FALSE;
  1467.   }
  1468.  
  1469.   ExtCloseCatalog(req->Catalog);
  1470.   req->Catalog = NULL;
  1471.   req->PositiveText = req->NegativeText = NULL;
  1472.  
  1473.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  1474.   {
  1475.     KPrintF("=>%s\n",rc ? "TRUE" : "FALSE" );
  1476.   }
  1477.   return (ULONG) rc;
  1478. }
  1479.  
  1480.  
  1481. /******************************************************************************
  1482. ** AHI_FreeAudioRequest *******************************************************
  1483. ******************************************************************************/
  1484.  
  1485. /****** ahi.device/AHI_FreeAudioRequest *************************************
  1486. *
  1487. *   NAME
  1488. *       AHI_FreeAudioRequest -- frees requester resources 
  1489. *
  1490. *   SYNOPSIS
  1491. *       AHI_FreeAudioRequest( requester );
  1492. *                             A0
  1493. *
  1494. *       void AHI_FreeAudioRequest( struct AHIAudioModeRequester * );
  1495. *
  1496. *   FUNCTION
  1497. *       Frees any resources allocated by AHI_AllocAudioRequestA(). Once a
  1498. *       requester has been freed, it can no longer be used with other calls to
  1499. *       AHI_AudioRequestA().
  1500. *
  1501. *   INPUTS
  1502. *       requester - Requester obtained from AHI_AllocAudioRequestA(), or NULL
  1503. *       in which case this function does nothing.
  1504. *
  1505. *   RESULT
  1506. *
  1507. *   EXAMPLE
  1508. *
  1509. *   NOTES
  1510. *
  1511. *   BUGS
  1512. *
  1513. *   SEE ALSO
  1514. *      AHI_AllocAudioRequestA()
  1515. *
  1516. ****************************************************************************
  1517. *
  1518. */
  1519.  
  1520. void ASMCALL 
  1521. FreeAudioRequest( REG(a0, struct AHIAudioModeRequester *req),
  1522.                   REG(a6, struct AHIBase *AHIBase) )
  1523. {
  1524.  
  1525.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  1526.   {
  1527.     Debug_FreeAudioRequest(req);
  1528.   }
  1529.  
  1530.   if(req)
  1531.     FreeVec(req);
  1532. }
  1533.