Fix IRQ name
[AROS.git] / workbench / devs / AHI / Device / requester.c
blobf83d1e334bacb8a44c97e755889eaffbaf308673
1 /*
2 AHI - Hardware independent audio subsystem
3 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
18 MA 02139, USA.
21 #include <config.h>
23 // Fix broken includes
24 struct VSPrite;
26 #include <exec/memory.h>
27 #include <graphics/rpattr.h>
28 #include <intuition/gadgetclass.h>
29 #include <intuition/intuition.h>
30 #include <intuition/intuitionbase.h>
31 #include <libraries/gadtools.h>
32 #include <libraries/asl.h>
34 #include <clib/alib_protos.h>
35 #include <proto/exec.h>
36 #include <proto/dos.h>
37 #include <proto/gadtools.h>
38 #include <proto/graphics.h>
39 #include <proto/intuition.h>
40 #include <proto/utility.h>
41 #define __NOLIBBASE__
42 #define __NOGLOBALIFACE__
43 #include <proto/ahi.h>
44 #undef __NOLIBBASE__
45 #undef __NOGLOBALIFACE__
46 #include <proto/ahi_sub.h>
48 #include <math.h>
49 #include <string.h>
50 #include <stddef.h>
52 #include "ahi_def.h"
53 #include "localize.h"
54 #include "misc.h"
55 #include "modeinfo.h"
56 #include "debug.h"
57 #include "gateway.h"
59 #define min(a,b) (((a)<(b))?(a):(b))
60 #define max(a,b) (((a)>(b))?(a):(b))
62 struct AHIAudioModeRequesterExt;
64 static void OpenInfoWindow( struct AHIAudioModeRequesterExt * );
65 static void CloseInfoWindow( struct AHIAudioModeRequesterExt * );
66 static void UpdateInfoWindow( struct AHIAudioModeRequesterExt * );
69 /******************************************************************************
70 ** Audio mode requester ******************************************************
71 ******************************************************************************/
73 #define MY_IDCMPS (LISTVIEWIDCMP|SLIDERIDCMP|BUTTONIDCMP|IDCMP_SIZEVERIFY|IDCMP_NEWSIZE|IDCMP_REFRESHWINDOW|IDCMP_CLOSEWINDOW|IDCMP_MENUPICK|IDCMP_VANILLAKEY|IDCMP_RAWKEY)
74 #define MY_INFOIDCMPS (LISTVIEWIDCMP|IDCMP_REFRESHWINDOW|IDCMP_CLOSEWINDOW)
76 #define haveIDCMP 0x0001
77 #define lockwin 0x0002
78 #define freqgad 0x0004
79 #define ownIDCMP 0x0008
80 #define defaultmode 0x0010
82 static const struct TagItem reqboolmap[] =
84 { AHIR_PrivateIDCMP, haveIDCMP },
85 { AHIR_SleepWindow, lockwin },
86 { AHIR_DoMixFreq, freqgad },
87 { AHIR_DoDefaultMode, defaultmode },
88 { TAG_DONE, 0 }
91 #define LASTMODEITEM 1
92 #define NEXTMODEITEM 2
93 #define PROPERTYITEM 3
94 #define RESTOREITEM 4
95 #define OKITEM 5
96 #define CANCELITEM 6
98 /* Node for audio mode requester */
100 struct IDnode
102 struct Node node;
103 ULONG ID;
104 char name[80];
107 /* The attribues list */
109 #define ATTRNODES 6
111 struct Attrnode
113 struct Node node;
114 UBYTE text[80];
117 /* AHIAudioModeRequester extension */
118 struct AHIAudioModeRequesterExt
120 struct AHIAudioModeRequester Req;
121 ULONG tempAudioID;
122 ULONG tempFrequency;
123 struct Window *SrcWindow;
124 STRPTR PubScreenName;
125 struct Screen *Screen;
126 ULONG Flags;
127 struct Hook *IntuiMsgFunc;
128 struct TextAttr *TextAttr;
129 struct Locale *Locale;
130 STRPTR TitleText;
131 STRPTR PositiveText;
132 STRPTR NegativeText;
133 struct TagItem *FilterTags;
134 struct Hook *FilterFunc;
136 // struct Screen *PubScreen;
137 struct Window *Window;
138 struct Window *InfoWindow;
139 WORD gx,gy,gw,gh;
140 APTR vi;
141 struct Gadget *Gadgets;
142 struct Gadget *InfoGadgets;
143 struct Gadget *InfoListViewGadget;
144 struct Gadget *listviewgadget;
145 struct Gadget *slidergadget;
146 struct MinList *list;
147 struct MinList InfoList;
148 struct Menu *Menu;
149 struct Catalog *Catalog;
150 struct Attrnode AttrNodes[ATTRNODES];
154 static const struct TextAttr Topaz80 = { "topaz.font", 8, 0, 0, };
156 #define MINSLIDERWIDTH 40
158 #define OKBUTTON 1
159 #define CANCELBUTTON 2
160 #define FREQSLIDER 3
161 #define LISTVIEW 4
163 #define FREQTEXT2 GetString(msgFreqFmt, req->Catalog) //"%lu Hz"
164 #define FREQLEN2 (5+3) // 5 digits + space + "Hz"
166 LONG IndexToFrequency( struct Gadget *gad, WORD level )
168 LONG freq = 0;
169 ULONG id;
171 id = ((struct AHIAudioModeRequesterExt *)gad->UserData)->tempAudioID;
173 if(id != AHI_DEFAULT_ID)
175 AHI_GetAudioAttrs( id, NULL,
176 AHIDB_FrequencyArg, level,
177 AHIDB_Frequency, &freq,
178 TAG_DONE );
180 else
182 freq = AHIBase->ahib_Frequency;
184 return freq;
188 static void FillReqStruct(struct AHIAudioModeRequesterExt *req, struct TagItem *tags)
190 ULONG obsolete_userdata;
192 // Check all known tags
193 req->SrcWindow=(struct Window *)GetTagData(AHIR_Window,(IPTR)req->SrcWindow,tags);
194 req->PubScreenName=(STRPTR)GetTagData(AHIR_PubScreenName,(IPTR)req->PubScreenName,tags);
195 req->Screen=(struct Screen *)GetTagData(AHIR_Screen,(IPTR)req->Screen,tags);
196 req->IntuiMsgFunc=(struct Hook *)GetTagData(AHIR_IntuiMsgFunc,(IPTR)req->IntuiMsgFunc,tags);
198 obsolete_userdata = GetTagData( AHIR_ObsoleteUserData, 0, tags );
199 req->Req.ahiam_ObsoleteUserData[ 0 ] = obsolete_userdata >> 16;
200 req->Req.ahiam_ObsoleteUserData[ 1 ] = obsolete_userdata & 0xffff;
202 req->Req.ahiam_UserData=(void *)GetTagData(AHIR_UserData,(IPTR)req->Req.ahiam_UserData,tags);
203 req->TextAttr=(struct TextAttr *)GetTagData(AHIR_TextAttr,(IPTR)req->TextAttr,tags);
204 req->Locale=(struct Locale *)GetTagData(AHIR_Locale,(IPTR)req->Locale,tags);
205 req->TitleText=(STRPTR)GetTagData(AHIR_TitleText,(IPTR)req->TitleText,tags);
206 req->PositiveText=(STRPTR)GetTagData(AHIR_PositiveText,(IPTR)req->PositiveText,tags);
207 req->NegativeText=(STRPTR)GetTagData(AHIR_NegativeText,(IPTR)req->NegativeText,tags);
208 req->Req.ahiam_LeftEdge=GetTagData(AHIR_InitialLeftEdge,req->Req.ahiam_LeftEdge,tags);
209 req->Req.ahiam_TopEdge=GetTagData(AHIR_InitialTopEdge,req->Req.ahiam_TopEdge,tags);
210 req->Req.ahiam_Width=GetTagData(AHIR_InitialWidth,req->Req.ahiam_Width,tags);
211 req->Req.ahiam_Height=GetTagData(AHIR_InitialHeight,req->Req.ahiam_Height,tags);
212 req->Req.ahiam_AudioID=GetTagData(AHIR_InitialAudioID,req->Req.ahiam_AudioID,tags);
213 req->Req.ahiam_MixFreq=GetTagData(AHIR_InitialMixFreq,req->Req.ahiam_MixFreq,tags);
214 req->Req.ahiam_InfoOpened=GetTagData(AHIR_InitialInfoOpened,req->Req.ahiam_InfoOpened,tags);
215 req->Req.ahiam_InfoLeftEdge=GetTagData(AHIR_InitialInfoLeftEdge,req->Req.ahiam_InfoLeftEdge,tags);
216 req->Req.ahiam_InfoTopEdge=GetTagData(AHIR_InitialInfoTopEdge,req->Req.ahiam_InfoTopEdge,tags);
217 // req->Req.ahiam_InfoWidth=GetTagData(AHIR_InitialInfoWidth,req->Req.ahiam_InfoWidth,tags);
218 // req->Req.ahiam_InfoHeight=GetTagData(AHIR_InitialInfoHeight,req->Req.ahiam_InfoHeight,tags);
219 req->FilterTags=(struct TagItem *)GetTagData(AHIR_FilterTags,(IPTR)req->FilterTags,tags);
220 req->FilterFunc=(struct Hook *)GetTagData(AHIR_FilterFunc,(IPTR)req->FilterFunc,tags);
221 req->Flags=PackBoolTags(req->Flags,tags,reqboolmap);
225 static void
226 CalculateWindowSizePos( struct AHIAudioModeRequesterExt* req,
227 struct Screen* screen )
229 struct AslSemaphore* asl_semaphore = NULL;
231 // Default position and size
232 WORD left = 30;
233 WORD top = 20;
234 WORD width = 318;
235 WORD height = 198;
237 #ifdef ASL_SEMAPHORE_NAME /* Don't break if no v45 includes found */
238 Forbid();
239 asl_semaphore = (struct AslSemaphore*) FindSemaphore( ASL_SEMAPHORE_NAME );
241 if( asl_semaphore != NULL )
243 ObtainSemaphore( (struct SignalSemaphore*) asl_semaphore );
245 Permit();
247 if( asl_semaphore != NULL )
249 if( asl_semaphore->as_Version >= 45 &&
250 asl_semaphore->as_Size > offsetof( struct AslSemaphore,
251 as_RelativeHeight ) )
253 if( asl_semaphore->as_SizePosition & ASLOPTION_ASLOverrides )
255 // Force default settings
256 req->Req.ahiam_LeftEdge = -1;
257 req->Req.ahiam_TopEdge = -1;
258 req->Req.ahiam_Width = -1;
259 req->Req.ahiam_Height = -1;
262 if( ( asl_semaphore->as_SizePosition & ASLSIZE_MASK ) ==
263 ASLSIZE_RelativeSize )
265 // FIXME: Is it correct to use screen size only? The include file
266 // says something about parent window??
268 width = (WORD) ( (LONG) screen->Width *
269 asl_semaphore->as_RelativeWidth / 100 );
270 height = (WORD) ( (LONG) screen->Height *
271 asl_semaphore->as_RelativeHeight / 100 );
274 else
276 // Not valid
277 ReleaseSemaphore( (struct SignalSemaphore*) asl_semaphore );
278 asl_semaphore = NULL;
281 #endif
283 // Set default main window size
284 if( req->Req.ahiam_Width == -1 )
285 req->Req.ahiam_Width = width;
287 if( req->Req.ahiam_Height == -1 )
288 req->Req.ahiam_Height = height;
291 #ifdef ASL_SEMAPHORE_NAME /* Don't break if no v45 includes found */
292 if( asl_semaphore != NULL )
294 switch( asl_semaphore->as_SizePosition & ASLPOS_MASK )
296 case ASLPOS_CenterWindow:
297 if( req->SrcWindow != NULL )
299 top = ( req->SrcWindow->TopEdge +
300 req->SrcWindow->Height / 2 -
301 req->Req.ahiam_Height / 2 );
302 left = ( req->SrcWindow->LeftEdge +
303 req->SrcWindow->Width / 2 -
304 req->Req.ahiam_Width / 2 );
305 break;
307 else
309 // Fall through and use ASLPOS_CenterScreen instead
312 case ASLPOS_CenterScreen:
313 top = ( screen->Height / 2 -
314 req->Req.ahiam_Height / 2 );
315 left = ( screen->Width / 2 -
316 req->Req.ahiam_Width / 2 );
317 break;
319 case ASLPOS_WindowPosition:
320 if( req->SrcWindow != NULL )
322 top = ( req->SrcWindow->TopEdge +
323 asl_semaphore->as_RelativeTop );
324 left = ( req->SrcWindow->LeftEdge +
325 asl_semaphore->as_RelativeLeft );
326 break;
328 else
330 // Fall through and use ASLPOS_ScreenPosition instead
333 case ASLPOS_ScreenPosition:
334 top = asl_semaphore->as_RelativeTop;
335 left = asl_semaphore->as_RelativeLeft;
336 break;
338 case ASLPOS_CenterMouse:
339 top = ( screen->MouseY -
340 req->Req.ahiam_Height / 2 );
341 left = ( screen->MouseX -
342 req->Req.ahiam_Width / 2 );
343 break;
345 case ASLPOS_DefaultPosition:
346 default:
347 // Do nothing (use hardcoded defaults)
348 break;
351 #endif
353 // Set default main window position
354 if( req->Req.ahiam_LeftEdge == -1 )
355 req->Req.ahiam_LeftEdge = left;
357 if( req->Req.ahiam_TopEdge == -1 )
358 req->Req.ahiam_TopEdge = top;
361 // Set default info window position (size is fixed)
362 if( req->Req.ahiam_InfoLeftEdge == -1 )
363 req->Req.ahiam_InfoLeftEdge = req->Req.ahiam_LeftEdge + 16;
365 if( req->Req.ahiam_InfoTopEdge == -1 )
366 req->Req.ahiam_InfoTopEdge = req->Req.ahiam_TopEdge + 25;
369 // Clean up
370 if( asl_semaphore != NULL )
372 ReleaseSemaphore( (struct SignalSemaphore*) asl_semaphore );
377 ** Returns the ordinal number of the current audio id.
380 static LONG GetSelected(struct AHIAudioModeRequesterExt *req)
382 struct IDnode *idnode;
383 LONG valt=0;
385 for(idnode=(struct IDnode *)req->list->mlh_Head;
386 idnode->node.ln_Succ;
387 idnode=(struct IDnode *) idnode->node.ln_Succ)
389 if(idnode->ID == req->tempAudioID)
390 break;
391 else
392 valt++;
394 if(idnode->node.ln_Succ == NULL)
396 valt=~0;
397 req->tempAudioID=AHI_INVALID_ID; // Crashed if this is not done! FIXIT!
399 return valt;
403 ** Calculates what the current slider level shoud be and how many levels total
406 static void GetSliderAttrs(struct AHIAudioModeRequesterExt *req, LONG *levels, LONG *level)
408 *levels=0;
409 *level=0;
411 AHI_GetAudioAttrs(req->tempAudioID, NULL,
412 AHIDB_Frequencies, levels,
413 AHIDB_IndexArg, (req->tempAudioID == AHI_DEFAULT_ID ?
414 AHIBase->ahib_Frequency : req->tempFrequency),
415 AHIDB_Index, level,
416 TAG_DONE);
418 if(*level >= *levels)
419 *level = *levels-1;
421 AHI_GetAudioAttrs(req->tempAudioID, NULL,
422 AHIDB_FrequencyArg, *level,
423 AHIDB_Frequency, &req->tempFrequency,
424 TAG_DONE);
428 ** Updates the requester to the current frequency and if 'all'==TRUE, audio mode.
431 static void SetSelected(struct AHIAudioModeRequesterExt *req, BOOL all)
433 LONG sliderlevels,sliderlevel,selected;
434 BOOL disabled = FALSE;
435 ULONG top = GTLV_Top;
436 ULONG makevisible = GTLV_MakeVisible;
438 if(all)
440 //Set listview
441 selected=GetSelected(req);
443 if( selected == ~0 || GadToolsBase->lib_Version >= 39 )
445 top = TAG_IGNORE;
448 if( selected == ~0 )
450 makevisible = TAG_IGNORE;
453 GT_SetGadgetAttrs(req->listviewgadget, req->Window, NULL,
454 top, selected,
455 makevisible, selected,
456 GTLV_Selected, selected,
457 TAG_DONE);
460 //Set slider
461 GetSliderAttrs(req,&sliderlevels,&sliderlevel);
463 if( sliderlevels == 0 || req->tempAudioID == AHI_DEFAULT_ID )
465 disabled = TRUE;
468 GT_SetGadgetAttrs(req->slidergadget, req->Window, NULL,
469 GTSL_Max, sliderlevels-1,
470 GTSL_Level, sliderlevel,
471 GA_Disabled, disabled,
472 TAG_DONE);
474 UpdateInfoWindow(req);
479 ** Positions all gadgets in the requester.
482 static BOOL LayOutReq (struct AHIAudioModeRequesterExt *req, const struct TextAttr *TextAttr)
484 struct Gadget *gad;
485 struct NewGadget ng;
487 struct TextAttr *gadtextattr;
488 struct TextFont *font;
489 LONG fontwidth,buttonheight,buttonwidth,pixels;
490 struct IntuiText intuitext = {1,0,JAM1,0,0,NULL,NULL,NULL};
491 LONG sliderlevels,sliderlevel;
492 LONG selected;
494 selected=GetSelected(req);
495 GetSliderAttrs(req,&sliderlevels,&sliderlevel);
497 // Calculate gadget area
498 req->gx=req->Window->BorderLeft+4;
499 req->gy=req->Window->BorderTop+2;
500 req->gw=req->Window->Width-req->gx-(req->Window->BorderRight+4);
501 req->gh=req->Window->Height-req->gy-(req->Window->BorderBottom+2);
503 if(req->Gadgets)
505 RemoveGList(req->Window,req->Gadgets,-1);
506 FreeGadgets(req->Gadgets);
507 SetAPen(req->Window->RPort,0);
508 SetDrMd(req->Window->RPort,JAM1);
509 EraseRect(req->Window->RPort, req->Window->BorderLeft, req->Window->BorderTop,
510 req->Window->Width-req->Window->BorderRight-1,req->Window->Height-req->Window->BorderBottom-1);
511 RefreshWindowFrame(req->Window);
513 req->Gadgets=NULL;
514 if((gad=CreateContext(&req->Gadgets)))
516 if(TextAttr)
517 gadtextattr=(struct TextAttr *)TextAttr;
518 else
519 gadtextattr=req->Window->WScreen->Font;
521 if((font=OpenFont(gadtextattr)))
523 fontwidth=font->tf_XSize;
524 CloseFont(font);
526 else
527 return FALSE;
529 buttonheight=gadtextattr->ta_YSize+6;
530 intuitext.ITextFont=gadtextattr;
531 intuitext.IText=req->PositiveText;
532 buttonwidth=IntuiTextLength(&intuitext);
533 intuitext.IText=req->NegativeText;
534 pixels=IntuiTextLength(&intuitext);
535 buttonwidth=max(pixels,buttonwidth);
536 buttonwidth+=4+fontwidth;
538 // Create gadgets and check if they fit
539 // Do the two buttons fit?
540 if(2*buttonwidth > req->gw)
541 return FALSE;
542 ng.ng_TextAttr=gadtextattr;
543 ng.ng_VisualInfo=req->vi;
544 ng.ng_UserData=req;
545 // OK button
546 ng.ng_LeftEdge=req->gx;
547 ng.ng_TopEdge=req->gy+req->gh-buttonheight;
548 ng.ng_Width=buttonwidth;
549 ng.ng_Height=buttonheight;
550 ng.ng_GadgetText=req->PositiveText;
551 ng.ng_GadgetID=OKBUTTON;
552 ng.ng_Flags=PLACETEXT_IN;
553 gad=CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);
554 // Cancel button
555 ng.ng_LeftEdge=req->gx+req->gw-ng.ng_Width;
556 ng.ng_GadgetText=req->NegativeText;
557 ng.ng_GadgetID=CANCELBUTTON;
558 gad=CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);
559 // Frequency
560 if(req->Flags & freqgad)
562 intuitext.IText = GetString(msgReqFrequency, req->Catalog);
563 pixels=IntuiTextLength(&intuitext)+INTERWIDTH;
564 if(pixels+MINSLIDERWIDTH+INTERWIDTH+FREQLEN2*fontwidth > req->gw)
565 return FALSE;
566 ng.ng_Width=req->gw-pixels-INTERWIDTH-FREQLEN2*fontwidth;
567 ng.ng_LeftEdge=req->gx+pixels;
568 ng.ng_TopEdge-=2+buttonheight;
569 ng.ng_GadgetText = GetString(msgReqFrequency, req->Catalog);
570 ng.ng_GadgetID=FREQSLIDER;
571 ng.ng_Flags=PLACETEXT_LEFT;
572 gad=CreateGadget(SLIDER_KIND,gad,&ng,
573 GTSL_Min,0,
574 GTSL_Max,sliderlevels-1,
575 GTSL_Level,sliderlevel,
576 GTSL_LevelFormat, FREQTEXT2,
577 GTSL_MaxLevelLen,FREQLEN2,
578 GTSL_LevelPlace,PLACETEXT_RIGHT,
579 GTSL_DispFunc, m68k_IndexToFrequency,
580 GA_RelVerify,TRUE,
581 GA_Disabled,!sliderlevels || (req->tempAudioID == AHI_DEFAULT_ID),
582 TAG_DONE);
583 req->slidergadget=gad; // Save for HadleReq()...
585 // ListView
586 if((ng.ng_Height=ng.ng_TopEdge-2-req->gy) < buttonheight)
587 return FALSE;
588 ng.ng_LeftEdge=req->gx;
589 ng.ng_TopEdge=req->gy;
590 ng.ng_Width=req->gw;
591 ng.ng_GadgetText=NULL,
592 ng.ng_GadgetID=LISTVIEW;
593 ng.ng_Flags=PLACETEXT_ABOVE;
594 gad=CreateGadget(LISTVIEW_KIND,gad,&ng,
595 GTLV_ScrollWidth,(fontwidth>8 ? fontwidth*2 : 18),
596 GTLV_Labels, req->list,
597 GTLV_ShowSelected,0,
598 ((selected == ~0) || (GadToolsBase->lib_Version >= 39) ? TAG_IGNORE : GTLV_Top),selected,
599 (selected == ~0 ? TAG_IGNORE : GTLV_MakeVisible),selected,
600 GTLV_Selected,selected,
601 TAG_DONE);
602 req->listviewgadget=gad; // Save for HadleReq()...
604 if(!gad)
605 return FALSE;
607 else
608 return FALSE;
610 AddGList(req->Window,req->Gadgets,~0,-1,NULL);
611 RefreshGList(req->Gadgets,req->Window,NULL,-1);
612 GT_RefreshWindow(req->Window,NULL);
614 return TRUE;
619 /* these functions close an Intuition window
620 * that shares a port with other Intuition
621 * windows or IPC customers.
623 * We are careful to set the UserPort to
624 * null before closing, and to free
625 * any messages that it might have been
626 * sent.
629 /* remove and reply all IntuiMessages on a port that
630 * have been sent to a particular window
631 * (note that we don't rely on the ln_Succ pointer
632 * of a message after we have replied it)
634 static void StripIntuiMessagesAHI( struct MsgPort *mp, struct Window *win )
636 struct IntuiMessage *msg;
637 struct Node *succ;
639 msg = (struct IntuiMessage *) mp->mp_MsgList.lh_Head;
641 while((succ = msg->ExecMessage.mn_Node.ln_Succ)) {
643 if( msg->IDCMPWindow == win ) {
645 /* Intuition is about to free this message.
646 * Make sure that we have politely sent it back.
648 Remove( (struct Node *) msg );
650 ReplyMsg( (struct Message *) msg );
653 msg = (struct IntuiMessage *) succ;
657 static void CloseWindowSafely( struct Window *win )
659 /* we forbid here to keep out of race conditions with Intuition */
660 Forbid();
662 /* send back any messages for this window
663 * that have not yet been processed
665 StripIntuiMessagesAHI( win->UserPort, win );
667 /* clear UserPort so Intuition will not free it */
668 win->UserPort = NULL;
670 /* tell Intuition to stop sending more messages */
671 ModifyIDCMP( win, 0L );
673 /* turn multitasking back on */
674 Permit();
676 /* and really close the window */
677 CloseWindow( win );
680 static BOOL HandleReq( struct AHIAudioModeRequesterExt *req )
682 // Returns FALSE if requester was cancelled
685 BOOL done=FALSE,rc=TRUE;
686 ULONG class,sec,oldsec=0,micro,oldmicro=0,oldid=AHI_INVALID_ID;
687 UWORD code;
688 UWORD qual;
689 struct Gadget *pgsel;
690 struct IntuiMessage *imsg;
691 struct IDnode *idnode;
692 LONG sliderlevels,sliderlevel,i,selected;
693 struct MenuItem *item;
695 while(!done)
697 Wait(1L << req->Window->UserPort->mp_SigBit);
699 while ((imsg=GT_GetIMsg(req->Window->UserPort)) != NULL )
702 if(imsg->IDCMPWindow == req->InfoWindow)
704 class = imsg->Class;
705 GT_ReplyIMsg(imsg);
707 switch(class)
709 case IDCMP_CLOSEWINDOW:
710 CloseInfoWindow(req);
711 break;
712 case IDCMP_REFRESHWINDOW :
713 GT_BeginRefresh(req->InfoWindow);
714 GT_EndRefresh(req->InfoWindow,TRUE);
715 break;
717 continue; // Get next IntuiMessage
720 else if(imsg->IDCMPWindow != req->Window) // Not my window!
722 if(req->IntuiMsgFunc)
723 CallHookPkt(req->IntuiMsgFunc,req,imsg);
724 // else what to do??? Reply and forget? FIXIT!
725 continue;
728 sec=imsg->Seconds;
729 micro=imsg->Micros;
730 qual=imsg->Qualifier;
731 class=imsg->Class;
732 code=imsg->Code;
733 pgsel=(struct Gadget *)imsg->IAddress; // pgsel illegal if not gadget
734 GT_ReplyIMsg(imsg);
736 switch ( class )
738 case IDCMP_RAWKEY:
739 switch (code)
741 case 0x4c: // Cursor Up
742 selected=GetSelected(req);
743 if(selected == ~0)
744 selected=0;
745 if(selected > 0)
746 selected--;
747 idnode=(struct IDnode *)req->list->mlh_Head;
748 for(i=0;i<selected;i++)
749 idnode=(struct IDnode *)idnode->node.ln_Succ;
750 req->tempAudioID=idnode->ID;
751 SetSelected(req,TRUE);
752 break;
753 case 0x4d: // Cursor Down
754 selected=GetSelected(req);
755 selected++; // ~0 => 0
756 idnode=(struct IDnode *)req->list->mlh_Head;
757 for(i=0;i<selected;i++)
758 if(idnode->node.ln_Succ->ln_Succ)
759 idnode=(struct IDnode *)idnode->node.ln_Succ;
760 req->tempAudioID=idnode->ID;
761 SetSelected(req,TRUE);
762 break;
763 case 0x4e: // Cursor Right
764 GetSliderAttrs(req,&sliderlevels,&sliderlevel);
765 sliderlevel += (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? 10 :1);
766 if(sliderlevel >= sliderlevels)
767 sliderlevel=sliderlevels-1;
768 AHI_GetAudioAttrs(req->tempAudioID, NULL,
769 AHIDB_FrequencyArg,sliderlevel,
770 AHIDB_Frequency, &req->tempFrequency,
771 TAG_DONE);
772 SetSelected(req,FALSE);
773 break;
774 case 0x4f: // Cursor Left
775 GetSliderAttrs(req,&sliderlevels,&sliderlevel);
776 sliderlevel -= (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? 10 :1);
777 if(sliderlevel < 0)
778 sliderlevel=0;
779 AHI_GetAudioAttrs(req->tempAudioID, NULL,
780 AHIDB_FrequencyArg,sliderlevel,
781 AHIDB_Frequency, &req->tempFrequency,
782 TAG_DONE);
783 SetSelected(req,FALSE);
784 break;
786 break;
787 case IDCMP_GADGETUP :
788 switch ( pgsel->GadgetID )
790 case OKBUTTON:
791 done=TRUE;
792 break;
793 case CANCELBUTTON:
794 done=TRUE;
795 rc=FALSE;
796 break;
797 case FREQSLIDER:
798 AHI_GetAudioAttrs(req->tempAudioID, NULL,
799 AHIDB_FrequencyArg,code,
800 AHIDB_Frequency, &req->tempFrequency,
801 TAG_DONE);
802 break;
803 case LISTVIEW:
804 idnode=(struct IDnode *)req->list->mlh_Head;
805 for(i=0;i<code;i++)
806 idnode=(struct IDnode *)idnode->node.ln_Succ;
807 req->tempAudioID=idnode->ID;
808 SetSelected(req,FALSE);
809 // Test doubleclick and save timestamp
810 if( (oldid == req->tempAudioID) && DoubleClick(oldsec,oldmicro,sec,micro))
811 done=TRUE;
812 oldsec=sec;
813 oldmicro=micro;
814 oldid=req->tempAudioID;
816 break;
818 break;
820 case IDCMP_NEWSIZE:
821 if(!(LayOutReq(req,req->TextAttr)))
822 if(!(LayOutReq(req,&Topaz80)))
824 // ERROR! Quit.
825 done=TRUE;
826 break;
828 break;
829 case IDCMP_CLOSEWINDOW:
830 done=TRUE;
831 rc=FALSE;
832 break;
833 case IDCMP_REFRESHWINDOW :
834 GT_BeginRefresh(req->Window);
835 GT_EndRefresh(req->Window,TRUE);
836 break;
837 case IDCMP_SIZEVERIFY:
838 break;
839 case IDCMP_MENUPICK:
840 while((code != MENUNULL) && !done)
842 item=ItemAddress(req->Menu, code);
843 switch((IPTR)GTMENUITEM_USERDATA(item))
845 case LASTMODEITEM:
846 selected=GetSelected(req);
847 if(selected == ~0)
848 selected=0;
849 if(selected > 0)
850 selected--;
851 idnode=(struct IDnode *)req->list->mlh_Head;
852 for(i=0;i<selected;i++)
853 idnode=(struct IDnode *)idnode->node.ln_Succ;
854 req->tempAudioID=idnode->ID;
855 SetSelected(req,TRUE);
856 break;
857 case NEXTMODEITEM:
858 selected=GetSelected(req);
859 selected++; // ~0 => 0
860 idnode=(struct IDnode *)req->list->mlh_Head;
861 for(i=0;i<selected;i++)
862 if(idnode->node.ln_Succ->ln_Succ)
863 idnode=(struct IDnode *)idnode->node.ln_Succ;
864 req->tempAudioID=idnode->ID;
865 SetSelected(req,TRUE);
866 break;
867 case PROPERTYITEM:
868 OpenInfoWindow(req);
869 break;
870 case RESTOREITEM:
871 req->tempAudioID=req->Req.ahiam_AudioID;
872 req->tempFrequency=req->Req.ahiam_MixFreq;
873 SetSelected(req,TRUE);
874 break;
875 case OKITEM:
876 done=TRUE;
877 break;
878 case CANCELITEM:
879 done=TRUE;
880 rc=FALSE;
881 break;
883 code = item->NextSelect;
885 break;
890 if(rc)
892 req->Req.ahiam_AudioID = req->tempAudioID;
894 if(req->tempAudioID != AHI_DEFAULT_ID)
896 req->Req.ahiam_MixFreq = req->tempFrequency;
898 else
900 req->Req.ahiam_MixFreq = AHI_DEFAULT_FREQ;
903 return rc;
907 static void OpenInfoWindow( struct AHIAudioModeRequesterExt *req )
909 struct Gadget *gad;
910 struct NewGadget ng;
913 if(req->InfoWindow == NULL)
915 req->InfoWindow=OpenWindowTags(NULL,
916 WA_Left, req->Req.ahiam_InfoLeftEdge,
917 WA_Top, req->Req.ahiam_InfoTopEdge,
918 WA_Width, req->Req.ahiam_InfoWidth,
919 WA_Height, req->Req.ahiam_InfoHeight,
920 WA_Title, GetString(msgReqInfoTitle, req->Catalog),
921 WA_CustomScreen, req->Window->WScreen,
922 WA_PubScreenFallBack, TRUE,
923 WA_DragBar, TRUE,
924 WA_DepthGadget, TRUE,
925 WA_CloseGadget, TRUE,
926 WA_Activate, FALSE,
927 WA_SimpleRefresh, TRUE,
928 WA_AutoAdjust, TRUE,
929 WA_IDCMP, 0,
930 WA_NewLookMenus, TRUE,
931 TAG_DONE);
933 if(req->InfoWindow)
935 req->InfoWindow->UserPort = req->Window->UserPort;
936 ModifyIDCMP(req->InfoWindow, MY_INFOIDCMPS);
938 if((gad = CreateContext(&req->InfoGadgets)))
940 ng.ng_TextAttr = req->TextAttr;
941 ng.ng_VisualInfo = req->vi;
942 ng.ng_LeftEdge = req->InfoWindow->BorderLeft+4;
943 ng.ng_TopEdge = req->InfoWindow->BorderTop+2;
944 ng.ng_Width = req->InfoWindow->Width
945 - (req->InfoWindow->BorderLeft+4)
946 - (req->InfoWindow->BorderRight+4);
947 ng.ng_Height = req->InfoWindow->Height
948 - (req->InfoWindow->BorderTop+2)
949 - (req->InfoWindow->BorderBottom+2);
951 ng.ng_GadgetText = NULL;
952 ng.ng_GadgetID = 0;
953 ng.ng_Flags = PLACETEXT_ABOVE;
954 gad = CreateGadget(LISTVIEW_KIND, gad, &ng,
955 GTLV_ReadOnly, TRUE,
956 TAG_DONE);
957 req->InfoListViewGadget = gad;
959 if(gad)
961 AddGList(req->InfoWindow, req->InfoGadgets, ~0, -1, NULL);
962 RefreshGList(req->InfoGadgets, req->InfoWindow, NULL, -1);
963 GT_RefreshWindow(req->InfoWindow, NULL);
964 UpdateInfoWindow(req);
972 static void UpdateInfoWindow( struct AHIAudioModeRequesterExt *req )
974 LONG id=0, bits=0, stereo=0, pan=0, hifi=0, channels=0, minmix=0, maxmix=0,
975 record=0, fullduplex=0, multichannel=0;
976 int i;
978 id = req->tempAudioID;
979 if(id == AHI_DEFAULT_ID)
981 id = AHIBase->ahib_AudioMode;
983 if(req->InfoWindow)
985 AHI_GetAudioAttrs(id, NULL,
986 AHIDB_MultiChannel, &multichannel,
987 AHIDB_Stereo, &stereo,
988 AHIDB_Panning, &pan,
989 AHIDB_HiFi, &hifi,
990 AHIDB_Record, &record,
991 AHIDB_FullDuplex, &fullduplex,
992 AHIDB_Bits, &bits,
993 AHIDB_MaxChannels, &channels,
994 AHIDB_MinMixFreq, &minmix,
995 AHIDB_MaxMixFreq, &maxmix,
996 TAG_DONE);
998 GT_SetGadgetAttrs(req->InfoListViewGadget, req->InfoWindow, NULL,
999 GTLV_Labels, ~0,
1000 TAG_DONE);
1002 NewList((struct List *) &req->InfoList);
1003 for(i=0; i<ATTRNODES; i++)
1005 req->AttrNodes[i].node.ln_Name = req->AttrNodes[i].text;
1006 req->AttrNodes[i].text[0] = '\0';
1007 req->AttrNodes[i].node.ln_Type = NT_USER;
1008 req->AttrNodes[i].node.ln_Pri = 0;
1011 i = 0;
1012 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1013 Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoAudioID, req->Catalog),
1014 id);
1015 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1016 Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoResolution, req->Catalog),
1017 bits, GetString((multichannel ? msgReqInfoMultiChannel : (stereo ?
1018 (pan ? msgReqInfoStereoPan : msgReqInfoStereo) :
1019 msgReqInfoMono)), req->Catalog));
1020 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1021 Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoChannels, req->Catalog),
1022 channels);
1023 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1024 Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoMixrate, req->Catalog),
1025 minmix, maxmix);
1026 if(hifi)
1028 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1029 Sprintf(req->AttrNodes[i++].text, GetString(msgReqInfoHiFi, req->Catalog));
1031 if(record)
1033 AddTail((struct List *) &req->InfoList,(struct Node *) &req->AttrNodes[i]);
1034 Sprintf(req->AttrNodes[i++].text, GetString(
1035 fullduplex ? msgReqInfoRecordFull : msgReqInfoRecordHalf, req->Catalog));
1038 GT_SetGadgetAttrs(req->InfoListViewGadget, req->InfoWindow, NULL,
1039 GTLV_Labels, &req->InfoList,
1040 TAG_DONE);
1044 static void CloseInfoWindow( struct AHIAudioModeRequesterExt *req )
1046 if(req->InfoWindow)
1048 req->Req.ahiam_InfoOpened = TRUE;
1049 req->Req.ahiam_InfoLeftEdge = req->InfoWindow->LeftEdge;
1050 req->Req.ahiam_InfoTopEdge = req->InfoWindow->TopEdge;
1051 req->Req.ahiam_InfoWidth = req->InfoWindow->Width;
1052 req->Req.ahiam_InfoHeight = req->InfoWindow->Height;
1053 CloseWindowSafely(req->InfoWindow);
1054 req->InfoWindow = NULL;
1057 else
1059 req->Req.ahiam_InfoOpened = FALSE;
1063 FreeGadgets(req->InfoGadgets);
1064 req->InfoGadgets = NULL;
1068 /******************************************************************************
1069 ** AHI_AllocAudioRequestA *****************************************************
1070 ******************************************************************************/
1072 /****** ahi.device/AHI_AllocAudioRequestA ***********************************
1074 * NAME
1075 * AHI_AllocAudioRequestA -- allocate an audio mode requester.
1076 * AHI_AllocAudioRequest -- varargs stub for AHI_AllocAudioRequestA()
1078 * SYNOPSIS
1079 * requester = AHI_AllocAudioRequestA( tags );
1080 * D0 A0
1082 * struct AHIAudioModeRequester *AHI_AllocAudioRequestA(
1083 * struct TagItem * );
1085 * requester = AHI_AllocAudioRequest( tag1, ... );
1087 * struct AHIAudioModeRequester *AHI_AllocAudioRequest( Tag, ... );
1089 * FUNCTION
1090 * Allocates an audio mode requester data structure.
1092 * INPUTS
1093 * tags - A pointer to an optional tag list specifying how to initialize
1094 * the data structure returned by this function. See the
1095 * documentation for AHI_AudioRequestA() for an explanation of how
1096 * to use the currently defined tags.
1098 * RESULT
1099 * requester - An initialized requester data structure, or NULL on
1100 * failure.
1102 * EXAMPLE
1104 * NOTES
1105 * The requester data structure is READ-ONLY and can only be modified
1106 * by using tags!
1108 * BUGS
1110 * SEE ALSO
1111 * AHI_AudioRequestA(), AHI_FreeAudioRequest()
1113 ****************************************************************************
1117 struct AHIAudioModeRequester*
1118 _AHI_AllocAudioRequestA( struct TagItem* tags,
1119 struct AHIBase* AHIBase )
1121 struct AHIAudioModeRequesterExt *req;
1123 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1125 Debug_AllocAudioRequestA(tags);
1128 if((req=AllocVec(sizeof(struct AHIAudioModeRequesterExt),MEMF_CLEAR)))
1130 // Fill in defaults
1131 req->Req.ahiam_LeftEdge = -1;
1132 req->Req.ahiam_TopEdge = -1;
1133 req->Req.ahiam_Width = -1;
1134 req->Req.ahiam_Height = -1;
1136 req->Req.ahiam_AudioID = AHI_INVALID_ID;
1137 req->Req.ahiam_MixFreq = AHIBase->ahib_Frequency;
1139 req->Req.ahiam_InfoLeftEdge = -1;
1140 req->Req.ahiam_InfoTopEdge = -1;
1141 req->Req.ahiam_InfoWidth = 280;
1142 req->Req.ahiam_InfoHeight = 112;
1144 req->PubScreenName = (STRPTR) -1;
1146 FillReqStruct(req,tags);
1149 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1151 KPrintF("=>0x%P\n", req);
1154 return (struct AHIAudioModeRequester *) req;
1158 /******************************************************************************
1159 ** AHI_AudioRequestA **********************************************************
1160 ******************************************************************************/
1162 /****** ahi.device/AHI_AudioRequestA ****************************************
1164 * NAME
1165 * AHI_AudioRequestA -- get an audio mode from user using an requester.
1166 * AHI_AudioRequest -- varargs stub for AHI_AudioRequestA()
1168 * SYNOPSIS
1169 * success = AHI_AudioRequestA( requester, tags );
1170 * D0 A0 A1
1172 * BOOL AHI_AudioRequestA( struct AHIAudioModeRequester *,
1173 * struct TagItem * );
1175 * result = AHI_AudioRequest( requester, tag1, ... );
1177 * BOOL AHI_AudioRequest( struct AHIAudioModeRequester *, Tag, ... );
1179 * FUNCTION
1180 * Prompts the user for an audio mode, based on the modifying tags.
1181 * If the user cancels or the system aborts the request, FALSE is
1182 * returned, otherwise the requester's data structure reflects the
1183 * user input.
1185 * Note that tag values stay in effect for each use of the requester
1186 * until they are cleared or modified by passing the same tag with a
1187 * new value.
1189 * INPUTS
1190 * requester - Requester structure allocated with
1191 * AHI_AllocAudioRequestA(). If this parameter is NULL, this
1192 * function will always return FALSE with a dos.library/IoErr()
1193 * result of ERROR_NO_FREE_STORE.
1194 * tags - Pointer to an optional tag list which may be used to control
1195 * features of the requester.
1197 * TAGS
1198 * Tags used for the requester (they look remarkable similar to the
1199 * screen mode requester in ASL, don't they? ;-) )
1201 * AHIR_Window (struct Window *) - Parent window of requester. If no
1202 * AHIR_Screen tag is specified, the window structure is used to
1203 * determine on which screen to open the requesting window.
1205 * AHIR_PubScreenName (STRPTR) - Name of a public screen to open on.
1206 * This overrides the screen used by AHIR_Window.
1208 * AHIR_Screen (struct Screen *) - Screen on which to open the
1209 * requester. This overrides the screen used by AHIR_Window or by
1210 * AHIR_PubScreenName.
1212 * AHIR_PrivateIDCMP (BOOL) - When set to TRUE, this tells AHI to
1213 * allocate a new IDCMP port for the requesting window. If not
1214 * specified or set to FALSE, and if AHIR_Window is provided, the
1215 * requesting window will share AHIR_Window's IDCMP port.
1217 * AHIR_IntuiMsgFunc (struct Hook *) - A function to call whenever an
1218 * unknown Intuition message arrives at the message port being used
1219 * by the requesting window. The function receives the following
1220 * parameters:
1221 * A0 - (struct Hook *)
1222 * A1 - (struct IntuiMessage *)
1223 * A2 - (struct AHIAudioModeRequester *)
1225 * AHIR_SleepWindow (BOOL) - When set to TRUE, this tag will cause the
1226 * window specified by AHIR_Window to be "put to sleep". That is, a
1227 * busy pointer will be displayed in the parent window, and no
1228 * gadget or menu activity will be allowed. This is done by opening
1229 * an invisible Intuition Requester in the parent window.
1231 * AHIR_UserData (APTR) - A 32-bit value that is simply copied in the
1232 * ahiam_UserData field of the requester structure.
1234 * AHIR_TextAttr (struct TextAttr *) - Font to be used for the
1235 * requesting window's gadgets and menus. If this tag is not
1236 * provided or its value is NULL, the default font of the screen
1237 * on which the requesting window opens will be used. This font
1238 * must already be in memory as AHI calls OpenFont() and not
1239 * OpenDiskFont().
1241 * AHIR_Locale (struct Locale *) - Locale to use for the requesting
1242 * window. This determines the language used for the requester's
1243 * gadgets and menus. If this tag is not provided or its value is
1244 * NULL, the system's current default locale will be used.
1246 * AHIR_TitleText (STRPTR) - Title to use for the requesting window.
1247 * Default is no title.
1249 * AHIR_PositiveText (STRPTR) - Label of the positive gadget in the
1250 * requester. English default is "OK".
1252 * AHIR_NegativeText (STRPTR) - Label of the negative gadget in the
1253 * requester. English default is "Cancel".
1255 * AHIR_InitialLeftEdge (WORD) - Suggested left edge of requesting
1256 * window.
1258 * AHIR_InitialTopEdge (WORD) - Suggested top edge of requesting
1259 * window.
1261 * AHIR_InitialWidth (WORD) - Suggested width of requesting window.
1263 * AHIR_InitialHeight (WORD) - Suggested height of requesting window.
1265 * AHIR_InitialAudioID (ULONG) - Initial setting of the Mode list view
1266 * gadget (ahiam_AudioID). Default is ~0 (AHI_INVALID_ID), which
1267 * means that no mode will be selected.
1269 * AHIR_InitialMixFreq (ULONG) - Initial setting of the frequency
1270 * slider. Default is the lowest frequency supported.
1272 * AHIR_InitialInfoOpened (BOOL) - Whether to open the property
1273 * information window automatically. Default is FALSE.
1275 * AHIR_InitialInfoLeftEdge (WORD) - Initial left edge of information
1276 * window.
1278 * AHIR_InitialInfoTopEdge (WORD) - Initial top edge of information
1279 * window.
1281 * AHIR_DoMixFreq (BOOL) - Set this tag to TRUE to cause the requester
1282 * to display the frequency slider gadget. Default is FALSE.
1284 * AHIR_DoDefaultMode (BOOL) - Set this tag to TRUE to let the user
1285 * select the mode she has set in the preferences program. If she
1286 * selects this mode, ahiam_AudioID will be AHI_DEFAULT_ID and
1287 * ahiam_MixFreq will be AHI_DEFAULT_FREQ. Note that if you filter
1288 * the mode list (see below), you must also check the mode (with
1289 * AHI_BestAudioIDA()) before you use it since the user may change
1290 * the meaning of AHI_DEFAULT_MODE anytime, without your knowledge.
1291 * Default is FALSE. (V4)
1293 * AHIR_FilterFunc (struct Hook *) - A function to call for each mode
1294 * encountered. If the function returns TRUE, the mode is included
1295 * in the file list, otherwise it is rejected and not displayed. The
1296 * function receives the following parameters:
1297 * A0 - (struct Hook *)
1298 * A1 - (ULONG) mode id
1299 * A2 - (struct AHIAudioModeRequester *)
1301 * AHIR_FilterTags (struct TagItem *) - A pointer to a tag list used to
1302 * filter modes away, like AHIR_FilterFunc does. The tags are the
1303 * same as AHI_BestAudioIDA() takes as arguments. See that function
1304 * for an explanation of each tag.
1306 * RESULT
1307 * result - FALSE if the user cancelled the requester or if something
1308 * prevented the requester from opening. If TRUE, values in the
1309 * requester structure will be set.
1311 * If the return value is FALSE, you can look at the result from the
1312 * dos.library/IoErr() function to determine whether the requester
1313 * was cancelled or simply failed to open. If dos.library/IoErr()
1314 * returns 0, then the requester was cancelled, any other value
1315 * indicates a failure to open. Current possible failure codes are
1316 * ERROR_NO_FREE_STORE which indicates there was not enough memory,
1317 * and ERROR_NO_MORE_ENTRIES which indicates no modes were available
1318 * (usually because the application filter hook filtered them all
1319 * away).
1321 * EXAMPLE
1323 * NOTES
1324 * The requester data structure is READ-ONLY and can only be modified
1325 * by using tags!
1327 * The mixing/recording frequencies that are presented to the user
1328 * may not be the only ones a driver supports, but just a selection.
1330 * BUGS
1332 * SEE ALSO
1333 * AHI_AllocAudioRequestA(), AHI_FreeAudioRequest()
1335 ****************************************************************************
1339 ULONG
1340 _AHI_AudioRequestA( struct AHIAudioModeRequester* req_in,
1341 struct TagItem* tags,
1342 struct AHIBase* AHIBase )
1344 struct AHIAudioModeRequesterExt *req=(struct AHIAudioModeRequesterExt *)req_in;
1345 struct MinList list;
1346 struct IDnode *node = NULL, *node2 = NULL;
1347 struct Screen *pub_screen = NULL;
1348 struct Screen *screen = NULL;
1349 ULONG id=AHI_INVALID_ID;
1350 BOOL rc=TRUE;
1351 struct Requester lockreq;
1352 BOOL locksuxs = FALSE;
1353 WORD zipcoords[4];
1355 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1357 Debug_AudioRequestA(req_in,tags);
1360 SetIoErr( 0 );
1362 if(!req)
1364 SetIoErr( ERROR_REQUIRED_ARG_MISSING );
1365 return FALSE;
1368 // Update requester structure
1369 FillReqStruct(req,tags);
1370 req->tempAudioID=req->Req.ahiam_AudioID;
1371 req->tempFrequency=req->Req.ahiam_MixFreq;
1373 // Open the catalog
1375 req->Catalog = ExtOpenCatalog(req->Locale, NULL);
1377 if(req->PositiveText == NULL)
1378 req->PositiveText = GetString(msgReqOK, req->Catalog);
1379 if(req->NegativeText == NULL)
1380 req->NegativeText = GetString(msgReqCancel, req->Catalog);
1383 // Scan audio database for modes and create list
1384 req->list=&list;
1385 NewList((struct List *)req->list);
1386 while(AHI_INVALID_ID != (id=AHI_NextAudioID(id)))
1388 // Check FilterTags
1389 if(req->FilterTags)
1390 if(!TestAudioID(id,req->FilterTags))
1391 continue;
1392 if(req->FilterFunc)
1393 if(!CallHookPkt(req->FilterFunc,req,(APTR)id))
1394 continue;
1395 // Add mode to list
1396 if((node=AllocVec(sizeof(struct IDnode),MEMF_ANY)))
1398 node->node.ln_Type=NT_USER;
1399 node->node.ln_Pri=0;
1400 node->node.ln_Name=node->name;
1401 node->ID=id;
1402 #ifndef __AMIGAOS4__
1403 Sprintf(node->node.ln_Name, GetString(msgUnknown, req->Catalog),id);
1404 #endif
1405 AHI_GetAudioAttrs(id, NULL,
1406 AHIDB_BufferLen,80,
1407 AHIDB_Name, node->node.ln_Name,
1408 TAG_DONE);
1409 // Insert node alphabetically
1410 for(node2=(struct IDnode *)req->list->mlh_Head;node2->node.ln_Succ;node2=(struct IDnode *) node2->node.ln_Succ)
1411 if(Stricmp(node->node.ln_Name,node2->node.ln_Name) < 0)
1412 break;
1413 Insert((struct List *) req->list,(struct Node *)node,node2->node.ln_Pred);
1417 // Add the users preferred mode
1419 if((req->Flags & defaultmode) && (AHIBase->ahib_AudioMode != AHI_INVALID_ID)) do
1421 if(req->FilterTags)
1422 if(!TestAudioID(AHIBase->ahib_AudioMode,req->FilterTags))
1423 continue;
1424 if(req->FilterFunc)
1425 if(!CallHookPkt(req->FilterFunc,req,(APTR)AHIBase->ahib_AudioMode))
1426 continue;
1428 if((node=AllocVec(sizeof(struct IDnode),MEMF_ANY)))
1430 node->node.ln_Type=NT_USER;
1431 node->node.ln_Pri=0;
1432 node->node.ln_Name=node->name;
1433 node->ID = AHI_DEFAULT_ID;
1434 Sprintf(node->node.ln_Name, GetString(msgDefaultMode, req->Catalog));
1435 AddTail((struct List *) req->list, (struct Node *)node);
1437 } while(FALSE);
1439 if(NULL == ((struct IDnode *)req->list->mlh_Head)->node.ln_Succ)
1441 // List is empty, no audio modes!
1442 // Return immediately (no nodes to free)
1443 SetIoErr(ERROR_NO_MORE_ENTRIES);
1444 ExtCloseCatalog(req->Catalog);
1445 req->Catalog = FALSE;
1446 return FALSE;
1449 // Find our screen
1450 if(req->Screen)
1452 pub_screen = NULL;
1453 screen = req->Screen;
1455 else if(req->PubScreenName != (STRPTR) -1)
1457 pub_screen = LockPubScreen( req->PubScreenName );
1458 screen = pub_screen;
1460 else if(req->SrcWindow)
1462 pub_screen = NULL;
1463 screen = req->SrcWindow->WScreen;
1466 if( screen == NULL )
1468 pub_screen = LockPubScreen( NULL );
1469 screen = pub_screen;
1472 CalculateWindowSizePos( req, screen );
1474 // Clear ownIDCMP flag
1475 req->Flags &= ~ownIDCMP;
1477 if( req->SrcWindow != NULL )
1479 if(req->Flags & haveIDCMP)
1480 req->Flags |= ownIDCMP;
1483 zipcoords[0]=req->Req.ahiam_LeftEdge;
1484 zipcoords[1]=req->Req.ahiam_TopEdge;
1485 zipcoords[2]=1;
1486 zipcoords[3]=1;
1488 req->Window=OpenWindowTags(
1489 NULL,
1490 WA_Left,req->Req.ahiam_LeftEdge,
1491 WA_Top,req->Req.ahiam_TopEdge,
1492 WA_Width,req->Req.ahiam_Width,
1493 WA_Height,req->Req.ahiam_Height,
1494 WA_Zoom, zipcoords,
1495 WA_MaxWidth,~0,
1496 WA_MaxHeight,~0,
1497 WA_Title, req->TitleText,
1498 ( pub_screen != NULL ? WA_PubScreen : WA_CustomScreen ), screen,
1499 WA_PubScreenFallBack,TRUE,
1500 WA_SizeGadget,TRUE,
1501 WA_SizeBBottom,TRUE,
1502 WA_DragBar,TRUE,
1503 WA_DepthGadget,TRUE,
1504 WA_CloseGadget,TRUE,
1505 WA_Activate,TRUE,
1506 WA_SimpleRefresh,TRUE,
1507 WA_AutoAdjust,TRUE,
1508 WA_IDCMP,(req->Flags & ownIDCMP ? 0 : MY_IDCMPS),
1509 WA_NewLookMenus, TRUE,
1510 TAG_DONE);
1512 if( pub_screen != NULL )
1514 UnlockPubScreen( NULL, pub_screen);
1517 if(req->Window)
1519 // Topaz80: "Frequency"+INTERWIDTH+MINSLIDERWIDTH+INTERWIDTH+"99999 Hz" gives...
1520 WORD min_width = (req->Window->BorderLeft+4)+
1521 strlen( GetString(msgReqFrequency, req->Catalog))*8+
1522 INTERWIDTH+MINSLIDERWIDTH+INTERWIDTH+
1523 FREQLEN2*8+
1524 (req->Window->BorderRight+4);
1526 // Topaz80: 5 lines, freq & buttons gives...
1527 WORD min_height = (req->Window->BorderTop+2)+
1528 (5*8+6)+2+(8+6)+2+(8+6)+
1529 (req->Window->BorderBottom+2);
1531 if( req->Window->Width < min_width ||
1532 req->Window->Height < min_height )
1534 ChangeWindowBox( req->Window,
1535 req->Window->LeftEdge,
1536 req->Window->TopEdge,
1537 max( req->Window->Width, min_width ),
1538 max( req->Window->Height, min_height ) );
1539 Delay( 5 );
1542 WindowLimits( req->Window, min_width, min_height, 0, 0 );
1544 if((req->vi=GetVisualInfoA(req->Window->WScreen, NULL)))
1546 if(!(LayOutReq(req,req->TextAttr)))
1547 if(!(LayOutReq(req,&Topaz80)))
1548 rc=FALSE;
1550 if(rc) // Layout OK?
1552 struct NewMenu reqnewmenu[] =
1554 { NM_TITLE, NULL , 0 ,0,0,(APTR) 0, },
1555 { NM_ITEM, NULL , 0 ,0,0,(APTR) LASTMODEITEM, },
1556 { NM_ITEM, NULL , 0 ,0,0,(APTR) NEXTMODEITEM, },
1557 { NM_ITEM, NM_BARLABEL , 0 ,0,0,(APTR) 0, },
1558 { NM_ITEM, NULL , 0 ,0,0,(APTR) PROPERTYITEM, },
1559 { NM_ITEM, NULL , 0 ,0,0,(APTR) RESTOREITEM , },
1560 { NM_ITEM, NM_BARLABEL , 0 ,0,0,(APTR) 0, },
1561 { NM_ITEM, NULL , 0 ,0,0,(APTR) OKITEM, },
1562 { NM_ITEM, NULL , 0 ,0,0,(APTR) CANCELITEM, },
1563 { NM_END, NULL , 0 ,0,0,(APTR) 0, },
1565 static const APTR strings[] =
1567 msgMenuControl,
1568 msgMenuLastMode,
1569 msgMenuNextMode,
1570 msgMenuPropertyList,
1571 msgMenuRestore,
1572 msgMenuOK,
1573 msgMenuCancel,
1576 struct NewMenu *menuptr;
1577 APTR *stringptr;
1579 menuptr = (struct NewMenu *) &reqnewmenu;
1580 stringptr = (APTR *) &strings;
1582 while(menuptr->nm_Type != NM_END)
1584 if(menuptr->nm_Label == NULL)
1586 menuptr->nm_CommKey = GetString(*stringptr, req->Catalog);
1587 menuptr->nm_Label = menuptr->nm_CommKey + 2;
1588 stringptr++;
1590 menuptr++;
1593 if(req->Flags & ownIDCMP)
1595 req->Window->UserPort=req->SrcWindow->UserPort;
1596 ModifyIDCMP(req->Window,MY_IDCMPS);
1599 if((req->Flags & lockwin) && req->SrcWindow)
1601 InitRequester(&lockreq);
1602 locksuxs=Request(&lockreq,req->SrcWindow);
1603 if(IntuitionBase->LibNode.lib_Version >= 39)
1604 SetWindowPointer(req->SrcWindow,
1605 WA_BusyPointer,TRUE,
1606 TAG_DONE);
1609 // Add menus
1610 if((req->Menu=CreateMenus(reqnewmenu,
1611 GTMN_FullMenu, TRUE,
1612 GTMN_NewLookMenus, TRUE,
1613 TAG_DONE )))
1615 if(LayoutMenus(req->Menu,req->vi, TAG_DONE))
1617 if(SetMenuStrip(req->Window, req->Menu))
1619 if(req->Req.ahiam_InfoOpened)
1621 OpenInfoWindow(req);
1624 rc=HandleReq(req);
1626 CloseInfoWindow(req);
1627 ClearMenuStrip(req->Window);
1629 } // else LayoutMenus failed
1630 FreeMenus(req->Menu);
1631 req->Menu=NULL;
1632 } // else CreateMenus failed
1635 if((req->Flags & lockwin) && req->SrcWindow)
1637 if(locksuxs)
1638 EndRequest(&lockreq,req->SrcWindow);
1639 if(IntuitionBase->LibNode.lib_Version >= 39)
1640 SetWindowPointer(req->SrcWindow,
1641 WA_BusyPointer,FALSE,
1642 TAG_DONE);
1645 req->Req.ahiam_LeftEdge = req->Window->LeftEdge;
1646 req->Req.ahiam_TopEdge = req->Window->TopEdge;
1647 req->Req.ahiam_Width = req->Window->Width;
1648 req->Req.ahiam_Height = req->Window->Height;
1649 } // else LayOutReq failed
1651 else // no vi
1653 SetIoErr(ERROR_NO_FREE_STORE);
1654 rc=FALSE;
1657 if(req->Flags & ownIDCMP)
1658 CloseWindowSafely(req->Window);
1659 else
1660 CloseWindow(req->Window);
1661 req->Window=NULL;
1662 FreeVisualInfo(req->vi);
1663 req->vi=NULL;
1664 FreeGadgets(req->Gadgets);
1665 req->Gadgets=NULL;
1666 FreeVec(node);
1668 else // no window
1670 SetIoErr(ERROR_NO_FREE_STORE);
1671 rc=FALSE;
1674 ExtCloseCatalog(req->Catalog);
1675 req->Catalog = NULL;
1676 req->PositiveText = req->NegativeText = NULL;
1678 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1680 KPrintF("=>%s\n",rc ? "TRUE" : "FALSE" );
1682 return (ULONG) rc;
1686 /******************************************************************************
1687 ** AHI_FreeAudioRequest *******************************************************
1688 ******************************************************************************/
1690 /****** ahi.device/AHI_FreeAudioRequest *************************************
1692 * NAME
1693 * AHI_FreeAudioRequest -- frees requester resources
1695 * SYNOPSIS
1696 * AHI_FreeAudioRequest( requester );
1697 * A0
1699 * void AHI_FreeAudioRequest( struct AHIAudioModeRequester * );
1701 * FUNCTION
1702 * Frees any resources allocated by AHI_AllocAudioRequestA(). Once a
1703 * requester has been freed, it can no longer be used with other calls to
1704 * AHI_AudioRequestA().
1706 * INPUTS
1707 * requester - Requester obtained from AHI_AllocAudioRequestA(), or NULL
1708 * in which case this function does nothing.
1710 * RESULT
1712 * EXAMPLE
1714 * NOTES
1716 * BUGS
1718 * SEE ALSO
1719 * AHI_AllocAudioRequestA()
1721 ****************************************************************************
1725 void
1726 _AHI_FreeAudioRequest( struct AHIAudioModeRequester* req,
1727 struct AHIBase* AHIBase )
1730 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1732 Debug_FreeAudioRequest(req);
1735 if(req)
1736 FreeVec(req);