revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Device / requester.c
blobe30c99d622b6e5e2e1fca59f89309c036230773e
1 /*
2 AHI - Hardware independent audio subsystem
3 Copyright (C) 2017 The AROS Dev Team
4 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
19 MA 02139, USA.
22 #include <config.h>
24 // Fix broken includes
25 struct VSPrite;
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 <libraries/asl.h>
35 #include <clib/alib_protos.h>
36 #include <proto/exec.h>
37 #include <proto/dos.h>
38 #include <proto/gadtools.h>
39 #include <proto/graphics.h>
40 #include <proto/intuition.h>
41 #include <proto/utility.h>
42 #define __NOLIBBASE__
43 #define __NOGLOBALIFACE__
44 #include <proto/ahi.h>
45 #undef __NOLIBBASE__
46 #undef __NOGLOBALIFACE__
47 #include <proto/ahi_sub.h>
49 #include <math.h>
50 #include <string.h>
51 #include <stddef.h>
53 #include "ahi_def.h"
54 #include "localize.h"
55 #include "misc.h"
56 #include "modeinfo.h"
57 #include "debug.h"
58 #include "gateway.h"
60 #define min(a,b) (((a)<(b))?(a):(b))
61 #define max(a,b) (((a)>(b))?(a):(b))
63 struct AHIAudioModeRequesterExt;
65 static void OpenInfoWindow( struct AHIAudioModeRequesterExt * );
66 static void CloseInfoWindow( struct AHIAudioModeRequesterExt * );
67 static void UpdateInfoWindow( struct AHIAudioModeRequesterExt * );
70 /******************************************************************************
71 ** Audio mode requester ******************************************************
72 ******************************************************************************/
74 #define MY_IDCMPS (LISTVIEWIDCMP|SLIDERIDCMP|BUTTONIDCMP|IDCMP_SIZEVERIFY|IDCMP_NEWSIZE|IDCMP_REFRESHWINDOW|IDCMP_CLOSEWINDOW|IDCMP_MENUPICK|IDCMP_VANILLAKEY|IDCMP_RAWKEY)
75 #define MY_INFOIDCMPS (LISTVIEWIDCMP|IDCMP_REFRESHWINDOW|IDCMP_CLOSEWINDOW)
77 #define haveIDCMP 0x0001
78 #define lockwin 0x0002
79 #define freqgad 0x0004
80 #define ownIDCMP 0x0008
81 #define defaultmode 0x0010
83 static const struct TagItem reqboolmap[] =
85 { AHIR_PrivateIDCMP, haveIDCMP },
86 { AHIR_SleepWindow, lockwin },
87 { AHIR_DoMixFreq, freqgad },
88 { AHIR_DoDefaultMode, defaultmode },
89 { TAG_DONE, 0 }
92 #define LASTMODEITEM 1
93 #define NEXTMODEITEM 2
94 #define PROPERTYITEM 3
95 #define RESTOREITEM 4
96 #define OKITEM 5
97 #define CANCELITEM 6
99 /* Node for audio mode requester */
101 struct IDnode
103 struct Node node;
104 ULONG ID;
105 char name[80];
108 /* The attribues list */
110 #define ATTRNODES 6
112 struct Attrnode
114 struct Node node;
115 UBYTE text[80];
118 /* AHIAudioModeRequester extension */
119 struct AHIAudioModeRequesterExt
121 struct AHIAudioModeRequester Req;
122 ULONG tempAudioID;
123 ULONG tempFrequency;
124 struct Window *SrcWindow;
125 STRPTR PubScreenName;
126 struct Screen *Screen;
127 ULONG Flags;
128 struct Hook *IntuiMsgFunc;
129 struct TextAttr *TextAttr;
130 struct Locale *Locale;
131 STRPTR TitleText;
132 STRPTR PositiveText;
133 STRPTR NegativeText;
134 struct TagItem *FilterTags;
135 struct Hook *FilterFunc;
137 // struct Screen *PubScreen;
138 struct Window *Window;
139 struct Window *InfoWindow;
140 WORD gx,gy,gw,gh;
141 APTR vi;
142 struct Gadget *Gadgets;
143 struct Gadget *InfoGadgets;
144 struct Gadget *InfoListViewGadget;
145 struct Gadget *listviewgadget;
146 struct Gadget *slidergadget;
147 struct MinList *list;
148 struct MinList InfoList;
149 struct Menu *Menu;
150 struct Catalog *Catalog;
151 struct Attrnode AttrNodes[ATTRNODES];
155 static const struct TextAttr Topaz80 = { "topaz.font", 8, 0, 0, };
157 #define MINSLIDERWIDTH 40
159 #define OKBUTTON 1
160 #define CANCELBUTTON 2
161 #define FREQSLIDER 3
162 #define LISTVIEW 4
164 #define FREQTEXT2 GetString(msgFreqFmt, req->Catalog) //"%lu Hz"
165 #define FREQLEN2 (5+3) // 5 digits + space + "Hz"
167 LONG IndexToFrequency( struct Gadget *gad, WORD level )
169 LONG freq = 0;
170 ULONG id;
172 id = ((struct AHIAudioModeRequesterExt *)gad->UserData)->tempAudioID;
174 if(id != AHI_DEFAULT_ID)
176 AHI_GetAudioAttrs( id, NULL,
177 AHIDB_FrequencyArg, level,
178 AHIDB_Frequency, (IPTR)&freq,
179 TAG_DONE );
181 else
183 freq = AHIBase->ahib_Frequency;
185 return freq;
189 static void FillReqStruct(struct AHIAudioModeRequesterExt *req, struct TagItem *tags)
191 IPTR obsolete_userdata;
193 // Check all known tags
194 req->SrcWindow=(struct Window *)GetTagData(AHIR_Window,(IPTR)req->SrcWindow,tags);
195 req->PubScreenName=(STRPTR)GetTagData(AHIR_PubScreenName,(IPTR)req->PubScreenName,tags);
196 req->Screen=(struct Screen *)GetTagData(AHIR_Screen,(IPTR)req->Screen,tags);
197 req->IntuiMsgFunc=(struct Hook *)GetTagData(AHIR_IntuiMsgFunc,(IPTR)req->IntuiMsgFunc,tags);
199 obsolete_userdata = GetTagData( AHIR_ObsoleteUserData, 0, tags );
200 req->Req.ahiam_ObsoleteUserData[ 0 ] = obsolete_userdata >> 16;
201 req->Req.ahiam_ObsoleteUserData[ 1 ] = obsolete_userdata & 0xffff;
203 req->Req.ahiam_UserData=(void *)GetTagData(AHIR_UserData,(IPTR)req->Req.ahiam_UserData,tags);
204 req->TextAttr=(struct TextAttr *)GetTagData(AHIR_TextAttr,(IPTR)req->TextAttr,tags);
205 req->Locale=(struct Locale *)GetTagData(AHIR_Locale,(IPTR)req->Locale,tags);
206 req->TitleText=(STRPTR)GetTagData(AHIR_TitleText,(IPTR)req->TitleText,tags);
207 req->PositiveText=(STRPTR)GetTagData(AHIR_PositiveText,(IPTR)req->PositiveText,tags);
208 req->NegativeText=(STRPTR)GetTagData(AHIR_NegativeText,(IPTR)req->NegativeText,tags);
209 req->Req.ahiam_LeftEdge=GetTagData(AHIR_InitialLeftEdge,req->Req.ahiam_LeftEdge,tags);
210 req->Req.ahiam_TopEdge=GetTagData(AHIR_InitialTopEdge,req->Req.ahiam_TopEdge,tags);
211 req->Req.ahiam_Width=GetTagData(AHIR_InitialWidth,req->Req.ahiam_Width,tags);
212 req->Req.ahiam_Height=GetTagData(AHIR_InitialHeight,req->Req.ahiam_Height,tags);
213 req->Req.ahiam_AudioID=GetTagData(AHIR_InitialAudioID,req->Req.ahiam_AudioID,tags);
214 req->Req.ahiam_MixFreq=GetTagData(AHIR_InitialMixFreq,req->Req.ahiam_MixFreq,tags);
215 req->Req.ahiam_InfoOpened=GetTagData(AHIR_InitialInfoOpened,req->Req.ahiam_InfoOpened,tags);
216 req->Req.ahiam_InfoLeftEdge=GetTagData(AHIR_InitialInfoLeftEdge,req->Req.ahiam_InfoLeftEdge,tags);
217 req->Req.ahiam_InfoTopEdge=GetTagData(AHIR_InitialInfoTopEdge,req->Req.ahiam_InfoTopEdge,tags);
218 // req->Req.ahiam_InfoWidth=GetTagData(AHIR_InitialInfoWidth,req->Req.ahiam_InfoWidth,tags);
219 // req->Req.ahiam_InfoHeight=GetTagData(AHIR_InitialInfoHeight,req->Req.ahiam_InfoHeight,tags);
220 req->FilterTags=(struct TagItem *)GetTagData(AHIR_FilterTags,(IPTR)req->FilterTags,tags);
221 req->FilterFunc=(struct Hook *)GetTagData(AHIR_FilterFunc,(IPTR)req->FilterFunc,tags);
222 req->Flags=PackBoolTags(req->Flags,tags,(struct TagItem *)reqboolmap);
226 static void
227 CalculateWindowSizePos( struct AHIAudioModeRequesterExt* req,
228 struct Screen* screen )
230 struct AslSemaphore* asl_semaphore = NULL;
232 // Default position and size
233 WORD left = 30;
234 WORD top = 20;
235 WORD width = 318;
236 WORD height = 198;
238 #ifdef ASL_SEMAPHORE_NAME /* Don't break if no v45 includes found */
239 Forbid();
240 asl_semaphore = (struct AslSemaphore*) FindSemaphore( ASL_SEMAPHORE_NAME );
242 if( asl_semaphore != NULL )
244 ObtainSemaphore( (struct SignalSemaphore*) asl_semaphore );
246 Permit();
248 if( asl_semaphore != NULL )
250 if( asl_semaphore->as_Version >= 45 &&
251 asl_semaphore->as_Size > offsetof( struct AslSemaphore,
252 as_RelativeHeight ) )
254 if( asl_semaphore->as_SizePosition & ASLOPTION_ASLOverrides )
256 // Force default settings
257 req->Req.ahiam_LeftEdge = -1;
258 req->Req.ahiam_TopEdge = -1;
259 req->Req.ahiam_Width = -1;
260 req->Req.ahiam_Height = -1;
263 if( ( asl_semaphore->as_SizePosition & ASLSIZE_MASK ) ==
264 ASLSIZE_RelativeSize )
266 // FIXME: Is it correct to use screen size only? The include file
267 // says something about parent window??
269 width = (WORD) ( (LONG) screen->Width *
270 asl_semaphore->as_RelativeWidth / 100 );
271 height = (WORD) ( (LONG) screen->Height *
272 asl_semaphore->as_RelativeHeight / 100 );
275 else
277 // Not valid
278 ReleaseSemaphore( (struct SignalSemaphore*) asl_semaphore );
279 asl_semaphore = NULL;
282 #endif
284 // Set default main window size
285 if( req->Req.ahiam_Width == -1 )
286 req->Req.ahiam_Width = width;
288 if( req->Req.ahiam_Height == -1 )
289 req->Req.ahiam_Height = height;
292 #ifdef ASL_SEMAPHORE_NAME /* Don't break if no v45 includes found */
293 if( asl_semaphore != NULL )
295 switch( asl_semaphore->as_SizePosition & ASLPOS_MASK )
297 case ASLPOS_CenterWindow:
298 if( req->SrcWindow != NULL )
300 top = ( req->SrcWindow->TopEdge +
301 req->SrcWindow->Height / 2 -
302 req->Req.ahiam_Height / 2 );
303 left = ( req->SrcWindow->LeftEdge +
304 req->SrcWindow->Width / 2 -
305 req->Req.ahiam_Width / 2 );
306 break;
308 else
310 // Fall through and use ASLPOS_CenterScreen instead
313 case ASLPOS_CenterScreen:
314 top = ( screen->Height / 2 -
315 req->Req.ahiam_Height / 2 );
316 left = ( screen->Width / 2 -
317 req->Req.ahiam_Width / 2 );
318 break;
320 case ASLPOS_WindowPosition:
321 if( req->SrcWindow != NULL )
323 top = ( req->SrcWindow->TopEdge +
324 asl_semaphore->as_RelativeTop );
325 left = ( req->SrcWindow->LeftEdge +
326 asl_semaphore->as_RelativeLeft );
327 break;
329 else
331 // Fall through and use ASLPOS_ScreenPosition instead
334 case ASLPOS_ScreenPosition:
335 top = asl_semaphore->as_RelativeTop;
336 left = asl_semaphore->as_RelativeLeft;
337 break;
339 case ASLPOS_CenterMouse:
340 top = ( screen->MouseY -
341 req->Req.ahiam_Height / 2 );
342 left = ( screen->MouseX -
343 req->Req.ahiam_Width / 2 );
344 break;
346 case ASLPOS_DefaultPosition:
347 default:
348 // Do nothing (use hardcoded defaults)
349 break;
352 #endif
354 // Set default main window position
355 if( req->Req.ahiam_LeftEdge == -1 )
356 req->Req.ahiam_LeftEdge = left;
358 if( req->Req.ahiam_TopEdge == -1 )
359 req->Req.ahiam_TopEdge = top;
362 // Set default info window position (size is fixed)
363 if( req->Req.ahiam_InfoLeftEdge == -1 )
364 req->Req.ahiam_InfoLeftEdge = req->Req.ahiam_LeftEdge + 16;
366 if( req->Req.ahiam_InfoTopEdge == -1 )
367 req->Req.ahiam_InfoTopEdge = req->Req.ahiam_TopEdge + 25;
370 // Clean up
371 if( asl_semaphore != NULL )
373 ReleaseSemaphore( (struct SignalSemaphore*) asl_semaphore );
378 ** Returns the ordinal number of the current audio id.
381 static LONG GetSelected(struct AHIAudioModeRequesterExt *req)
383 struct IDnode *idnode;
384 LONG valt=0;
386 for(idnode=(struct IDnode *)req->list->mlh_Head;
387 idnode->node.ln_Succ;
388 idnode=(struct IDnode *) idnode->node.ln_Succ)
390 if(idnode->ID == req->tempAudioID)
391 break;
392 else
393 valt++;
395 if(idnode->node.ln_Succ == NULL)
397 valt=~0;
398 req->tempAudioID=AHI_INVALID_ID; // Crashed if this is not done! FIXIT!
400 return valt;
404 ** Calculates what the current slider level shoud be and how many levels total
407 static void GetSliderAttrs(struct AHIAudioModeRequesterExt *req, LONG *levels, LONG *level)
409 *levels=0;
410 *level=0;
412 AHI_GetAudioAttrs(req->tempAudioID, NULL,
413 AHIDB_Frequencies, (IPTR)levels,
414 AHIDB_IndexArg, (req->tempAudioID == AHI_DEFAULT_ID ?
415 AHIBase->ahib_Frequency : req->tempFrequency),
416 AHIDB_Index, (IPTR)level,
417 TAG_DONE);
419 if(*level >= *levels)
420 *level = *levels-1;
422 AHI_GetAudioAttrs(req->tempAudioID, NULL,
423 AHIDB_FrequencyArg, *level,
424 AHIDB_Frequency, (IPTR)&req->tempFrequency,
425 TAG_DONE);
429 ** Updates the requester to the current frequency and if 'all'==TRUE, audio mode.
432 static void SetSelected(struct AHIAudioModeRequesterExt *req, BOOL all)
434 LONG sliderlevels,sliderlevel,selected;
435 BOOL disabled = FALSE;
436 ULONG top = GTLV_Top;
437 ULONG makevisible = GTLV_MakeVisible;
439 if(all)
441 //Set listview
442 selected=GetSelected(req);
444 if( selected == ~0 || GadToolsBase->lib_Version >= 39 )
446 top = TAG_IGNORE;
449 if( selected == ~0 )
451 makevisible = TAG_IGNORE;
454 GT_SetGadgetAttrs(req->listviewgadget, req->Window, NULL,
455 top, selected,
456 makevisible, selected,
457 GTLV_Selected, selected,
458 TAG_DONE);
461 //Set slider
462 GetSliderAttrs(req,&sliderlevels,&sliderlevel);
464 if( sliderlevels == 0 || req->tempAudioID == AHI_DEFAULT_ID )
466 disabled = TRUE;
469 GT_SetGadgetAttrs(req->slidergadget, req->Window, NULL,
470 GTSL_Max, sliderlevels-1,
471 GTSL_Level, sliderlevel,
472 GA_Disabled, disabled,
473 TAG_DONE);
475 UpdateInfoWindow(req);
480 ** Positions all gadgets in the requester.
483 static BOOL LayOutReq (struct AHIAudioModeRequesterExt *req, const struct TextAttr *TextAttr)
485 struct Gadget *gad;
486 struct NewGadget ng;
488 struct TextAttr *gadtextattr;
489 struct TextFont *font;
490 LONG fontwidth,buttonheight,buttonwidth,pixels;
491 struct IntuiText intuitext = {1,0,JAM1,0,0,NULL,NULL,NULL};
492 LONG sliderlevels,sliderlevel;
493 LONG selected;
495 selected=GetSelected(req);
496 GetSliderAttrs(req,&sliderlevels,&sliderlevel);
498 // Calculate gadget area
499 req->gx=req->Window->BorderLeft+4;
500 req->gy=req->Window->BorderTop+2;
501 req->gw=req->Window->Width-req->gx-(req->Window->BorderRight+4);
502 req->gh=req->Window->Height-req->gy-(req->Window->BorderBottom+2);
504 if(req->Gadgets)
506 RemoveGList(req->Window,req->Gadgets,-1);
507 FreeGadgets(req->Gadgets);
508 SetAPen(req->Window->RPort,0);
509 SetDrMd(req->Window->RPort,JAM1);
510 EraseRect(req->Window->RPort, req->Window->BorderLeft, req->Window->BorderTop,
511 req->Window->Width-req->Window->BorderRight-1,req->Window->Height-req->Window->BorderBottom-1);
512 RefreshWindowFrame(req->Window);
514 req->Gadgets=NULL;
515 if((gad=CreateContext(&req->Gadgets)))
517 if(TextAttr)
518 gadtextattr=(struct TextAttr *)TextAttr;
519 else
520 gadtextattr=req->Window->WScreen->Font;
522 if((font=OpenFont(gadtextattr)))
524 fontwidth=font->tf_XSize;
525 CloseFont(font);
527 else
528 return FALSE;
530 buttonheight=gadtextattr->ta_YSize+6;
531 intuitext.ITextFont=gadtextattr;
532 intuitext.IText=req->PositiveText;
533 buttonwidth=IntuiTextLength(&intuitext);
534 intuitext.IText=req->NegativeText;
535 pixels=IntuiTextLength(&intuitext);
536 buttonwidth=max(pixels,buttonwidth);
537 buttonwidth+=4+fontwidth;
539 // Create gadgets and check if they fit
540 // Do the two buttons fit?
541 if(2*buttonwidth > req->gw)
542 return FALSE;
543 ng.ng_TextAttr=gadtextattr;
544 ng.ng_VisualInfo=req->vi;
545 ng.ng_UserData=req;
546 // OK button
547 ng.ng_LeftEdge=req->gx;
548 ng.ng_TopEdge=req->gy+req->gh-buttonheight;
549 ng.ng_Width=buttonwidth;
550 ng.ng_Height=buttonheight;
551 ng.ng_GadgetText=req->PositiveText;
552 ng.ng_GadgetID=OKBUTTON;
553 ng.ng_Flags=PLACETEXT_IN;
554 gad=CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);
555 // Cancel button
556 ng.ng_LeftEdge=req->gx+req->gw-ng.ng_Width;
557 ng.ng_GadgetText=req->NegativeText;
558 ng.ng_GadgetID=CANCELBUTTON;
559 gad=CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);
560 // Frequency
561 if(req->Flags & freqgad)
563 intuitext.IText = GetString(msgReqFrequency, req->Catalog);
564 pixels=IntuiTextLength(&intuitext)+INTERWIDTH;
565 if(pixels+MINSLIDERWIDTH+INTERWIDTH+FREQLEN2*fontwidth > req->gw)
566 return FALSE;
567 ng.ng_Width=req->gw-pixels-INTERWIDTH-FREQLEN2*fontwidth;
568 ng.ng_LeftEdge=req->gx+pixels;
569 ng.ng_TopEdge-=2+buttonheight;
570 ng.ng_GadgetText = GetString(msgReqFrequency, req->Catalog);
571 ng.ng_GadgetID=FREQSLIDER;
572 ng.ng_Flags=PLACETEXT_LEFT;
573 gad=CreateGadget(SLIDER_KIND,gad,&ng,
574 GTSL_Min,0,
575 GTSL_Max,sliderlevels-1,
576 GTSL_Level,sliderlevel,
577 GTSL_LevelFormat, FREQTEXT2,
578 GTSL_MaxLevelLen,FREQLEN2,
579 GTSL_LevelPlace,PLACETEXT_RIGHT,
580 GTSL_DispFunc, m68k_IndexToFrequency,
581 GA_RelVerify,TRUE,
582 GA_Disabled,!sliderlevels || (req->tempAudioID == AHI_DEFAULT_ID),
583 TAG_DONE);
584 req->slidergadget=gad; // Save for HadleReq()...
586 // ListView
587 if((ng.ng_Height=ng.ng_TopEdge-2-req->gy) < buttonheight)
588 return FALSE;
589 ng.ng_LeftEdge=req->gx;
590 ng.ng_TopEdge=req->gy;
591 ng.ng_Width=req->gw;
592 ng.ng_GadgetText=NULL,
593 ng.ng_GadgetID=LISTVIEW;
594 ng.ng_Flags=PLACETEXT_ABOVE;
595 gad=CreateGadget(LISTVIEW_KIND,gad,&ng,
596 GTLV_ScrollWidth,(fontwidth>8 ? fontwidth*2 : 18),
597 GTLV_Labels, req->list,
598 GTLV_ShowSelected,0,
599 ((selected == ~0) || (GadToolsBase->lib_Version >= 39) ? TAG_IGNORE : GTLV_Top),selected,
600 (selected == ~0 ? TAG_IGNORE : GTLV_MakeVisible),selected,
601 GTLV_Selected,selected,
602 TAG_DONE);
603 req->listviewgadget=gad; // Save for HadleReq()...
605 if(!gad)
606 return FALSE;
608 else
609 return FALSE;
611 AddGList(req->Window,req->Gadgets,~0,-1,NULL);
612 RefreshGList(req->Gadgets,req->Window,NULL,-1);
613 GT_RefreshWindow(req->Window,NULL);
615 return TRUE;
620 /* these functions close an Intuition window
621 * that shares a port with other Intuition
622 * windows or IPC customers.
624 * We are careful to set the UserPort to
625 * null before closing, and to free
626 * any messages that it might have been
627 * sent.
630 /* remove and reply all IntuiMessages on a port that
631 * have been sent to a particular window
632 * (note that we don't rely on the ln_Succ pointer
633 * of a message after we have replied it)
635 static void StripIntuiMessagesAHI( struct MsgPort *mp, struct Window *win )
637 struct IntuiMessage *msg;
638 struct Node *succ;
640 msg = (struct IntuiMessage *) mp->mp_MsgList.lh_Head;
642 while((succ = msg->ExecMessage.mn_Node.ln_Succ)) {
644 if( msg->IDCMPWindow == win ) {
646 /* Intuition is about to free this message.
647 * Make sure that we have politely sent it back.
649 Remove( (struct Node *) msg );
651 ReplyMsg( (struct Message *) msg );
654 msg = (struct IntuiMessage *) succ;
658 static void CloseWindowSafely( struct Window *win )
660 /* we forbid here to keep out of race conditions with Intuition */
661 Forbid();
663 /* send back any messages for this window
664 * that have not yet been processed
666 StripIntuiMessagesAHI( win->UserPort, win );
668 /* clear UserPort so Intuition will not free it */
669 win->UserPort = NULL;
671 /* tell Intuition to stop sending more messages */
672 ModifyIDCMP( win, 0L );
674 /* turn multitasking back on */
675 Permit();
677 /* and really close the window */
678 CloseWindow( win );
681 static BOOL HandleReq( struct AHIAudioModeRequesterExt *req )
683 // Returns FALSE if requester was cancelled
686 BOOL done=FALSE,rc=TRUE;
687 ULONG class,sec,oldsec=0,micro,oldmicro=0;
688 IPTR oldid=AHI_INVALID_ID;
689 UWORD code;
690 UWORD qual;
691 struct Gadget *pgsel;
692 struct IntuiMessage *imsg;
693 struct IDnode *idnode;
694 LONG sliderlevels,sliderlevel,i,selected;
695 struct MenuItem *item;
697 while(!done)
699 Wait(1L << req->Window->UserPort->mp_SigBit);
701 while ((imsg=GT_GetIMsg(req->Window->UserPort)) != NULL )
704 if(imsg->IDCMPWindow == req->InfoWindow)
706 class = imsg->Class;
707 GT_ReplyIMsg(imsg);
709 switch(class)
711 case IDCMP_CLOSEWINDOW:
712 CloseInfoWindow(req);
713 break;
714 case IDCMP_REFRESHWINDOW :
715 GT_BeginRefresh(req->InfoWindow);
716 GT_EndRefresh(req->InfoWindow,TRUE);
717 break;
719 continue; // Get next IntuiMessage
722 else if(imsg->IDCMPWindow != req->Window) // Not my window!
724 if(req->IntuiMsgFunc)
725 CallHookPkt(req->IntuiMsgFunc,req,imsg);
726 // else what to do??? Reply and forget? FIXIT!
727 continue;
730 sec=imsg->Seconds;
731 micro=imsg->Micros;
732 qual=imsg->Qualifier;
733 class=imsg->Class;
734 code=imsg->Code;
735 pgsel=(struct Gadget *)imsg->IAddress; // pgsel illegal if not gadget
736 GT_ReplyIMsg(imsg);
738 switch ( class )
740 case IDCMP_RAWKEY:
741 switch (code)
743 case 0x4c: // Cursor Up
744 selected=GetSelected(req);
745 if(selected == ~0)
746 selected=0;
747 if(selected > 0)
748 selected--;
749 idnode=(struct IDnode *)req->list->mlh_Head;
750 for(i=0;i<selected;i++)
751 idnode=(struct IDnode *)idnode->node.ln_Succ;
752 req->tempAudioID=idnode->ID;
753 SetSelected(req,TRUE);
754 break;
755 case 0x4d: // Cursor Down
756 selected=GetSelected(req);
757 selected++; // ~0 => 0
758 idnode=(struct IDnode *)req->list->mlh_Head;
759 for(i=0;i<selected;i++)
760 if(idnode->node.ln_Succ->ln_Succ)
761 idnode=(struct IDnode *)idnode->node.ln_Succ;
762 req->tempAudioID=idnode->ID;
763 SetSelected(req,TRUE);
764 break;
765 case 0x4e: // Cursor Right
766 GetSliderAttrs(req,&sliderlevels,&sliderlevel);
767 sliderlevel += (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? 10 :1);
768 if(sliderlevel >= sliderlevels)
769 sliderlevel=sliderlevels-1;
770 AHI_GetAudioAttrs(req->tempAudioID, NULL,
771 AHIDB_FrequencyArg,sliderlevel,
772 AHIDB_Frequency, (IPTR)&req->tempFrequency,
773 TAG_DONE);
774 SetSelected(req,FALSE);
775 break;
776 case 0x4f: // Cursor Left
777 GetSliderAttrs(req,&sliderlevels,&sliderlevel);
778 sliderlevel -= (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? 10 :1);
779 if(sliderlevel < 0)
780 sliderlevel=0;
781 AHI_GetAudioAttrs(req->tempAudioID, NULL,
782 AHIDB_FrequencyArg,sliderlevel,
783 AHIDB_Frequency, (IPTR)&req->tempFrequency,
784 TAG_DONE);
785 SetSelected(req,FALSE);
786 break;
788 break;
789 case IDCMP_GADGETUP :
790 switch ( pgsel->GadgetID )
792 case OKBUTTON:
793 done=TRUE;
794 break;
795 case CANCELBUTTON:
796 done=TRUE;
797 rc=FALSE;
798 break;
799 case FREQSLIDER:
800 AHI_GetAudioAttrs(req->tempAudioID, NULL,
801 AHIDB_FrequencyArg,code,
802 AHIDB_Frequency, (IPTR)&req->tempFrequency,
803 TAG_DONE);
804 break;
805 case LISTVIEW:
806 idnode=(struct IDnode *)req->list->mlh_Head;
807 for(i=0;i<code;i++)
808 idnode=(struct IDnode *)idnode->node.ln_Succ;
809 req->tempAudioID=idnode->ID;
810 SetSelected(req,FALSE);
811 // Test doubleclick and save timestamp
812 if( (oldid == req->tempAudioID) && DoubleClick(oldsec,oldmicro,sec,micro))
813 done=TRUE;
814 oldsec=sec;
815 oldmicro=micro;
816 oldid=req->tempAudioID;
818 break;
820 break;
822 case IDCMP_NEWSIZE:
823 if(!(LayOutReq(req,req->TextAttr)))
824 if(!(LayOutReq(req,&Topaz80)))
826 // ERROR! Quit.
827 done=TRUE;
828 break;
830 break;
831 case IDCMP_CLOSEWINDOW:
832 done=TRUE;
833 rc=FALSE;
834 break;
835 case IDCMP_REFRESHWINDOW :
836 GT_BeginRefresh(req->Window);
837 GT_EndRefresh(req->Window,TRUE);
838 break;
839 case IDCMP_SIZEVERIFY:
840 break;
841 case IDCMP_MENUPICK:
842 while((code != MENUNULL) && !done)
844 item=ItemAddress(req->Menu, code);
845 switch((IPTR)GTMENUITEM_USERDATA(item))
847 case LASTMODEITEM:
848 selected=GetSelected(req);
849 if(selected == ~0)
850 selected=0;
851 if(selected > 0)
852 selected--;
853 idnode=(struct IDnode *)req->list->mlh_Head;
854 for(i=0;i<selected;i++)
855 idnode=(struct IDnode *)idnode->node.ln_Succ;
856 req->tempAudioID=idnode->ID;
857 SetSelected(req,TRUE);
858 break;
859 case NEXTMODEITEM:
860 selected=GetSelected(req);
861 selected++; // ~0 => 0
862 idnode=(struct IDnode *)req->list->mlh_Head;
863 for(i=0;i<selected;i++)
864 if(idnode->node.ln_Succ->ln_Succ)
865 idnode=(struct IDnode *)idnode->node.ln_Succ;
866 req->tempAudioID=idnode->ID;
867 SetSelected(req,TRUE);
868 break;
869 case PROPERTYITEM:
870 OpenInfoWindow(req);
871 break;
872 case RESTOREITEM:
873 req->tempAudioID=req->Req.ahiam_AudioID;
874 req->tempFrequency=req->Req.ahiam_MixFreq;
875 SetSelected(req,TRUE);
876 break;
877 case OKITEM:
878 done=TRUE;
879 break;
880 case CANCELITEM:
881 done=TRUE;
882 rc=FALSE;
883 break;
885 code = item->NextSelect;
887 break;
892 if(rc)
894 req->Req.ahiam_AudioID = req->tempAudioID;
896 if(req->tempAudioID != AHI_DEFAULT_ID)
898 req->Req.ahiam_MixFreq = req->tempFrequency;
900 else
902 req->Req.ahiam_MixFreq = AHI_DEFAULT_FREQ;
905 return rc;
909 static void OpenInfoWindow( struct AHIAudioModeRequesterExt *req )
911 struct Gadget *gad;
912 struct NewGadget ng;
915 if(req->InfoWindow == NULL)
917 req->InfoWindow=OpenWindowTags(NULL,
918 WA_Left, req->Req.ahiam_InfoLeftEdge,
919 WA_Top, req->Req.ahiam_InfoTopEdge,
920 WA_Width, req->Req.ahiam_InfoWidth,
921 WA_Height, req->Req.ahiam_InfoHeight,
922 WA_Title, GetString(msgReqInfoTitle, req->Catalog),
923 WA_CustomScreen, req->Window->WScreen,
924 WA_PubScreenFallBack, TRUE,
925 WA_DragBar, TRUE,
926 WA_DepthGadget, TRUE,
927 WA_CloseGadget, TRUE,
928 WA_Activate, FALSE,
929 WA_SimpleRefresh, TRUE,
930 WA_AutoAdjust, TRUE,
931 WA_IDCMP, 0,
932 WA_NewLookMenus, TRUE,
933 TAG_DONE);
935 if(req->InfoWindow)
937 req->InfoWindow->UserPort = req->Window->UserPort;
938 ModifyIDCMP(req->InfoWindow, MY_INFOIDCMPS);
940 if((gad = CreateContext(&req->InfoGadgets)))
942 ng.ng_TextAttr = req->TextAttr;
943 ng.ng_VisualInfo = req->vi;
944 ng.ng_LeftEdge = req->InfoWindow->BorderLeft+4;
945 ng.ng_TopEdge = req->InfoWindow->BorderTop+2;
946 ng.ng_Width = req->InfoWindow->Width
947 - (req->InfoWindow->BorderLeft+4)
948 - (req->InfoWindow->BorderRight+4);
949 ng.ng_Height = req->InfoWindow->Height
950 - (req->InfoWindow->BorderTop+2)
951 - (req->InfoWindow->BorderBottom+2);
953 ng.ng_GadgetText = NULL;
954 ng.ng_GadgetID = 0;
955 ng.ng_Flags = PLACETEXT_ABOVE;
956 gad = CreateGadget(LISTVIEW_KIND, gad, &ng,
957 GTLV_ReadOnly, TRUE,
958 TAG_DONE);
959 req->InfoListViewGadget = gad;
961 if(gad)
963 AddGList(req->InfoWindow, req->InfoGadgets, ~0, -1, NULL);
964 RefreshGList(req->InfoGadgets, req->InfoWindow, NULL, -1);
965 GT_RefreshWindow(req->InfoWindow, NULL);
966 UpdateInfoWindow(req);
974 static void UpdateInfoWindow( struct AHIAudioModeRequesterExt *req )
976 LONG id=0, bits=0, stereo=0, pan=0, hifi=0, channels=0, minmix=0, maxmix=0,
977 record=0, fullduplex=0, multichannel=0;
978 int i;
980 id = req->tempAudioID;
981 if(id == AHI_DEFAULT_ID)
983 id = AHIBase->ahib_AudioMode;
985 if(req->InfoWindow)
987 AHI_GetAudioAttrs(id, NULL,
988 AHIDB_MultiChannel, (IPTR)&multichannel,
989 AHIDB_Stereo, (IPTR)&stereo,
990 AHIDB_Panning, (IPTR)&pan,
991 AHIDB_HiFi, (IPTR)&hifi,
992 AHIDB_Record, (IPTR)&record,
993 AHIDB_FullDuplex, (IPTR)&fullduplex,
994 AHIDB_Bits, (IPTR)&bits,
995 AHIDB_MaxChannels, (IPTR)&channels,
996 AHIDB_MinMixFreq, (IPTR)&minmix,
997 AHIDB_MaxMixFreq, (IPTR)&maxmix,
998 TAG_DONE);
1000 GT_SetGadgetAttrs(req->InfoListViewGadget, req->InfoWindow, NULL,
1001 GTLV_Labels, ~0,
1002 TAG_DONE);
1004 NewList((struct List *) &req->InfoList);
1005 for(i=0; i<ATTRNODES; i++)
1007 req->AttrNodes[i].node.ln_Name = req->AttrNodes[i].text;
1008 req->AttrNodes[i].text[0] = '\0';
1009 req->AttrNodes[i].node.ln_Type = NT_USER;
1010 req->AttrNodes[i].node.ln_Pri = 0;
1013 i = 0;
1014 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1015 Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoAudioID, req->Catalog),
1016 id);
1017 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1018 Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoResolution, req->Catalog),
1019 bits, (IPTR)GetString((multichannel ? msgReqInfoMultiChannel : (stereo ?
1020 (pan ? msgReqInfoStereoPan : msgReqInfoStereo) :
1021 msgReqInfoMono)), req->Catalog));
1022 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1023 Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoChannels, req->Catalog),
1024 channels);
1025 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1026 Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoMixrate, req->Catalog),
1027 minmix, maxmix);
1028 if(hifi)
1030 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1031 Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoHiFi, req->Catalog));
1033 if(record)
1035 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1036 Sprintf(req->AttrNodes[i++].text, GetString(
1037 fullduplex ? msgReqInfoRecordFull : msgReqInfoRecordHalf, req->Catalog));
1040 GT_SetGadgetAttrs(req->InfoListViewGadget, req->InfoWindow, NULL,
1041 GTLV_Labels, &req->InfoList,
1042 TAG_DONE);
1046 static void CloseInfoWindow( struct AHIAudioModeRequesterExt *req )
1048 if(req->InfoWindow)
1050 req->Req.ahiam_InfoOpened = TRUE;
1051 req->Req.ahiam_InfoLeftEdge = req->InfoWindow->LeftEdge;
1052 req->Req.ahiam_InfoTopEdge = req->InfoWindow->TopEdge;
1053 req->Req.ahiam_InfoWidth = req->InfoWindow->Width;
1054 req->Req.ahiam_InfoHeight = req->InfoWindow->Height;
1055 CloseWindowSafely(req->InfoWindow);
1056 req->InfoWindow = NULL;
1059 else
1061 req->Req.ahiam_InfoOpened = FALSE;
1065 FreeGadgets(req->InfoGadgets);
1066 req->InfoGadgets = NULL;
1070 /******************************************************************************
1071 ** AHI_AllocAudioRequestA *****************************************************
1072 ******************************************************************************/
1074 /****** ahi.device/AHI_AllocAudioRequestA ***********************************
1076 * NAME
1077 * AHI_AllocAudioRequestA -- allocate an audio mode requester.
1078 * AHI_AllocAudioRequest -- varargs stub for AHI_AllocAudioRequestA()
1080 * SYNOPSIS
1081 * requester = AHI_AllocAudioRequestA( tags );
1082 * D0 A0
1084 * struct AHIAudioModeRequester *AHI_AllocAudioRequestA(
1085 * struct TagItem * );
1087 * requester = AHI_AllocAudioRequest( tag1, ... );
1089 * struct AHIAudioModeRequester *AHI_AllocAudioRequest( Tag, ... );
1091 * FUNCTION
1092 * Allocates an audio mode requester data structure.
1094 * INPUTS
1095 * tags - A pointer to an optional tag list specifying how to initialize
1096 * the data structure returned by this function. See the
1097 * documentation for AHI_AudioRequestA() for an explanation of how
1098 * to use the currently defined tags.
1100 * RESULT
1101 * requester - An initialized requester data structure, or NULL on
1102 * failure.
1104 * EXAMPLE
1106 * NOTES
1107 * The requester data structure is READ-ONLY and can only be modified
1108 * by using tags!
1110 * BUGS
1112 * SEE ALSO
1113 * AHI_AudioRequestA(), AHI_FreeAudioRequest()
1115 ****************************************************************************
1119 struct AHIAudioModeRequester*
1120 _AHI_AllocAudioRequestA( struct TagItem* tags,
1121 struct AHIBase* AHIBase )
1123 struct AHIAudioModeRequesterExt *req;
1125 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1127 Debug_AllocAudioRequestA(tags);
1130 if((req=AllocVec(sizeof(struct AHIAudioModeRequesterExt),MEMF_CLEAR)))
1132 // Fill in defaults
1133 req->Req.ahiam_LeftEdge = -1;
1134 req->Req.ahiam_TopEdge = -1;
1135 req->Req.ahiam_Width = -1;
1136 req->Req.ahiam_Height = -1;
1138 req->Req.ahiam_AudioID = AHI_INVALID_ID;
1139 req->Req.ahiam_MixFreq = AHIBase->ahib_Frequency;
1141 req->Req.ahiam_InfoLeftEdge = -1;
1142 req->Req.ahiam_InfoTopEdge = -1;
1143 req->Req.ahiam_InfoWidth = 280;
1144 req->Req.ahiam_InfoHeight = 112;
1146 req->PubScreenName = (STRPTR) -1;
1148 FillReqStruct(req,tags);
1151 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1153 KPrintF("=>0x%P\n", (IPTR)req);
1156 return (struct AHIAudioModeRequester *) req;
1160 /******************************************************************************
1161 ** AHI_AudioRequestA **********************************************************
1162 ******************************************************************************/
1164 /****** ahi.device/AHI_AudioRequestA ****************************************
1166 * NAME
1167 * AHI_AudioRequestA -- get an audio mode from user using an requester.
1168 * AHI_AudioRequest -- varargs stub for AHI_AudioRequestA()
1170 * SYNOPSIS
1171 * success = AHI_AudioRequestA( requester, tags );
1172 * D0 A0 A1
1174 * BOOL AHI_AudioRequestA( struct AHIAudioModeRequester *,
1175 * struct TagItem * );
1177 * result = AHI_AudioRequest( requester, tag1, ... );
1179 * BOOL AHI_AudioRequest( struct AHIAudioModeRequester *, Tag, ... );
1181 * FUNCTION
1182 * Prompts the user for an audio mode, based on the modifying tags.
1183 * If the user cancels or the system aborts the request, FALSE is
1184 * returned, otherwise the requester's data structure reflects the
1185 * user input.
1187 * Note that tag values stay in effect for each use of the requester
1188 * until they are cleared or modified by passing the same tag with a
1189 * new value.
1191 * INPUTS
1192 * requester - Requester structure allocated with
1193 * AHI_AllocAudioRequestA(). If this parameter is NULL, this
1194 * function will always return FALSE with a dos.library/IoErr()
1195 * result of ERROR_NO_FREE_STORE.
1196 * tags - Pointer to an optional tag list which may be used to control
1197 * features of the requester.
1199 * TAGS
1200 * Tags used for the requester (they look remarkable similar to the
1201 * screen mode requester in ASL, don't they? ;-) )
1203 * AHIR_Window (struct Window *) - Parent window of requester. If no
1204 * AHIR_Screen tag is specified, the window structure is used to
1205 * determine on which screen to open the requesting window.
1207 * AHIR_PubScreenName (STRPTR) - Name of a public screen to open on.
1208 * This overrides the screen used by AHIR_Window.
1210 * AHIR_Screen (struct Screen *) - Screen on which to open the
1211 * requester. This overrides the screen used by AHIR_Window or by
1212 * AHIR_PubScreenName.
1214 * AHIR_PrivateIDCMP (BOOL) - When set to TRUE, this tells AHI to
1215 * allocate a new IDCMP port for the requesting window. If not
1216 * specified or set to FALSE, and if AHIR_Window is provided, the
1217 * requesting window will share AHIR_Window's IDCMP port.
1219 * AHIR_IntuiMsgFunc (struct Hook *) - A function to call whenever an
1220 * unknown Intuition message arrives at the message port being used
1221 * by the requesting window. The function receives the following
1222 * parameters:
1223 * A0 - (struct Hook *)
1224 * A1 - (struct IntuiMessage *)
1225 * A2 - (struct AHIAudioModeRequester *)
1227 * AHIR_SleepWindow (BOOL) - When set to TRUE, this tag will cause the
1228 * window specified by AHIR_Window to be "put to sleep". That is, a
1229 * busy pointer will be displayed in the parent window, and no
1230 * gadget or menu activity will be allowed. This is done by opening
1231 * an invisible Intuition Requester in the parent window.
1233 * AHIR_UserData (APTR) - A 32-bit value that is simply copied in the
1234 * ahiam_UserData field of the requester structure.
1236 * AHIR_TextAttr (struct TextAttr *) - Font to be used for the
1237 * requesting window's gadgets and menus. If this tag is not
1238 * provided or its value is NULL, the default font of the screen
1239 * on which the requesting window opens will be used. This font
1240 * must already be in memory as AHI calls OpenFont() and not
1241 * OpenDiskFont().
1243 * AHIR_Locale (struct Locale *) - Locale to use for the requesting
1244 * window. This determines the language used for the requester's
1245 * gadgets and menus. If this tag is not provided or its value is
1246 * NULL, the system's current default locale will be used.
1248 * AHIR_TitleText (STRPTR) - Title to use for the requesting window.
1249 * Default is no title.
1251 * AHIR_PositiveText (STRPTR) - Label of the positive gadget in the
1252 * requester. English default is "OK".
1254 * AHIR_NegativeText (STRPTR) - Label of the negative gadget in the
1255 * requester. English default is "Cancel".
1257 * AHIR_InitialLeftEdge (WORD) - Suggested left edge of requesting
1258 * window.
1260 * AHIR_InitialTopEdge (WORD) - Suggested top edge of requesting
1261 * window.
1263 * AHIR_InitialWidth (WORD) - Suggested width of requesting window.
1265 * AHIR_InitialHeight (WORD) - Suggested height of requesting window.
1267 * AHIR_InitialAudioID (IPTR) - Initial setting of the Mode list view
1268 * gadget (ahiam_AudioID). Default is ~0 (AHI_INVALID_ID), which
1269 * means that no mode will be selected.
1271 * AHIR_InitialMixFreq (ULONG) - Initial setting of the frequency
1272 * slider. Default is the lowest frequency supported.
1274 * AHIR_InitialInfoOpened (BOOL) - Whether to open the property
1275 * information window automatically. Default is FALSE.
1277 * AHIR_InitialInfoLeftEdge (WORD) - Initial left edge of information
1278 * window.
1280 * AHIR_InitialInfoTopEdge (WORD) - Initial top edge of information
1281 * window.
1283 * AHIR_DoMixFreq (BOOL) - Set this tag to TRUE to cause the requester
1284 * to display the frequency slider gadget. Default is FALSE.
1286 * AHIR_DoDefaultMode (BOOL) - Set this tag to TRUE to let the user
1287 * select the mode she has set in the preferences program. If she
1288 * selects this mode, ahiam_AudioID will be AHI_DEFAULT_ID and
1289 * ahiam_MixFreq will be AHI_DEFAULT_FREQ. Note that if you filter
1290 * the mode list (see below), you must also check the mode (with
1291 * AHI_BestAudioIDA()) before you use it since the user may change
1292 * the meaning of AHI_DEFAULT_MODE anytime, without your knowledge.
1293 * Default is FALSE. (V4)
1295 * AHIR_FilterFunc (struct Hook *) - A function to call for each mode
1296 * encountered. If the function returns TRUE, the mode is included
1297 * in the file list, otherwise it is rejected and not displayed. The
1298 * function receives the following parameters:
1299 * A0 - (struct Hook *)
1300 * A1 - (IPTR) mode id
1301 * A2 - (struct AHIAudioModeRequester *)
1303 * AHIR_FilterTags (struct TagItem *) - A pointer to a tag list used to
1304 * filter modes away, like AHIR_FilterFunc does. The tags are the
1305 * same as AHI_BestAudioIDA() takes as arguments. See that function
1306 * for an explanation of each tag.
1308 * RESULT
1309 * result - FALSE if the user cancelled the requester or if something
1310 * prevented the requester from opening. If TRUE, values in the
1311 * requester structure will be set.
1313 * If the return value is FALSE, you can look at the result from the
1314 * dos.library/IoErr() function to determine whether the requester
1315 * was cancelled or simply failed to open. If dos.library/IoErr()
1316 * returns 0, then the requester was cancelled, any other value
1317 * indicates a failure to open. Current possible failure codes are
1318 * ERROR_NO_FREE_STORE which indicates there was not enough memory,
1319 * and ERROR_NO_MORE_ENTRIES which indicates no modes were available
1320 * (usually because the application filter hook filtered them all
1321 * away).
1323 * EXAMPLE
1325 * NOTES
1326 * The requester data structure is READ-ONLY and can only be modified
1327 * by using tags!
1329 * The mixing/recording frequencies that are presented to the user
1330 * may not be the only ones a driver supports, but just a selection.
1332 * BUGS
1334 * SEE ALSO
1335 * AHI_AllocAudioRequestA(), AHI_FreeAudioRequest()
1337 ****************************************************************************
1341 ULONG
1342 _AHI_AudioRequestA( struct AHIAudioModeRequester* req_in,
1343 struct TagItem* tags,
1344 struct AHIBase* AHIBase )
1346 struct AHIAudioModeRequesterExt *req=(struct AHIAudioModeRequesterExt *)req_in;
1347 struct MinList list;
1348 struct IDnode *node = NULL, *node2 = NULL;
1349 struct Screen *pub_screen = NULL;
1350 struct Screen *screen = NULL;
1351 IPTR id=AHI_INVALID_ID;
1352 BOOL rc=TRUE;
1353 struct Requester lockreq;
1354 BOOL locksuxs = FALSE;
1355 WORD zipcoords[4];
1357 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1359 Debug_AudioRequestA(req_in,tags);
1362 SetIoErr( 0 );
1364 if(!req)
1366 SetIoErr( ERROR_REQUIRED_ARG_MISSING );
1367 return FALSE;
1370 // Update requester structure
1371 FillReqStruct(req,tags);
1372 req->tempAudioID=req->Req.ahiam_AudioID;
1373 req->tempFrequency=req->Req.ahiam_MixFreq;
1375 // Open the catalog
1377 req->Catalog = ExtOpenCatalog(req->Locale, NULL);
1379 if(req->PositiveText == NULL)
1380 req->PositiveText = GetString(msgReqOK, req->Catalog);
1381 if(req->NegativeText == NULL)
1382 req->NegativeText = GetString(msgReqCancel, req->Catalog);
1385 // Scan audio database for modes and create list
1386 req->list=&list;
1387 NewList((struct List *)req->list);
1388 while(AHI_INVALID_ID != (id=AHI_NextAudioID(id)))
1390 // Check FilterTags
1391 if(req->FilterTags)
1392 if(!TestAudioID(id,req->FilterTags))
1393 continue;
1394 if(req->FilterFunc)
1395 if(!CallHookPkt(req->FilterFunc,req,(APTR)id))
1396 continue;
1397 // Add mode to list
1398 if((node=AllocVec(sizeof(struct IDnode),MEMF_ANY)))
1400 node->node.ln_Type=NT_USER;
1401 node->node.ln_Pri=0;
1402 node->node.ln_Name=node->name;
1403 node->ID=id;
1404 #ifndef __AMIGAOS4__
1405 Sprintf(node->node.ln_Name, GetString(msgUnknown, req->Catalog),id);
1406 #endif
1407 AHI_GetAudioAttrs(id, NULL,
1408 AHIDB_BufferLen,80,
1409 AHIDB_Name, (IPTR)node->node.ln_Name,
1410 TAG_DONE);
1411 // Insert node alphabetically
1412 for(node2=(struct IDnode *)req->list->mlh_Head;node2->node.ln_Succ;node2=(struct IDnode *) node2->node.ln_Succ)
1413 if(Stricmp(node->node.ln_Name,node2->node.ln_Name) < 0)
1414 break;
1415 Insert((struct List *) req->list,(struct Node *)node,node2->node.ln_Pred);
1419 // Add the users preferred mode
1421 if((req->Flags & defaultmode) && (AHIBase->ahib_AudioMode != AHI_INVALID_ID)) do
1423 if(req->FilterTags)
1424 if(!TestAudioID(AHIBase->ahib_AudioMode,req->FilterTags))
1425 continue;
1426 if(req->FilterFunc)
1427 if(!CallHookPkt(req->FilterFunc,req,(APTR)AHIBase->ahib_AudioMode))
1428 continue;
1430 if((node=AllocVec(sizeof(struct IDnode),MEMF_ANY)))
1432 node->node.ln_Type=NT_USER;
1433 node->node.ln_Pri=0;
1434 node->node.ln_Name=node->name;
1435 node->ID = AHI_DEFAULT_ID;
1436 Sprintf(node->node.ln_Name, GetString(msgDefaultMode, req->Catalog));
1437 AddTail((struct List *) req->list, (struct Node *)node);
1439 } while(FALSE);
1441 if(NULL == ((struct IDnode *)req->list->mlh_Head)->node.ln_Succ)
1443 // List is empty, no audio modes!
1444 // Return immediately (no nodes to free)
1445 SetIoErr(ERROR_NO_MORE_ENTRIES);
1446 ExtCloseCatalog(req->Catalog);
1447 req->Catalog = FALSE;
1448 return FALSE;
1451 // Find our screen
1452 if(req->Screen)
1454 pub_screen = NULL;
1455 screen = req->Screen;
1457 else if(req->PubScreenName != (STRPTR) -1)
1459 pub_screen = LockPubScreen( req->PubScreenName );
1460 screen = pub_screen;
1462 else if(req->SrcWindow)
1464 pub_screen = NULL;
1465 screen = req->SrcWindow->WScreen;
1468 if( screen == NULL )
1470 pub_screen = LockPubScreen( NULL );
1471 screen = pub_screen;
1474 CalculateWindowSizePos( req, screen );
1476 // Clear ownIDCMP flag
1477 req->Flags &= ~ownIDCMP;
1479 if( req->SrcWindow != NULL )
1481 if(req->Flags & haveIDCMP)
1482 req->Flags |= ownIDCMP;
1485 zipcoords[0]=req->Req.ahiam_LeftEdge;
1486 zipcoords[1]=req->Req.ahiam_TopEdge;
1487 zipcoords[2]=1;
1488 zipcoords[3]=1;
1490 req->Window=OpenWindowTags(
1491 NULL,
1492 WA_Left,req->Req.ahiam_LeftEdge,
1493 WA_Top,req->Req.ahiam_TopEdge,
1494 WA_Width,req->Req.ahiam_Width,
1495 WA_Height,req->Req.ahiam_Height,
1496 WA_Zoom, zipcoords,
1497 WA_MaxWidth,~0,
1498 WA_MaxHeight,~0,
1499 WA_Title, req->TitleText,
1500 ( pub_screen != NULL ? WA_PubScreen : WA_CustomScreen ), screen,
1501 WA_PubScreenFallBack,TRUE,
1502 WA_SizeGadget,TRUE,
1503 WA_SizeBBottom,TRUE,
1504 WA_DragBar,TRUE,
1505 WA_DepthGadget,TRUE,
1506 WA_CloseGadget,TRUE,
1507 WA_Activate,TRUE,
1508 WA_SimpleRefresh,TRUE,
1509 WA_AutoAdjust,TRUE,
1510 WA_IDCMP,(req->Flags & ownIDCMP ? 0 : MY_IDCMPS),
1511 WA_NewLookMenus, TRUE,
1512 TAG_DONE);
1514 if( pub_screen != NULL )
1516 UnlockPubScreen( NULL, pub_screen);
1519 if(req->Window)
1521 // Topaz80: "Frequency"+INTERWIDTH+MINSLIDERWIDTH+INTERWIDTH+"99999 Hz" gives...
1522 WORD min_width = (req->Window->BorderLeft+4)+
1523 strlen( GetString(msgReqFrequency, req->Catalog))*8+
1524 INTERWIDTH+MINSLIDERWIDTH+INTERWIDTH+
1525 FREQLEN2*8+
1526 (req->Window->BorderRight+4);
1528 // Topaz80: 5 lines, freq & buttons gives...
1529 WORD min_height = (req->Window->BorderTop+2)+
1530 (5*8+6)+2+(8+6)+2+(8+6)+
1531 (req->Window->BorderBottom+2);
1533 if( req->Window->Width < min_width ||
1534 req->Window->Height < min_height )
1536 ChangeWindowBox( req->Window,
1537 req->Window->LeftEdge,
1538 req->Window->TopEdge,
1539 max( req->Window->Width, min_width ),
1540 max( req->Window->Height, min_height ) );
1541 Delay( 5 );
1544 WindowLimits( req->Window, min_width, min_height, 0, 0 );
1546 if((req->vi=GetVisualInfoA(req->Window->WScreen, NULL)))
1548 if(!(LayOutReq(req,req->TextAttr)))
1549 if(!(LayOutReq(req,&Topaz80)))
1550 rc=FALSE;
1552 if(rc) // Layout OK?
1554 struct NewMenu reqnewmenu[] =
1556 { NM_TITLE, NULL , 0 ,0,0,(APTR) 0, },
1557 { NM_ITEM, NULL , 0 ,0,0,(APTR) LASTMODEITEM, },
1558 { NM_ITEM, NULL , 0 ,0,0,(APTR) NEXTMODEITEM, },
1559 { NM_ITEM, NM_BARLABEL , 0 ,0,0,(APTR) 0, },
1560 { NM_ITEM, NULL , 0 ,0,0,(APTR) PROPERTYITEM, },
1561 { NM_ITEM, NULL , 0 ,0,0,(APTR) RESTOREITEM , },
1562 { NM_ITEM, NM_BARLABEL , 0 ,0,0,(APTR) 0, },
1563 { NM_ITEM, NULL , 0 ,0,0,(APTR) OKITEM, },
1564 { NM_ITEM, NULL , 0 ,0,0,(APTR) CANCELITEM, },
1565 { NM_END, NULL , 0 ,0,0,(APTR) 0, },
1567 static const APTR strings[] =
1569 msgMenuControl,
1570 msgMenuLastMode,
1571 msgMenuNextMode,
1572 msgMenuPropertyList,
1573 msgMenuRestore,
1574 msgMenuOK,
1575 msgMenuCancel,
1578 struct NewMenu *menuptr;
1579 APTR *stringptr;
1581 menuptr = (struct NewMenu *) &reqnewmenu;
1582 stringptr = (APTR *) &strings;
1584 while(menuptr->nm_Type != NM_END)
1586 if(menuptr->nm_Label == NULL)
1588 menuptr->nm_CommKey = GetString(*stringptr, req->Catalog);
1589 menuptr->nm_Label = menuptr->nm_CommKey + 2;
1590 stringptr++;
1592 menuptr++;
1595 if(req->Flags & ownIDCMP)
1597 req->Window->UserPort=req->SrcWindow->UserPort;
1598 ModifyIDCMP(req->Window,MY_IDCMPS);
1601 if((req->Flags & lockwin) && req->SrcWindow)
1603 InitRequester(&lockreq);
1604 locksuxs=Request(&lockreq,req->SrcWindow);
1605 if(IntuitionBase->LibNode.lib_Version >= 39)
1606 SetWindowPointer(req->SrcWindow,
1607 WA_BusyPointer,TRUE,
1608 TAG_DONE);
1611 // Add menus
1612 if((req->Menu=CreateMenus(reqnewmenu,
1613 GTMN_FullMenu, TRUE,
1614 GTMN_NewLookMenus, TRUE,
1615 TAG_DONE )))
1617 if(LayoutMenus(req->Menu,req->vi, TAG_DONE))
1619 if(SetMenuStrip(req->Window, req->Menu))
1621 if(req->Req.ahiam_InfoOpened)
1623 OpenInfoWindow(req);
1626 rc=HandleReq(req);
1628 CloseInfoWindow(req);
1629 ClearMenuStrip(req->Window);
1631 } // else LayoutMenus failed
1632 FreeMenus(req->Menu);
1633 req->Menu=NULL;
1634 } // else CreateMenus failed
1637 if((req->Flags & lockwin) && req->SrcWindow)
1639 if(locksuxs)
1640 EndRequest(&lockreq,req->SrcWindow);
1641 if(IntuitionBase->LibNode.lib_Version >= 39)
1642 SetWindowPointer(req->SrcWindow,
1643 WA_BusyPointer,FALSE,
1644 TAG_DONE);
1647 req->Req.ahiam_LeftEdge = req->Window->LeftEdge;
1648 req->Req.ahiam_TopEdge = req->Window->TopEdge;
1649 req->Req.ahiam_Width = req->Window->Width;
1650 req->Req.ahiam_Height = req->Window->Height;
1651 } // else LayOutReq failed
1653 else // no vi
1655 SetIoErr(ERROR_NO_FREE_STORE);
1656 rc=FALSE;
1659 if(req->Flags & ownIDCMP)
1660 CloseWindowSafely(req->Window);
1661 else
1662 CloseWindow(req->Window);
1663 req->Window=NULL;
1664 FreeVisualInfo(req->vi);
1665 req->vi=NULL;
1666 FreeGadgets(req->Gadgets);
1667 req->Gadgets=NULL;
1668 FreeVec(node);
1670 else // no window
1672 SetIoErr(ERROR_NO_FREE_STORE);
1673 rc=FALSE;
1676 ExtCloseCatalog(req->Catalog);
1677 req->Catalog = NULL;
1678 req->PositiveText = req->NegativeText = NULL;
1680 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1682 KPrintF("=>%s\n", (IPTR)(rc ? "TRUE" : "FALSE"));
1684 return (ULONG) rc;
1688 /******************************************************************************
1689 ** AHI_FreeAudioRequest *******************************************************
1690 ******************************************************************************/
1692 /****** ahi.device/AHI_FreeAudioRequest *************************************
1694 * NAME
1695 * AHI_FreeAudioRequest -- frees requester resources
1697 * SYNOPSIS
1698 * AHI_FreeAudioRequest( requester );
1699 * A0
1701 * void AHI_FreeAudioRequest( struct AHIAudioModeRequester * );
1703 * FUNCTION
1704 * Frees any resources allocated by AHI_AllocAudioRequestA(). Once a
1705 * requester has been freed, it can no longer be used with other calls to
1706 * AHI_AudioRequestA().
1708 * INPUTS
1709 * requester - Requester obtained from AHI_AllocAudioRequestA(), or NULL
1710 * in which case this function does nothing.
1712 * RESULT
1714 * EXAMPLE
1716 * NOTES
1718 * BUGS
1720 * SEE ALSO
1721 * AHI_AllocAudioRequestA()
1723 ****************************************************************************
1727 void
1728 _AHI_FreeAudioRequest( struct AHIAudioModeRequester* req,
1729 struct AHIBase* AHIBase )
1732 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1734 Debug_FreeAudioRequest(req);
1737 if(req)
1738 FreeVec(req);