missed commit
[AROS.git] / workbench / devs / AHI / Device / database.c
blob8ca4bd1225da8166039b57bbd2bc021a42317a9f
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 #include <exec/memory.h>
25 #include <exec/semaphores.h>
26 #include <dos/dostags.h>
27 #include <dos/dos.h>
28 #include <libraries/iffparse.h>
30 #include <clib/alib_protos.h>
31 #include <proto/exec.h>
32 #include <proto/dos.h>
33 #include <proto/iffparse.h>
34 #include <proto/utility.h>
35 #define __NOLIBBASE__
36 #define __NOGLOBALIFACE__
37 #include <proto/ahi.h>
38 #undef __NOLIBBASE__
39 #undef __NOGLOBALIFACE__
40 #include <proto/ahi_sub.h>
42 #include <string.h>
44 #include "ahi_def.h"
45 #include "database.h"
46 #include "debug.h"
47 #include "header.h"
48 #include "misc.h"
50 static ULONG AddModeFile ( UBYTE *filename );
52 #ifdef __MORPHOS__
53 #define IS_MORPHOS 1
54 #else
55 #define IS_MORPHOS 0
56 #endif
58 #if !defined( WORDS_BIGENDIAN )
59 struct TagItem32 {
60 ULONG ti_Tag;
61 ULONG ti_Data;
64 struct TagItem32 *AHINextTagItem(struct TagItem32 **tagListPtr)
66 ULONG tagTag, tagData;
68 if (!(*tagListPtr))
69 return NULL;
71 while(1)
73 tagTag = (*tagListPtr)->ti_Tag;
74 EndianSwap( sizeof tagTag, &tagTag );
76 switch(tagTag)
78 case TAG_MORE:
79 (*tagListPtr)->ti_Tag = tagTag;
80 tagData = (*tagListPtr)->ti_Data;
81 EndianSwap( sizeof tagData, &tagData );
82 (*tagListPtr)->ti_Data = tagData;
83 *(IPTR *)tagListPtr += tagData;
84 continue;
86 case TAG_IGNORE:
87 (*tagListPtr)->ti_Tag = tagTag;
88 break;
90 case TAG_END:
91 (*tagListPtr)->ti_Tag = tagTag;
92 (*tagListPtr) = 0;
93 return NULL;
95 case TAG_SKIP:
96 (*tagListPtr)->ti_Tag = tagTag;
97 tagData = (*tagListPtr)->ti_Data;
98 EndianSwap( sizeof tagData, &tagData );
99 (*tagListPtr)->ti_Data = tagData;
100 (*tagListPtr) += tagData + 1;
101 continue;
103 default:
104 (*tagListPtr)->ti_Tag = tagTag;
105 tagData = (*tagListPtr)->ti_Data;
106 EndianSwap( sizeof tagData, &tagData );
107 (*tagListPtr)->ti_Data = tagData;
108 return (*tagListPtr)++;
112 (*tagListPtr)++;
115 #else
116 #define TagItem32 TagItem
117 #define AHINextTagItem NextTagItem
118 #endif
120 /******************************************************************************
121 ** Audio Database *************************************************************
122 ******************************************************************************/
124 struct AHI_AudioMode
126 struct MinNode ahidbn_MinNode;
127 struct TagItem ahidbn_Tags[0];
129 /* Taglist, mode name and driver name follows.
130 Size variable. Use FreeVec() to free node. */
134 ** Lock the database for read access. Return NULL if database not present.
137 struct AHI_AudioDatabase *
138 LockDatabase(void)
140 struct AHI_AudioDatabase *audiodb;
142 Forbid();
144 audiodb = (struct AHI_AudioDatabase *) FindSemaphore(ADB_NAME);
146 if(audiodb != NULL)
148 ObtainSemaphoreShared((struct SignalSemaphore *) audiodb);
151 Permit();
153 return audiodb;
157 ** Lock the database for write access. Create it if not present.
160 struct AHI_AudioDatabase *
161 LockDatabaseWrite(void)
163 struct AHI_AudioDatabase *audiodb;
165 Forbid();
167 audiodb = (struct AHI_AudioDatabase *) FindSemaphore(ADB_NAME);
169 if(audiodb != NULL)
171 ObtainSemaphore((struct SignalSemaphore *) audiodb);
173 else
175 audiodb = (struct AHI_AudioDatabase *)
176 AllocVec(sizeof(struct AHI_AudioDatabase), MEMF_PUBLIC|MEMF_CLEAR);
178 if(audiodb != NULL)
181 NewList( (struct List *) &audiodb->ahidb_AudioModes);
183 audiodb->ahidb_Semaphore.ss_Link.ln_Name = audiodb->ahidb_Name;
184 audiodb->ahidb_Semaphore.ss_Link.ln_Pri = 20;
185 strcpy(audiodb->ahidb_Semaphore.ss_Link.ln_Name, ADB_NAME);
187 AddSemaphore((struct SignalSemaphore *) audiodb);
188 ObtainSemaphore((struct SignalSemaphore *) audiodb);
191 Permit();
193 return audiodb;
196 void
197 UnlockDatabase ( struct AHI_AudioDatabase *audiodb )
199 if(audiodb)
201 ReleaseSemaphore((struct SignalSemaphore *) audiodb);
205 struct TagItem *
206 GetDBTagList ( struct AHI_AudioDatabase *audiodb,
207 IPTR id )
209 struct AHI_AudioMode *node;
210 struct TagItem *rc = NULL;
212 if((audiodb != NULL) && (id != AHI_INVALID_ID))
214 for(node=(struct AHI_AudioMode *)audiodb->ahidb_AudioModes.mlh_Head;
215 node->ahidbn_MinNode.mln_Succ;
216 node=(struct AHI_AudioMode *)node->ahidbn_MinNode.mln_Succ)
218 if(id == GetTagData(AHIDB_AudioID,AHI_INVALID_ID,node->ahidbn_Tags))
220 rc = node->ahidbn_Tags;
221 break;
226 return rc;
230 /******************************************************************************
231 ** AHI_NextAudioID ************************************************************
232 ******************************************************************************/
234 /****** ahi.device/AHI_NextAudioID ******************************************
236 * NAME
237 * AHI_NextAudioID -- iterate current audio mode identifiers
239 * SYNOPSIS
240 * next_ID = AHI_NextAudioID( last_ID );
241 * D0 D0
243 * IPTR AHI_NextAudioID( IPTR );
245 * FUNCTION
246 * This function is used to iterate through all current AudioIDs in
247 * the audio database.
249 * INPUTS
250 * last_ID - previous AudioID or AHI_INVALID_ID if beginning iteration.
252 * RESULT
253 * next_ID - subsequent AudioID or AHI_INVALID_ID if no more IDs.
255 * EXAMPLE
257 * NOTES
259 * BUGS
261 * SEE ALSO
262 * AHI_GetAudioAttrsA(), AHI_BestAudioIDA()
264 ****************************************************************************
268 IPTR
269 _AHI_NextAudioID( IPTR id,
270 struct AHIBase* AHIBase )
272 struct AHI_AudioDatabase *audiodb;
273 struct AHI_AudioMode *node;
274 IPTR nextid=AHI_INVALID_ID;
276 ahibug("[AHI:Device] %s(%08x)\n", __func__, id);
278 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_HIGH)
280 Debug_NextAudioID(id);
283 audiodb = LockDatabase();
285 if(audiodb != NULL)
287 node = (struct AHI_AudioMode *) audiodb->ahidb_AudioModes.mlh_Head;
289 if(id != AHI_INVALID_ID)
291 while(node != NULL)
293 IPTR thisid;
295 ahibug("[AHI:Device] %s: node @ 0x%p)\n", __func__, node);
297 thisid = GetTagData(AHIDB_AudioID,AHI_INVALID_ID,node->ahidbn_Tags);
298 node = (struct AHI_AudioMode *) node->ahidbn_MinNode.mln_Succ;
300 if(thisid == id)
302 break;
307 while(node && node->ahidbn_MinNode.mln_Succ)
309 if( GetTagData( AHIDB_MultTable, FALSE, node->ahidbn_Tags ) )
311 // Pretend the "Fast" modes are not here
312 node = (struct AHI_AudioMode*) node->ahidbn_MinNode.mln_Succ;
314 else
316 nextid = GetTagData(AHIDB_AudioID, AHI_INVALID_ID, node->ahidbn_Tags);
317 break;
321 UnlockDatabase(audiodb);
324 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_HIGH)
326 KPrintF("=>0x%08lx\n",nextid);
329 return nextid;
333 /******************************************************************************
334 ** AHI_AddAudioMode ***********************************************************
335 ******************************************************************************/
337 /****i* ahi.device/AHI_AddAudioMode *****************************************
339 * NAME
340 * AHI_AddAudioMode -- add an audio mode to the database (V4)
342 * SYNOPSIS
343 * success = AHI_AddAudioMode( DBtags );
344 * D0 A0
346 * ULONG AHI_AddAudioMode( struct TagItem *, UBYTE *, UBYTE *);
348 * FUNCTION
349 * Adds the audio mode described by a taglist to the audio mode
350 * database. If the database does not exists, it will be created.
352 * INPUTS
353 * DBtags - Tags describing the properties of this mode.
355 * RESULT
356 * success - FALSE if the mode could not be added.
358 * EXAMPLE
360 * NOTES
362 * BUGS
364 * SEE ALSO
366 ****************************************************************************
370 ULONG
371 _AHI_AddAudioMode( struct TagItem* DBtags,
372 struct AHIBase* AHIBase )
374 struct AHI_AudioDatabase *audiodb;
375 struct AHI_AudioMode *node;
376 ULONG nodesize = sizeof(struct AHI_AudioMode), tagitems = 0;
377 ULONG datalength = 0, namelength = 0, driverlength = 0, dvrbasenamelength = 0;
378 struct TagItem *tstate = DBtags, *tp, *tag;
379 ULONG rc = FALSE;
381 ahibug("[AHI:Device] %s()\n", __func__);
383 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_HIGH)
385 Debug_AddAudioMode(DBtags);
388 // Remove old mode if present in database
389 AHI_RemoveAudioMode( GetTagData(AHIDB_AudioID, AHI_INVALID_ID, DBtags));
391 // Now add the new mode
393 audiodb = LockDatabaseWrite();
395 if(audiodb != NULL)
398 // Find total size
400 while( (tag = NextTagItem(&tstate)) != NULL )
403 if(tag->ti_Data) switch(tag->ti_Tag)
405 case AHIDB_Data:
406 datalength = ((ULONG *)tag->ti_Data)[0];
407 nodesize += datalength;
408 break;
410 case AHIDB_Name:
411 namelength = strlen((UBYTE *)tag->ti_Data)+1;
412 nodesize += namelength;
413 break;
415 case AHIDB_Driver:
416 driverlength = strlen((UBYTE *)tag->ti_Data)+1;
417 nodesize += driverlength;
418 break;
420 case AHIDB_DriverBaseName:
421 dvrbasenamelength = strlen((UBYTE *)tag->ti_Data)+1;
422 nodesize += dvrbasenamelength;
423 break;
426 nodesize += sizeof(struct TagItem);
427 tagitems++;
430 nodesize += sizeof(struct TagItem); // The last TAG_END
431 tagitems++;
433 node = AllocVec(nodesize, MEMF_PUBLIC|MEMF_CLEAR);
435 if(node != NULL)
437 tp = node->ahidbn_Tags;
438 tstate = DBtags;
439 while( (tag = NextTagItem(&tstate)) != NULL)
441 if(tag->ti_Data) switch(tag->ti_Tag)
443 case AHIDB_Data:
444 tp->ti_Data = ((IPTR) &node->ahidbn_Tags[tagitems]);
445 CopyMem((APTR)tag->ti_Data, (APTR)tp->ti_Data, datalength);
446 break;
448 case AHIDB_Name:
449 tp->ti_Data = ((IPTR) &node->ahidbn_Tags[tagitems]) + datalength;
450 strcpy((UBYTE *)tp->ti_Data, (UBYTE *)tag->ti_Data);
451 break;
453 case AHIDB_Driver:
454 tp->ti_Data= ((IPTR) &node->ahidbn_Tags[tagitems]) + datalength + namelength;
455 strcpy((UBYTE *)tp->ti_Data, (UBYTE *)tag->ti_Data);
456 break;
458 case AHIDB_DriverBaseName:
459 tp->ti_Data = ((IPTR) &node->ahidbn_Tags[tagitems]) + datalength + namelength + driverlength;
460 strcpy((UBYTE *)tp->ti_Data, (UBYTE *)tag->ti_Data);
461 break;
463 default:
464 tp->ti_Data = tag->ti_Data;
465 break;
467 tp->ti_Tag = tag->ti_Tag;
468 tp++;
470 tp->ti_Tag = TAG_DONE;
472 AddHead((struct List *) &audiodb->ahidb_AudioModes, (struct Node *) node);
473 rc = TRUE;
476 UnlockDatabase(audiodb);
479 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_HIGH)
481 KPrintF("=>%ld\n",rc);
484 return rc;
488 /******************************************************************************
489 ** AHI_RemoveAudioMode ********************************************************
490 ******************************************************************************/
492 /****i* ahi.device/AHI_RemoveAudioMode **************************************
494 * NAME
495 * AHI_RemoveAudioMode -- remove a audio mode to the database (V4)
497 * SYNOPSIS
498 * success = AHI_RemoveAudioMode( ID );
499 * D0 D0
501 * ULONG AHI_RemoveAudioMode( IPTR );
503 * FUNCTION
504 * Removes the audio mode from the audio mode database.
506 * INPUTS
507 * ID - The audio ID of the mode to be removed, or AHI_INVALID_ID.
509 * RESULT
510 * success - FALSE if the mode could not be removed.
512 * EXAMPLE
514 * NOTES
516 * BUGS
518 * SEE ALSO
520 ****************************************************************************
524 ULONG
525 _AHI_RemoveAudioMode( IPTR id,
526 struct AHIBase* AHIBase )
528 struct AHI_AudioMode *node;
529 struct AHI_AudioDatabase *audiodb;
530 ULONG rc=FALSE;
532 ahibug("[AHI:Device] %s(%08x)\n", __func__, id);
534 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_HIGH)
536 Debug_RemoveAudioMode(id);
540 /* Why ?? */
542 audiodb = LockDatabaseWrite();
544 if(audiodb != NULL)
546 UnlockDatabase(audiodb);
549 audiodb = LockDatabaseWrite();
551 if(audiodb != NULL)
553 if(id != AHI_INVALID_ID)
555 for(node=(struct AHI_AudioMode *)audiodb->ahidb_AudioModes.mlh_Head;
556 node->ahidbn_MinNode.mln_Succ;
557 node=(struct AHI_AudioMode *)node->ahidbn_MinNode.mln_Succ)
559 if(id == GetTagData(AHIDB_AudioID, AHI_INVALID_ID, node->ahidbn_Tags))
561 Remove((struct Node *) node);
562 FreeVec(node);
563 rc = TRUE;
564 break;
568 // Remove the entire database if it's empty
570 Forbid();
572 if(audiodb->ahidb_AudioModes.mlh_Head->mln_Succ == NULL)
574 UnlockDatabase(audiodb);
576 audiodb = (struct AHI_AudioDatabase *) FindSemaphore(ADB_NAME);
578 if(audiodb != NULL)
580 RemSemaphore((struct SignalSemaphore *) audiodb);
581 FreeVec(audiodb);
584 audiodb = NULL;
588 Permit();
591 UnlockDatabase(audiodb);
594 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_HIGH)
596 KPrintF("=>%ld\n",rc);
599 return rc;
603 /******************************************************************************
604 ** AHI_LoadModeFile ***********************************************************
605 ******************************************************************************/
607 /****i* ahi.device/AHI_LoadModeFile *****************************************
609 * NAME
610 * AHI_LoadModeFile -- Add all modes in a mode file to the database (V4)
612 * SYNOPSIS
613 * success = AHI_LoadModeFile( name );
614 * D0 A0
616 * ULONG AHI_LoadModeFile( STRPTR );
618 * FUNCTION
619 * This function takes the name of a file or a directory and either
620 * adds all modes in the file or the modes of all files in the
621 * directory to the audio mode database. Directories inside the
622 * given directory will not be recursed. The file format is IFF-AHIM.
624 * INPUTS
625 * name - A pointer to the name of a file or directory.
627 * RESULT
628 * success - FALSE on error. Check dos.library/IOErr() for more
629 * information.
631 * EXAMPLE
633 * NOTES
635 * BUGS
637 * SEE ALSO
639 ****************************************************************************
643 ULONG
644 _AHI_LoadModeFile( UBYTE* name,
645 struct AHIBase* AHIBase )
647 ULONG rc=FALSE;
648 struct FileInfoBlock *fib;
649 BPTR lock,thisdir;
651 ahibug("[AHI:Device] %s('%s')\n", __func__, name);
653 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_HIGH)
655 Debug_LoadModeFile(name);
658 SetIoErr(0);
660 fib = AllocDosObject(DOS_FIB, TAG_DONE);
662 if(fib != NULL)
664 lock = Lock(name, ACCESS_READ);
666 if(lock != 0)
668 if(Examine(lock,fib))
670 if(fib->fib_DirEntryType>0) // Directory?
672 thisdir = CurrentDir(lock);
674 while(ExNext(lock, fib))
676 if(fib->fib_DirEntryType>0)
678 continue; // AHI_LoadModeFile(fib->fib_FileName); for recursion
680 else
682 #if 0
683 rc = AddModeFile(fib->fib_FileName);
685 if(!rc)
687 break;
689 #else
690 // Try to load. Just continue if failing.
691 AddModeFile(fib->fib_FileName);
692 rc = TRUE;
693 #endif
696 if(IoErr() == ERROR_NO_MORE_ENTRIES)
698 SetIoErr(0);
701 CurrentDir(thisdir);
703 else // Plain file
705 rc = AddModeFile(name);
709 UnLock(lock);
712 FreeDosObject(DOS_FIB,fib);
715 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_HIGH)
717 KPrintF("=>%ld\n",rc);
720 return rc;
723 /* AddModeFile **********************************************************/
725 static ULONG
726 AddModeFile ( UBYTE *filename )
728 struct IFFHandle *iff;
729 struct StoredProperty *name,*data;
730 struct CollectionItem *ci;
731 struct TagItem32 *tag,*tstate;
732 #if defined(__AROS__) && (__WORDSIZE==64)
733 struct TagItem *dstTag;
734 #else
735 #define dstTag tag
736 #endif
737 struct TagItem extratags[]=
739 { AHIDB_Driver, 0 },
740 { AHIDB_Data, 0 },
741 { AHIDB_DriverBaseName, (IPTR)(IS_MORPHOS ? "MOSSYS:DEVS/AHI" : "DEVS:AHI") },
742 { TAG_MORE, 0 }
744 ULONG rc=FALSE;
746 ahibug("[AHI:Device] %s('%s')\n", __func__, filename);
748 iff = AllocIFF();
750 if(iff != NULL)
753 iff->iff_Stream = (IPTR)Open(filename, MODE_OLDFILE);
755 if(iff->iff_Stream != 0)
757 InitIFFasDOS(iff);
759 if(!OpenIFF(iff, IFFF_READ))
762 if(!(PropChunk(iff, ID_AHIM, ID_AUDN)
763 || PropChunk(iff, ID_AHIM, ID_AUDD)
764 || CollectionChunk(iff, ID_AHIM, ID_AUDM)
765 || StopOnExit(iff, ID_AHIM, ID_FORM)))
767 if(ParseIFF(iff, IFFPARSE_SCAN) == IFFERR_EOC)
769 name = FindProp(iff, ID_AHIM, ID_AUDN);
770 data = FindProp(iff, ID_AHIM, ID_AUDD);
771 ci = FindCollection(iff, ID_AHIM, ID_AUDM);
773 rc = TRUE;
775 ahibug("[AHI:Device] %s: ci @ 0x%p, name @ 0x%p, data @ 0x%p\n", __func__, ci, name, data);
777 if(name != NULL)
779 char driver_name[ 128 ];
780 struct Library* driver_base;
782 rc = FALSE;
784 if( name->sp_Size <= 0 )
786 Req( "%s:\nAUDN chunk has illegal size: %ld.",
787 (IPTR)filename, name->sp_Size );
789 else
791 STRPTR s;
793 // Make sure string is NUL-terminated
795 for( s = (STRPTR) name->sp_Data;
796 (APTR) s < name->sp_Data + name->sp_Size;
797 ++s )
799 if( *s == 0 )
801 rc = TRUE;
802 break;
806 if( !rc )
808 Req( "%s:\nAUDN chunk is not NUL-terminated.",
809 (IPTR)filename );
813 extratags[0].ti_Data = (IPTR) name->sp_Data;
815 // Now verify that the driver can really be opened
817 strcpy( driver_name, IS_MORPHOS ? "MOSSYS:DEVS/AHI/" : "DEVS:AHI/" );
818 strncat( driver_name, name->sp_Data, 100 );
819 strcat( driver_name, ".audio" );
821 driver_base = OpenLibrary( driver_name, DriverVersion );
822 if( driver_base == NULL )
824 if (IS_MORPHOS == 0)
826 rc = FALSE;
828 else
830 // Make it MOSSYS:DEVS:AHI/...
831 // ^
832 driver_name[7 + 4] = ':';
834 // Try "DEVS:AHI/...."
836 driver_base = OpenLibrary( driver_name + 7, DriverVersion );
837 if( driver_base == NULL )
839 rc = FALSE;
841 else
843 // It is a DEVS:AHI driver!
844 extratags[2].ti_Data = (IPTR) "DEVS:AHI";
846 CloseLibrary( driver_base );
850 else
852 CloseLibrary( driver_base );
856 if(data != NULL)
858 if( data->sp_Size <= 0 )
860 Req( "%s:\nAUDD chunk has illegal size: %ld.",
861 (IPTR)filename, data->sp_Size );
863 rc = FALSE;
866 extratags[1].ti_Data = (IPTR) data->sp_Data;
869 while(rc && ci != NULL)
871 APTR driverTags;
873 // Relocate loaded taglist
874 ahibug("[AHI:Device] %s: relocating taglist @ 0x%p, %d bytes\n", __func__, ci->ci_Data, ci->ci_Size);
876 tstate = (struct TagItem *) ci->ci_Data;
878 #if defined(__AROS__) && (__WORDSIZE==64)
879 driverTags = AllocVec(sizeof(struct TagItem) * 128, MEMF_CLEAR);
880 dstTag = driverTags;
881 #else
882 driverTags = ci->ci_Data;
883 #endif
884 while( rc && ( tag = AHINextTagItem( &tstate ) ) != NULL )
886 #if defined(__AROS__) && (__WORDSIZE==64)
887 dstTag->ti_Tag = (IPTR)tag->ti_Tag;
888 dstTag->ti_Data = (IPTR)tag->ti_Data;
889 #endif
890 ahibug("[AHI:Device] %s: %08x = %p\n", __func__, dstTag->ti_Tag, dstTag->ti_Data);
892 if(tag->ti_Tag & (AHI_TagBaseR ^ AHI_TagBase))
894 dstTag->ti_Data += (IPTR)ci->ci_Data;
897 rc = FALSE;
899 switch( tag->ti_Tag )
901 case AHIDB_Name:
903 // Make sure the string is within the chunk and NUL-term.
905 if( dstTag->ti_Data < (IPTR) ci->ci_Data ||
906 dstTag->ti_Data >= (IPTR) ci->ci_Data + ci->ci_Size )
908 Req( "%s:\nAUDM chunk contains an invalid string.",
909 (IPTR)filename );
911 else
913 STRPTR s;
915 // Make sure string is NUL-terminated
917 for( s = (STRPTR) dstTag->ti_Data;
918 (APTR) s < ci->ci_Data + ci->ci_Size;
919 ++s )
921 if( *s == 0 )
923 rc = TRUE;
924 break;
929 break;
932 default:
933 rc = TRUE;
934 break;
937 if( !rc )
939 Req( "%s:\nAUDM chunk contains a string that is not "
940 "NUL-terminated.", (IPTR)filename );
942 #if defined(__AROS__) && (__WORDSIZE==64)
943 dstTag++;
944 #endif
947 if( rc )
949 // Link taglists
951 extratags[3].ti_Data = (IPTR)driverTags;
953 rc = AHI_AddAudioMode(extratags);
955 ci = ci->ci_Next;
957 #if defined(__AROS__) && (__WORDSIZE==64)
958 FreeVec(driverTags);
959 #endif
963 CloseIFF(iff);
965 Close((BPTR) iff->iff_Stream);
967 FreeIFF(iff);
970 return rc;