Two ease-of-use improvements:
[AROS.git] / workbench / devs / AHI / AHI / support.c
blobff2c08439df46fbb92cd2447ae0e7c577144c195
1 /*
2 AHI - The AHI preferences program
3 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program 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
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <config.h>
22 #include <devices/ahi.h>
23 #include <exec/memory.h>
24 #include <intuition/intuition.h>
25 #include <prefs/prefhdr.h>
26 #include <workbench/workbench.h>
28 #include <clib/alib_protos.h>
29 #include <proto/ahi.h>
30 #include <proto/dos.h>
31 #include <proto/exec.h>
32 #include <proto/gadtools.h>
33 #include <proto/icon.h>
34 #include <proto/iffparse.h>
35 #include <proto/utility.h>
37 #include <math.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <stddef.h>
43 #include "ahi.h"
44 #include "ahiprefs_Cat.h"
45 #include "support.h"
47 static BOOL AddUnit(struct List *, int);
48 static void FillUnitName(struct UnitNode *);
50 struct AHIGlobalPrefs globalprefs;
52 #ifdef __AMIGAOS4__
53 struct Library *GadToolsBase= NULL;
54 struct GadToolsIFace *IGadTools = NULL;
55 struct LocaleIFace *ILocale = NULL;
56 struct AHIIFace *IAHI = NULL;
57 #endif
59 struct Library *LocaleBase= NULL;
60 struct Library *AHIBase = NULL;
61 static struct MsgPort *AHImp = NULL;
62 static struct AHIRequest *AHIio = NULL;
63 static BYTE AHIDevice = -1;
66 static char deftoolname[] = {"AHI"};
68 static UWORD DiskI1Data[] =
70 /* Plane */
71 0x0000,0x0000,0x0004,0x0000,0x0000,0x0000,0x0001,0x0000,
72 0x0000,0x07ff,0x8000,0x4000,0x0000,0x1800,0x6000,0x1000,
73 0x0000,0x20fc,0x1000,0x0800,0x0000,0x4102,0x0800,0x0c00,
74 0x0000,0x4082,0x0800,0x0c00,0x0000,0x4082,0x0800,0x0c00,
75 0x0000,0x2104,0x0800,0x0c00,0x0000,0x1e18,0x1000,0x0c00,
76 0x0000,0x0060,0x2000,0x0c00,0x0000,0x0080,0xc000,0x0c00,
77 0x0000,0x0103,0x0000,0x0c00,0x0000,0x021c,0x0000,0x0c00,
78 0x0000,0x0108,0x0000,0x0c00,0x0000,0x00f0,0x0000,0x0c00,
79 0x0000,0x0108,0x0000,0x0c00,0x0000,0x0108,0x0000,0x0c00,
80 0x4000,0x00f0,0x0000,0x0c00,0x1000,0x0000,0x0000,0x0c00,
81 0x0400,0x0000,0x0000,0x0c00,0x01ff,0xffff,0xffff,0xfc00,
82 /* Plane */
83 0xffff,0xffff,0xfff8,0x0000,0xd555,0x5555,0x5556,0x0000,
84 0xd555,0x5000,0x5555,0x8000,0xd555,0x47ff,0x9555,0x6000,
85 0xd555,0x5f03,0xe555,0x5000,0xd555,0x3e55,0xf555,0x5000,
86 0xd555,0x3f55,0xf555,0x5000,0xd555,0x3f55,0xf555,0x5000,
87 0xd555,0x5e53,0xf555,0x5000,0xd555,0x4147,0xe555,0x5000,
88 0xd555,0x551f,0xd555,0x5000,0xd555,0x557f,0x1555,0x5000,
89 0xd555,0x54fc,0x5555,0x5000,0xd555,0x55e1,0x5555,0x5000,
90 0xd555,0x54f5,0x5555,0x5000,0xd555,0x5505,0x5555,0x5000,
91 0xd555,0x54f5,0x5555,0x5000,0xd555,0x54f5,0x5555,0x5000,
92 0x3555,0x5505,0x5555,0x5000,0x0d55,0x5555,0x5555,0x5000,
93 0x0355,0x5555,0x5555,0x5000,0x0000,0x0000,0x0000,0x0000
97 static struct Image image1 =
99 0,0,
100 54,22,2,
101 DiskI1Data,
102 0x0004,0x0000,
103 NULL
106 static STRPTR toolTypes[] = {
107 "ACTION=USE",
108 NULL
111 static struct DiskObject projIcon = {
112 WB_DISKMAGIC, /* Magic Number */
113 WB_DISKVERSION, /* Version */
114 { /* Embedded Gadget Structure */
115 NULL, /* Next Gadget Pointer */
116 97,12,52,23, /* Left,Top,Width,Height */
117 GFLG_GADGIMAGE|GFLG_GADGHBOX, /* Flags */
118 GACT_IMMEDIATE|GACT_RELVERIFY,/* Activation Flags */
119 GTYP_BOOLGADGET, /* Gadget Type */
120 (APTR)&image1, /* Render Image */
121 NULL, /* Select Image */
122 NULL, /* Gadget Text */
123 0, /* Mutual Exclude */
124 NULL, /* Special Info */
125 0, /* Gadget ID */
126 NULL /* User Data */
128 WBPROJECT, /* Icon Type */
129 deftoolname, /* Default Tool */
130 toolTypes, /* Tool Type Array */
131 NO_ICON_POSITION, /* Current X */
132 NO_ICON_POSITION, /* Current Y */
133 NULL, /* Drawer Structure */
134 NULL, /* Tool Window */
135 4096 /* Stack Size */
139 /******************************************************************************
140 **** Endian support code. *****************************************************
141 ******************************************************************************/
143 /* See the header file for macros */
145 #if !defined( WORDS_BIGENDIAN )
147 static UWORD
148 EndianSwapUWORD( UWORD x ) {
149 return ((((x) >> 8) & 0x00ffU) |
150 (((x) << 8) & 0xff00U) );
153 static ULONG
154 EndianSwapULONG( ULONG x ) {
155 return ((((x) >> 24) & 0x000000ffUL) |
156 (((x) >> 8) & 0x0000ff00UL) |
157 (((x) << 8) & 0x00ff0000UL) |
158 (((x) << 24) & 0xff000000UL) );
161 void
162 EndianSwap( size_t size, void* data) {
163 switch( size ) {
164 case 1:
165 break;
167 case 2:
168 *((UWORD*) data) = EndianSwapUWORD( *((UWORD*) data) );
169 break;
171 case 4:
172 *((ULONG*) data) = EndianSwapULONG( *((ULONG*) data) );
173 break;
175 case 8: {
176 ULONG tmp;
178 tmp = EndianSwapULONG( *((ULONG*) data) );
179 *((ULONG*) data) = EndianSwapULONG( *((ULONG*) (data + 4)) );
180 *((ULONG*) (data + 4)) = tmp;
181 break;
184 default:
185 Printf( "Unknown size: %ld\n", size );
186 abort();
190 #else
191 # define EndianSwap(s, x)
192 #endif
194 #define CopyIfValid( s, f, from, to, size ) \
195 do { \
196 if( (size_t) size > offsetof( s, f ) ) { \
197 (to).f = (from).f; \
198 EndianSwap( sizeof (to).f, &((to).f) ); \
200 } while( 0 )
203 /******************************************************************************
204 **** Call to open ahi.device etc. *********************************************
205 ******************************************************************************/
207 BOOL Initialize(void) {
208 LocaleBase = OpenLibrary("locale.library", 38);
210 #ifdef __AMIGAOS4__
211 ILocale = (struct LocaleIFace *) GetInterface(LocaleBase, "main", 1, NULL);
213 GadToolsBase = OpenLibrary("gadtools.library", 37);
215 if( GadToolsBase == NULL) {
216 Printf((char *) msgTextNoOpen, (ULONG) "gadtools.library", 37);
217 Printf("\n");
218 return FALSE;
221 IGadTools = (struct GadToolsIFace *) GetInterface(GadToolsBase, "main", 1, NULL);
222 #endif
224 OpenahiprefsCatalog();
226 AHImp=CreateMsgPort();
228 if( AHImp != NULL ) {
229 AHIio = (struct AHIRequest *)CreateIORequest(
230 AHImp,sizeof(struct AHIRequest));
232 if( AHIio != NULL ) {
233 AHIio->ahir_Version = 4;
234 AHIDevice = OpenDevice(AHINAME,AHI_NO_UNIT,(struct IORequest *)AHIio,0);
235 if(AHIDevice == 0) {
236 AHIBase = (struct Library *)AHIio->ahir_Std.io_Device;
237 #ifdef __AMIGAOS4__
238 IAHI = (struct AHIIFace *) GetInterface(AHIBase, "main", 1, NULL);
239 #endif
240 return TRUE;
245 Printf((char *) msgTextNoOpen, (ULONG) "ahi.device", 4);
246 Printf("\n");
247 return FALSE;
250 /******************************************************************************
251 **** Call to close ahi.device etc. ********************************************
252 ******************************************************************************/
254 void CleanUp(void) {
255 #ifdef __AMIGAOS4__
256 DropInterface((struct Interface*) IAHI);
257 DropInterface((struct Interface*) IGadTools);
258 CloseLibrary(GadToolsBase);
259 #endif
261 if(!AHIDevice)
262 CloseDevice((struct IORequest *)AHIio);
263 DeleteIORequest((struct IORequest *)AHIio);
264 DeleteMsgPort(AHImp);
266 AHIBase = NULL; AHImp = NULL; AHIio = NULL; AHIDevice = -1;
268 CloseahiprefsCatalog();
270 CloseLibrary(LocaleBase);
271 LocaleBase = NULL;
275 /***** Local function to create a Unit structure ****************************/
277 static BOOL AddUnit(struct List *list, int unit) {
278 struct UnitNode *u;
280 u = AllocVec(sizeof(struct UnitNode), MEMF_CLEAR);
282 if(u == NULL) {
283 return FALSE;
286 u->prefs.ahiup_Unit = unit;
287 u->prefs.ahiup_Channels = 1;
288 u->prefs.ahiup_AudioMode = AHI_BestAudioID(AHIDB_Realtime, TRUE, TAG_DONE);
289 u->prefs.ahiup_Frequency = 44100;
290 u->prefs.ahiup_MonitorVolume = 0x00000;
291 u->prefs.ahiup_InputGain = 0x10000;
292 u->prefs.ahiup_OutputVolume = 0x10000;
293 u->prefs.ahiup_Input = 0;
294 u->prefs.ahiup_Output = 0;
296 FillUnitName(u);
298 u->node.ln_Pri = -unit;
299 Enqueue(list, (struct Node *) u);
301 return TRUE;
304 /***** Local function to create a Unit name **********************************/
306 static void FillUnitName(struct UnitNode *u) {
307 if(u->prefs.ahiup_Unit != AHI_NO_UNIT) {
308 sprintf((char *) &u->name, msgUnitDevice, u->prefs.ahiup_Unit);
310 else {
311 sprintf((char *) &u->name, msgUnitMusic);
313 u->node.ln_Name = (char *) &u->name;
316 /******************************************************************************
317 **** Returns a list with all avalable units, fills globalprefs ****************
318 ******************************************************************************/
320 #define UNITNODES 4
322 // Call with name == NULL to get defaults
324 struct List *GetUnits(char *name) {
325 struct List *list;
326 struct IFFHandle *iff;
327 BOOL devnodes[UNITNODES] = { FALSE, FALSE, FALSE, FALSE } ;
328 BOOL lownode = FALSE;
329 int i;
331 // Reasonable defaults
332 globalprefs.ahigp_DebugLevel = AHI_DEBUG_NONE;
333 globalprefs.ahigp_DisableSurround = FALSE;
334 globalprefs.ahigp_DisableEcho = FALSE;
335 globalprefs.ahigp_FastEcho = FALSE;
336 globalprefs.ahigp_MaxCPU = (90 << 16) / 100;
337 globalprefs.ahigp_ClipMasterVolume = FALSE;
338 globalprefs.ahigp_Pad = 0;
339 globalprefs.ahigp_AntiClickTime = 0;
340 globalprefs.ahigp_ScaleMode = AHI_SCALE_FIXED_0_DB;
342 list = AllocVec(sizeof(struct List), MEMF_CLEAR);
344 if(list) {
345 NewList(list);
347 if(name && (iff = AllocIFF())) {
348 iff->iff_Stream = (ULONG) Open(name, MODE_OLDFILE);
349 if(iff->iff_Stream) {
350 InitIFFasDOS(iff);
351 if(!OpenIFF(iff, IFFF_READ)) {
352 if(!(PropChunk (iff, ID_PREF, ID_AHIG) ||
353 CollectionChunk(iff, ID_PREF, ID_AHIU) ||
354 StopOnExit (iff, ID_PREF, ID_FORM))) {
355 if(ParseIFF(iff, IFFPARSE_SCAN) == IFFERR_EOC) {
356 struct StoredProperty *global = FindProp(iff, ID_PREF, ID_AHIG);
357 struct CollectionItem *ci = FindCollection(iff, ID_PREF, ID_AHIU);
358 int ci_cnt = 0;
360 if(global != NULL) {
361 struct AHIGlobalPrefs *p = global->sp_Data;
363 CopyIfValid( struct AHIGlobalPrefs, ahigp_DebugLevel,
364 *p, globalprefs, global->sp_Size );
365 CopyIfValid( struct AHIGlobalPrefs, ahigp_DisableSurround,
366 *p, globalprefs, global->sp_Size );
367 CopyIfValid( struct AHIGlobalPrefs, ahigp_DisableEcho,
368 *p, globalprefs, global->sp_Size );
369 CopyIfValid( struct AHIGlobalPrefs, ahigp_FastEcho,
370 *p, globalprefs, global->sp_Size );
371 CopyIfValid( struct AHIGlobalPrefs, ahigp_MaxCPU,
372 *p, globalprefs, global->sp_Size );
373 CopyIfValid( struct AHIGlobalPrefs, ahigp_ClipMasterVolume,
374 *p, globalprefs, global->sp_Size );
375 CopyIfValid( struct AHIGlobalPrefs, ahigp_Pad,
376 *p, globalprefs, global->sp_Size );
377 CopyIfValid( struct AHIGlobalPrefs, ahigp_AntiClickTime,
378 *p, globalprefs, global->sp_Size );
379 CopyIfValid( struct AHIGlobalPrefs, ahigp_ScaleMode,
380 *p, globalprefs, global->sp_Size );
383 /* Set upsupported options to their defaults */
385 if( AHIBase->lib_Version <= 4 )
387 globalprefs.ahigp_AntiClickTime = 0;
388 globalprefs.ahigp_ScaleMode = AHI_SCALE_FIXED_SAFE;
391 if( AHIBase->lib_Version >= 5 )
393 globalprefs.ahigp_DisableSurround = FALSE;
394 globalprefs.ahigp_DisableEcho = FALSE;
395 globalprefs.ahigp_FastEcho = FALSE;
396 globalprefs.ahigp_ClipMasterVolume = TRUE;
400 while(ci) {
401 struct AHIUnitPrefs *p = ci->ci_Data;
402 struct UnitNode *u;
404 u = AllocVec(sizeof(struct UnitNode), MEMF_CLEAR);
405 if(u == NULL)
406 break;
408 u->prefs.ahiup_Unit = ci_cnt;
409 u->prefs.ahiup_Channels = 1;
410 u->prefs.ahiup_AudioMode = AHI_DEFAULT_ID;
411 u->prefs.ahiup_Frequency = AHI_DEFAULT_FREQ;
412 u->prefs.ahiup_MonitorVolume = 0;
413 u->prefs.ahiup_InputGain = 0;
414 u->prefs.ahiup_OutputVolume = 0x10000;
415 u->prefs.ahiup_Input = 0;
416 u->prefs.ahiup_Output = 0;
418 ++ci_cnt;
420 CopyIfValid( struct AHIUnitPrefs, ahiup_Unit,
421 *p, u->prefs, ci->ci_Size );
422 CopyIfValid( struct AHIUnitPrefs, ahiup_Channels,
423 *p, u->prefs, ci->ci_Size );
424 CopyIfValid( struct AHIUnitPrefs, ahiup_AudioMode,
425 *p, u->prefs, ci->ci_Size );
426 CopyIfValid( struct AHIUnitPrefs, ahiup_Frequency,
427 *p, u->prefs, ci->ci_Size );
428 CopyIfValid( struct AHIUnitPrefs, ahiup_MonitorVolume,
429 *p, u->prefs, ci->ci_Size );
430 CopyIfValid( struct AHIUnitPrefs, ahiup_InputGain,
431 *p, u->prefs, ci->ci_Size );
432 CopyIfValid( struct AHIUnitPrefs, ahiup_OutputVolume,
433 *p, u->prefs, ci->ci_Size );
434 CopyIfValid( struct AHIUnitPrefs, ahiup_Input,
435 *p, u->prefs, ci->ci_Size );
436 CopyIfValid( struct AHIUnitPrefs, ahiup_Output,
437 *p, u->prefs, ci->ci_Size );
439 FillUnitName(u);
441 u->node.ln_Pri = -(u->prefs.ahiup_Unit);
442 Enqueue(list, (struct Node *) u);
444 if(u->prefs.ahiup_Unit == AHI_NO_UNIT) {
445 lownode = TRUE;
447 else if(u->prefs.ahiup_Unit < UNITNODES) {
448 devnodes[u->prefs.ahiup_Unit] = TRUE;
451 ci=ci->ci_Next;
455 CloseIFF(iff);
457 Close((BPTR) iff->iff_Stream);
459 FreeIFF(iff);
463 // Fill up to lowlevel + UNITNODES device nodes, if not found in prefs file
465 if(!lownode) AddUnit(list, AHI_NO_UNIT);
466 for(i = 0; i < UNITNODES; i++) {
467 if(!devnodes[i]) AddUnit(list, i);
472 return list;
475 /******************************************************************************
476 **** Returns a list with all available modes **********************************
477 ******************************************************************************/
479 struct List *GetModes(struct AHIUnitPrefs *prefs) {
480 struct List *list;
482 list = AllocVec(sizeof(struct List), MEMF_CLEAR);
484 if(list) {
485 ULONG id = AHI_NextAudioID(AHI_INVALID_ID);
487 NewList(list);
489 while(id != AHI_INVALID_ID) {
490 struct ModeNode *t;
491 struct Node *node;
493 t = AllocVec( sizeof(struct ModeNode), MEMF_CLEAR);
495 if( t != NULL ) {
496 LONG realtime;
498 t->node.ln_Name = t->name;
499 t->ID = id;
501 realtime = FALSE;
503 AHI_GetAudioAttrs(id, NULL,
504 AHIDB_BufferLen, 80,
505 AHIDB_Name, (ULONG) t->node.ln_Name,
506 AHIDB_Realtime, (ULONG) &realtime,
507 TAG_DONE);
509 if((prefs->ahiup_Unit == AHI_NO_UNIT) ||
510 (realtime && (id & 0x00ff0000) != 0x00030000 /* Argh!! */)) {
511 // Insert node alphabetically
512 for(node = list->lh_Head;
513 node->ln_Succ;
514 node = node->ln_Succ) {
515 if(Stricmp(t->node.ln_Name,node->ln_Name) < 0)
516 break;
518 Insert(list, (struct Node *) t, node->ln_Pred);
520 else {
521 FreeVec(t);
524 id = AHI_NextAudioID(id);
527 return list;
530 /******************************************************************************
531 **** Creates a char* array from a list ****************************************
532 ******************************************************************************/
534 char **List2Array(struct List *list) {
535 char **strings, **rstrings;
536 int i;
537 struct Node *n;
539 for(n = list->lh_Head, i = 0; n->ln_Succ; n = n->ln_Succ) {
540 i++;
543 strings = AllocVec(sizeof(char *) * (i + 1), MEMF_CLEAR);
544 rstrings = strings;
546 if(strings) {
547 for(n = list->lh_Head; n->ln_Succ; n = n->ln_Succ) {
548 *strings++ = n->ln_Name;
550 *strings = NULL;
552 return rstrings;
555 /******************************************************************************
556 **** Returns a char* array with inputs names **********************************
557 ******************************************************************************/
559 char **GetInputs(ULONG id) {
560 char **strings, **rstrings;
561 LONG inputs = 0, i;
564 AHI_GetAudioAttrs(id, NULL,
565 AHIDB_Inputs, (ULONG) &inputs,
566 TAG_DONE);
568 strings = AllocVec(sizeof(char *) * (inputs + 1) + (32 * inputs), MEMF_CLEAR);
569 rstrings = strings;
571 if(strings) {
572 char *string = (char *) &strings[inputs + 1];
574 for(i = 0; i < inputs; i++) {
575 if(AHI_GetAudioAttrs(id, NULL,
576 AHIDB_BufferLen, 32,
577 AHIDB_InputArg, i,
578 AHIDB_Input, (ULONG) string,
579 TAG_DONE)) {
580 *strings++ = string;
581 while(*string++);
584 *strings = NULL;
586 return rstrings;
589 /******************************************************************************
590 **** Returns a char* array with outputs names *********************************
591 ******************************************************************************/
593 char **GetOutputs(ULONG id) {
594 char **strings, **rstrings;
595 LONG outputs = 0, i;
598 AHI_GetAudioAttrs(id, NULL,
599 AHIDB_Outputs, (ULONG) &outputs,
600 TAG_DONE);
602 strings = AllocVec(sizeof(char *) * (outputs + 1) + (32 * outputs), MEMF_CLEAR);
603 rstrings = strings;
605 if(strings) {
606 char *string = (char *) &strings[outputs + 1];
608 for(i = 0; i < outputs; i++) {
609 if(AHI_GetAudioAttrs(id, NULL,
610 AHIDB_BufferLen, 32,
611 AHIDB_OutputArg, i,
612 AHIDB_Output, (ULONG) string,
613 TAG_DONE)) {
614 *strings++ = string;
615 while(*string++);
618 *strings = NULL;
620 return rstrings;
623 /******************************************************************************
624 **** Saves all units and globalprefs ******************************************
625 ******************************************************************************/
627 BOOL SaveSettings(char *name, struct List *list) {
628 struct IFFHandle *iff;
629 struct PrefHeader header = { 0, 0, 0 };
630 struct Node *n;
631 BOOL success = FALSE;
633 if(name && (iff = AllocIFF())) {
634 iff->iff_Stream = (ULONG) Open(name, MODE_NEWFILE);
635 if(iff->iff_Stream) {
636 InitIFFasDOS(iff);
637 if(!OpenIFF(iff, IFFF_WRITE)) {
638 if(! PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN)) {
640 success = TRUE;
642 // Prefs header
643 if(! PushChunk(iff, ID_PREF, ID_PRHD, sizeof header)) {
644 EndianSwap( sizeof (UBYTE), &header.ph_Version );
645 EndianSwap( sizeof (UBYTE), &header.ph_Type );
646 EndianSwap( sizeof (ULONG), &header.ph_Flags );
647 WriteChunkBytes(iff, &header, sizeof header);
648 PopChunk(iff);
650 else success = FALSE;
652 // Global prefs
653 if(! PushChunk(iff, ID_PREF, ID_AHIG, sizeof globalprefs)) {
654 struct AHIGlobalPrefs p;
656 CopyIfValid( struct AHIGlobalPrefs, ahigp_DebugLevel,
657 globalprefs, p, sizeof p );
658 CopyIfValid( struct AHIGlobalPrefs, ahigp_DisableSurround,
659 globalprefs, p, sizeof p );
660 CopyIfValid( struct AHIGlobalPrefs, ahigp_DisableEcho,
661 globalprefs, p, sizeof p );
662 CopyIfValid( struct AHIGlobalPrefs, ahigp_FastEcho,
663 globalprefs, p, sizeof p );
664 CopyIfValid( struct AHIGlobalPrefs, ahigp_MaxCPU,
665 globalprefs, p, sizeof p );
666 CopyIfValid( struct AHIGlobalPrefs, ahigp_ClipMasterVolume,
667 globalprefs, p, sizeof p );
668 CopyIfValid( struct AHIGlobalPrefs, ahigp_Pad,
669 globalprefs, p, sizeof p );
670 CopyIfValid( struct AHIGlobalPrefs, ahigp_AntiClickTime,
671 globalprefs, p, sizeof p );
672 CopyIfValid( struct AHIGlobalPrefs, ahigp_ScaleMode,
673 globalprefs, p, sizeof p );
676 WriteChunkBytes(iff, &p, sizeof p);
677 PopChunk(iff);
679 else success = FALSE;
681 // Units
682 if(list != NULL) {
683 for(n = list->lh_Head; n->ln_Succ; n = n->ln_Succ) {
684 if(! PushChunk(iff, ID_PREF, ID_AHIU, sizeof(struct AHIUnitPrefs))) {
685 struct AHIUnitPrefs p;
687 CopyIfValid( struct AHIUnitPrefs, ahiup_Unit,
688 ((struct UnitNode *) n)->prefs, p, sizeof p );
689 CopyIfValid( struct AHIUnitPrefs, ahiup_Channels,
690 ((struct UnitNode *) n)->prefs, p, sizeof p );
691 CopyIfValid( struct AHIUnitPrefs, ahiup_AudioMode,
692 ((struct UnitNode *) n)->prefs, p, sizeof p );
693 CopyIfValid( struct AHIUnitPrefs, ahiup_Frequency,
694 ((struct UnitNode *) n)->prefs, p, sizeof p );
695 CopyIfValid( struct AHIUnitPrefs, ahiup_MonitorVolume,
696 ((struct UnitNode *) n)->prefs, p, sizeof p );
697 CopyIfValid( struct AHIUnitPrefs, ahiup_InputGain,
698 ((struct UnitNode *) n)->prefs, p, sizeof p );
699 CopyIfValid( struct AHIUnitPrefs, ahiup_OutputVolume,
700 ((struct UnitNode *) n)->prefs, p, sizeof p );
701 CopyIfValid( struct AHIUnitPrefs, ahiup_Input,
702 ((struct UnitNode *) n)->prefs, p, sizeof p );
703 CopyIfValid( struct AHIUnitPrefs, ahiup_Output,
704 ((struct UnitNode *) n)->prefs, p, sizeof p );
706 WriteChunkBytes(iff, &p, sizeof p);
707 PopChunk(iff);
709 else success = FALSE;
713 CloseIFF(iff);
715 Close((BPTR) iff->iff_Stream);
717 FreeIFF(iff);
719 return success;
723 /******************************************************************************
724 **** Write a project icon to disk *********************************************
725 ******************************************************************************/
727 BOOL WriteIcon(char *name) {
728 struct DiskObject *dobj;
729 char *olddeftool;
730 STRPTR* oldtooltypes;
731 BOOL success = FALSE;
733 /* Use the already present icon */
735 dobj=GetDiskObject(name);
737 if( dobj != NULL ) {
738 oldtooltypes = dobj->do_ToolTypes;
739 olddeftool = dobj->do_DefaultTool;
741 dobj->do_ToolTypes = toolTypes;
742 dobj->do_DefaultTool = deftoolname;
744 success = PutDiskObject(name,dobj);
746 /* we must restore the original pointers before freeing */
747 dobj->do_ToolTypes = oldtooltypes;
748 dobj->do_DefaultTool = olddeftool;
749 FreeDiskObject(dobj);
752 /* Try the user's default prefs icon */
753 if((! success) && (dobj=GetDiskObject("ENV:Sys/def_Pref"))) {
754 oldtooltypes = dobj->do_ToolTypes;
755 olddeftool = dobj->do_DefaultTool;
757 dobj->do_ToolTypes = toolTypes;
758 dobj->do_DefaultTool = deftoolname;
760 success = PutDiskObject(name,dobj);
762 /* we must restore the original pointers before freeing */
763 dobj->do_ToolTypes = oldtooltypes;
764 dobj->do_DefaultTool = olddeftool;
765 FreeDiskObject(dobj);
768 /* Else, put our default icon */
769 if(! success) {
770 success = PutDiskObject(name,&projIcon);
773 return success;
777 /******************************************************************************
778 **** Frees a list and all nodes ***********************************************
779 ******************************************************************************/
781 void FreeList(struct List *list) {
782 struct Node *n;
784 if(list == NULL)
785 return;
787 for( n = RemHead(list);
788 n != NULL;
789 n = RemHead(list) )
791 FreeVec(n);
794 FreeVec(list);
797 /******************************************************************************
798 **** Returns the index:th node in a list *************************************
799 ******************************************************************************/
801 struct Node *GetNode(int index, struct List *list) {
802 struct Node *n;
804 if(list == NULL || list->lh_Head->ln_Succ == NULL)
805 return NULL;
807 for(n = list->lh_Head; n->ln_Succ; n = n->ln_Succ) {
808 if(index == 0) {
809 break;
811 index--;
813 return n;
816 /******************************************************************************
817 **** Plays a test sound using the current selected mode and settings **********
818 ******************************************************************************/
820 BOOL PlaySound( struct AHIUnitPrefs* prefs )
822 struct AHIAudioCtrl* actrl;
823 BOOL rc = FALSE;
825 actrl = AHI_AllocAudio( AHIA_AudioID, prefs->ahiup_AudioMode,
826 AHIA_MixFreq, prefs->ahiup_Frequency,
827 AHIA_Channels, 1,
828 AHIA_Sounds, 1,
829 TAG_DONE );
831 if( actrl != NULL )
833 WORD* sample;
834 int length = 48000/440;
835 struct AHISampleInfo sound;
837 sample = AllocVec( length * sizeof( *sample ), MEMF_PUBLIC );
839 if( sample != NULL )
841 int i;
843 for( i = 0; i < length; ++i )
845 sample[ i ] = 0x7fff * sin( i * 2 * M_PI / length );
848 sound.ahisi_Type = AHIST_M16S;
849 sound.ahisi_Address = sample;
850 sound.ahisi_Length = length;
852 if( AHI_LoadSound( 0, AHIST_SAMPLE, &sound, actrl ) == AHIE_OK )
854 if( AHI_ControlAudio( actrl, AHIC_Play, FALSE,
855 AHIC_MonitorVolume, prefs->ahiup_MonitorVolume,
856 AHIC_InputGain, prefs->ahiup_InputGain,
857 AHIC_OutputVolume, prefs->ahiup_OutputVolume,
858 AHIC_Input, prefs->ahiup_Input,
859 AHIC_Output, prefs->ahiup_Output,
860 TAG_DONE ) == AHIE_OK )
862 ULONG volume = 0x10000;
864 switch( globalprefs.ahigp_ScaleMode )
866 case AHI_SCALE_DYNAMIC_SAFE:
867 volume = 0x10000;
868 break;
870 case AHI_SCALE_FIXED_SAFE:
871 if( prefs->ahiup_Channels != 0 )
873 volume = 0x10000 / prefs->ahiup_Channels;
875 break;
877 case AHI_SCALE_FIXED_0_DB:
878 volume = 0x10000;
879 break;
881 case AHI_SCALE_FIXED_3_DB:
882 volume = 0xB505;
883 break;
885 case AHI_SCALE_FIXED_6_DB:
886 volume = 0x8000;
887 break;
890 AHI_Play( actrl, AHIP_BeginChannel, 0,
891 AHIP_Freq, 48000,
892 AHIP_Vol, volume,
893 AHIP_Pan, 0x8000,
894 AHIP_Sound, 0,
895 AHIP_EndChannel, 0,
896 TAG_DONE );
898 if( AHI_ControlAudio( actrl, AHIC_Play, TRUE, TAG_DONE ) == AHIE_OK )
900 if( globalprefs.ahigp_ScaleMode == AHI_SCALE_DYNAMIC_SAFE )
902 Delay( 10 );
903 AHI_SetVol( 0, volume / 2, 0x8000, actrl, AHISF_IMM );
904 Delay( 30 );
905 AHI_SetVol( 0, volume, 0x8000, actrl, AHISF_IMM );
906 Delay( 10 );
908 else
910 Delay( 50 );
913 AHI_Play( actrl, AHIP_BeginChannel, 0,
914 AHIP_Sound, AHI_NOSOUND,
915 AHIP_EndChannel, 0,
916 TAG_DONE );
918 // Give the anti-click code a chance to do it's work ...
919 Delay( 1 );
921 AHI_ControlAudio( actrl, AHIC_Play, FALSE,
922 TAG_DONE );
926 AHI_UnloadSound( 0, actrl );
929 FreeVec( sample );
932 AHI_FreeAudio( actrl );
935 return rc;