2 toccata.library - AHI-based Toccata emulation library
3 Copyright (C) 1997-2005 Martin Blom <martin@blom.org> and Teemu Suikki.
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,
22 #include <devices/ahi.h>
24 #include <dos/dostags.h>
25 #include <exec/exec.h>
26 #include <libraries/iffparse.h>
27 #include <libraries/maud.h>
29 #include <proto/ahi.h>
30 #include <proto/dos.h>
31 #include <proto/exec.h>
32 #include <proto/iffparse.h>
33 #include <proto/utility.h>
34 #include <clib/toccata_protos.h>
35 #include <pragmas/toccata_pragmas.h>
48 #define DBG(text) {Forbid();FPuts(dfh,text);Flush(dfh);Permit();}
49 #define DVAL(text,val) {Forbid();VFPrintf(dfh,(STRPTR)text,&val);Flush(dfh);Permit();}
52 #define DVAL(text,val)
57 static ASM ULONG
SoundFunc(REG(a0
) struct Hook
*hook
,
58 REG(a2
) struct AHIAudioCtrl
*audioctrl
,
59 REG(a1
) struct AHISoundMessage
*msg
);
60 static ASM ULONG
RecordFunc(REG(a0
) struct Hook
*hook
,
61 REG(a2
) struct AHIAudioCtrl
*audioctrl
,
62 REG(a1
) struct AHIRecordMessage
*msg
);
64 ASM LONG
ReadMAUD(REG(a0
) UBYTE
*buffer
, REG(d0
) ULONG length
, REG(a1
) ULONG unused
);
66 static BOOL
AllocAudio(void);
67 static void FreeAudio(void);
68 static BOOL
TuneAudio(void);
69 static BOOL
ControlAudio(void);
71 static void Pause(ULONG pause
);
72 static void Stop(ULONG flags
);
73 static BOOL
RawPlayback(struct TagItem
*tags
);
74 static BOOL
Playback(struct TagItem
*tags
);
77 struct Process
*IOProcess
= NULL
;
78 BOOL IOInitialized
= FALSE
;
84 BOOL SlaveInitialized
= FALSE
;
85 BOOL AudioInitialized
= FALSE
;
87 BOOL Recording
= FALSE
;
88 BOOL Leveling
= FALSE
;
90 BOOL Sound0Loaded
= FALSE
;
91 BOOL Sound1Loaded
= FALSE
;
93 BOOL FirstBuf
= FALSE
;
95 /* RawPlayback variables */
97 struct Task
*ErrorTask
, *RawTask
, *SigTask
;
98 ULONG ErrorMask
, RawMask
, SigMask
;
99 struct Interrupt
*RawInt
;
100 BYTE
*RawBuffer1
, *RawBuffer2
;
101 ULONG RawBufferSize
, RawIrqSize
=512;
105 ULONG RawBufferLength
; /* RawBufferSize / samplesize */
107 LONG ByteSkipCounter
;
109 /* Playback variables */
111 struct Task
*EndTask
;
113 struct Window
*Window
;
116 ASM
LONG (*Load
)(REG(a0
) UBYTE
*, REG(d0
) ULONG
, REG(a1
) ULONG
);
125 struct IFFHandle
*iff
;
127 BYTE
*Buffer1
, *Buffer2
;
129 struct List BufferList
;
140 struct AHIAudioCtrl
*audioctrl
= NULL
;
142 Fixed MinMonVol
, MaxMonVol
, MinOutVol
, MaxOutVol
, MinGain
, MaxGain
;
144 struct Hook SoundHook
= {
145 NULL
, NULL
, (ULONG (*)()) HookLoad
, SoundFunc
, NULL
148 struct Hook RecordHook
= {
149 NULL
, NULL
, (ULONG (*)()) HookLoad
, RecordFunc
, NULL
152 /* dB<->Fixed conversion */
154 const Fixed negboundaries
[] = {
155 65536,55141,46395,39037,32845,27636,23253,19565,16461,13850,11654,9805,8250,
156 6941,5840,4914,4135,3479,2927,2463,2072,1743,1467,1234,1038,873,735,618,520,
157 438,368,310,260,219,184,155,130,110,92,77,65,55,46,39,32,27,23,19,16,13,11,9,
158 8,6,5,4,4,3,2,2,2,1,1,1,0
161 const Fixed posboundaries
[] = {
162 65536,77889,92572,110022,130761,155410,184705,219522,260903,
163 310084,368536,438005,520570,618699,735326,873936
169 * SoundFunc(): Called when a sample has just started
172 static ASM ULONG
SoundFunc(REG(a0
) struct Hook
*hook
,
173 REG(a2
) struct AHIAudioCtrl
*audioctrl
,
174 REG(a1
) struct AHISoundMessage
*msg
) {
184 if(!NextBufferOK
&& (ErrorTask
!= NULL
)) {
185 Signal(ErrorTask
, ErrorMask
);
186 if(IOProcess
!= NULL
) {
187 Signal((struct Task
*) IOProcess
, SIGBREAKF_CTRL_E
);
190 Signal((struct Task
*) SlaveProcess
, SIGBREAKF_CTRL_E
);
197 else if(RawTask
!= NULL
) {
199 Signal(RawTask
, RawMask
);
201 } else FirstBuf
=FALSE
;
203 AHI_SetSound(0, SoundFlag
, 0,RawBufferLength
, audioctrl
,0);
205 if(ByteCount
!= NULL
) {
206 *ByteCount
+= RawBufferSize
;
210 if(SigTask
!= NULL
) {
211 ByteSkipCounter
-= RawBufferSize
;
212 if(ByteSkipCounter
<= 0) {
213 ByteSkipCounter
+= ByteSkip
;
214 Signal(SigTask
, SigMask
);
223 * RecordFunc(): Called when a new block of recorded data is available
226 static ASM ULONG
RecordFunc(REG(a0
) struct Hook
*hook
,
227 REG(a2
) struct AHIAudioCtrl
*audioctrl
,
228 REG(a1
) struct AHIRecordMessage
*msg
) {
235 * SlaveTask(): The slave process
236 * CTRL_C terminates, CTRL_E stops playing/recording (error signal)
239 void ASM
SlaveTask(void) {
240 struct MsgPort
*AHImp
= NULL
;
241 struct AHIRequest
*AHIio
= NULL
;
244 ToccataBase
->tb_HardInfo
= NULL
;
247 dfh
=Open("con:10/300/400/300/Output",MODE_OLDFILE
);
248 DBG("Slave started!\n");
251 me
= (struct Process
*) FindTask(NULL
);
253 if(AHImp
=CreateMsgPort()) {
254 if(AHIio
=(struct AHIRequest
*)CreateIORequest(AHImp
,sizeof(struct AHIRequest
))) {
255 AHIio
->ahir_Version
= 4;
256 AHIDevice
= OpenDevice(AHINAME
, AHI_NO_UNIT
, (struct IORequest
*)AHIio
, NULL
);
261 AHIBase
= (struct Library
*) AHIio
->ahir_Std
.io_Device
;
265 SlaveInitialized
= TRUE
;
269 struct slavemessage
*msg
;
271 signals
= Wait((1L << me
->pr_MsgPort
.mp_SigBit
) |
272 SIGBREAKF_CTRL_C
| SIGBREAKF_CTRL_E
);
274 if(signals
& SIGBREAKF_CTRL_C
) {
278 if(signals
& SIGBREAKF_CTRL_E
) {
282 if(signals
& (1L << me
->pr_MsgPort
.mp_SigBit
)) {
283 while(msg
= (struct slavemessage
*) GetMsg(&me
->pr_MsgPort
)) {
284 DVAL("gotmessage! %ld: ",msg
->ID
);
285 DVAL("0x%08lx\n",msg
->Data
);
295 msg
->Data
= (APTR
) RawPlayback(msg
->Data
);
298 msg
->Data
= (APTR
) Playback(msg
->Data
);
304 Stop(*((ULONG
*) msg
->Data
));
307 Pause(*((ULONG
*) msg
->Data
));
319 ReplyMsg((struct Message
*) msg
);
325 SlaveInitialized
= FALSE
;
332 CloseDevice((struct IORequest
*)AHIio
);
334 DeleteIORequest((struct IORequest
*)AHIio
);
335 DeleteMsgPort(AHImp
);
336 DBG("(slave closed down)\n");
349 * IOTask(): The play/record process
350 * CTRL_C terminates, CTRL_D rawsignal, CTRL_E error signal
353 void ASM
IOTask(void) {
357 me
= (struct Process
*) FindTask(NULL
);
360 NewList(&BufferList
);
366 /* Open MAUD file for reading */
368 if(FileName
!= NULL
) {
371 iff
->iff_Stream
= Open(FileName
, MODE_OLDFILE
);
372 if(iff
->iff_Stream
) {
374 if(!OpenIFF(iff
, IFFF_READ
)) {
376 if(!StopChunk(iff
, ID_MAUD
, ID_MDAT
)) {
378 LONG error
= ParseIFF(iff
,IFFPARSE_SCAN
);
379 struct ContextNode
*cn
;
381 if(error
== IFFERR_EOC
) continue;
384 cn
= CurrentChunk(iff
);
386 if(cn
&& (cn
->cn_Type
== ID_MAUD
) && (cn
->cn_ID
== ID_MDAT
)) {
396 else rc
= TRUE
; /* Not an error! */
399 /* Fill the two play buffers with data */
401 memset(Buffer1
, 0, BufferSize
);
402 Load(Buffer1
, BufferSize
, LoadParam
);
404 memset(Buffer2
, 0, BufferSize
);
405 Load(Buffer2
, BufferSize
, LoadParam
);
409 /* Now prefill some more */
412 while(BuffersLoaded
< (PreBlocks
- 2)) {
413 struct Buffer
*buffer
;
415 buffer
= (struct Buffer
*) AllocVec(sizeof (struct Buffer
), MEMF_CLEAR
);
420 buffer
->Buffer
= AllocVec(BufferSize
, MEMF_PUBLIC
| MEMF_CLEAR
);
422 buffer
->Size
= Load(buffer
->Buffer
, BufferSize
, LoadParam
);
423 AddTail(&BufferList
, (struct Node
*) buffer
);
432 IOInitialized
= TRUE
;
434 DBG("iotask initialized\n");
440 signals
= SetSignal(0,0);
442 if(signals
& SIGBREAKF_CTRL_C
) {
443 DBG("iotask got break\n");
447 if(SIGBREAKF_CTRL_D
) {
448 struct Buffer
*buffer
;
451 DBG("iotask swapped buffer!\n");
453 buffer
= (struct Buffer
*) RemHead(&BufferList
);
457 memcpy((BufferFlag
== 0 ? Buffer1
: Buffer2
) , buffer
->Buffer
,
461 /* Clear the rest of the block */
462 if((BufferSize
- size
) > 0) {
463 memset((BufferFlag
== 0 ? Buffer1
: Buffer2
) + size
, 0,
467 if(BufferFlag
== 0) {
478 if(SIGBREAKF_CTRL_E
) {
479 DBG("iotask got error\n");
481 /* Ask him to stop and kill us */
482 Signal((struct Task
*) SlaveProcess
, SIGBREAKF_CTRL_E
);
487 /* If there are no signals pending, lets load some data! */
489 while((signals
& ((1L << me
->pr_MsgPort
.mp_SigBit
) |
490 SIGBREAKF_CTRL_C
| SIGBREAKF_CTRL_D
| SIGBREAKF_CTRL_E
)) == 0) {
492 if(BuffersLoaded
< PlayBlocks
) {
493 struct Buffer
*buffer
;
495 buffer
= AllocVec(sizeof (struct Buffer
), MEMF_CLEAR
);
500 buffer
->Buffer
= AllocVec(BufferSize
, MEMF_PUBLIC
| MEMF_CLEAR
);
502 buffer
->Size
= Load(buffer
->Buffer
, BufferSize
, LoadParam
);
503 AddTail(&BufferList
, (struct Node
*) buffer
);
513 signals
= Wait((1L << me
->pr_MsgPort
.mp_SigBit
) |
514 SIGBREAKF_CTRL_C
| SIGBREAKF_CTRL_D
| SIGBREAKF_CTRL_E
);
523 DBG("iotask terminating\n");
531 if(iff
->iff_Stream
) {
532 Close(iff
->iff_Stream
);
541 /* Free buffers if any left */
543 struct Buffer
*buffer
;
545 while(buffer
= (struct Buffer
*) RemHead(&BufferList
)) {
546 FreeVec(buffer
->Buffer
);
562 * ReadMAUD(): Used as callback function when playing
565 ASM LONG
ReadMAUD(REG(a0
) UBYTE
*buffer
, REG(d0
) ULONG length
,
566 REG(a1
) ULONG unused
)Â
{
568 return ReadChunkBytes(iff
, buffer
, length
);
572 * AllocAudio(): Allocate the audio hardware
575 static BOOL
AllocAudio(void) {
577 DBG("(AllocAudio())...\n");
579 /* Set up for HookFunc */
580 SoundHook
.h_Data
= ToccataBase
;
581 RecordHook
.h_Data
= ToccataBase
;
583 MinMonVol
= MaxMonVol
= 0;
584 MinOutVol
= MaxOutVol
= 0x10000;
585 MinGain
= MaxGain
= 0x10000;
587 audioctrl
= AHI_AllocAudio(
588 AHIA_AudioID
, (tprefs
.Mode
& TMODEF_STEREO
?
589 tprefs
.StereoMode
: tprefs
.MonoMode
),
590 AHIA_MixFreq
, tprefs
.Frequency
,
593 AHIA_SoundFunc
, &SoundHook
,
595 AHIA_PlayerFreq
, (tprefs
.Frequency
/ 512) << 16,
596 AHIA_MinPlayerFreq
, (tprefs
.Frequency
/ 512) << 16,
597 AHIA_MaxPlayerFreq
, (tprefs
.Frequency
/ 512) << 16,
598 AHIA_RecordFunc
, &RecordHook
,
601 if(audioctrl
!= NULL
) {
602 AHI_GetAudioAttrs(AHI_INVALID_ID
, audioctrl
,
603 AHIDB_MinMonitorVolume
, &MinMonVol
,
604 AHIDB_MaxMonitorVolume
, &MaxMonVol
,
605 AHIDB_MinOutputVolume
, &MinOutVol
,
606 AHIDB_MaxOutputVolume
, &MaxOutVol
,
607 AHIDB_MinInputGain
, &MinGain
,
608 AHIDB_MaxInputGain
, &MaxGain
,
614 AudioInitialized
= TRUE
;
624 * FreeAudio(): Release the audio hardware
627 static void FreeAudio(void) {
629 DBG("(FreeAudio())...\n");
636 if(audioctrl
!= NULL
) {
637 AHI_FreeAudio(audioctrl
);
641 AudioInitialized
= FALSE
;
646 * TuneAudio(): Change (hardware) properties of the allocated audio mode
649 static BOOL
TuneAudio() {
650 Fixed MonVol
, OutVol
, Gain
;
654 DBG("(TuneAudio())\n");
656 if(audioctrl
!= NULL
) {
658 MonVol
= negboundaries
[tprefs
.LoopbackVolume
];
659 OutVol
= negboundaries
[tprefs
.OutputVolumeLeft
];
660 Gain
= posboundaries
[tprefs
.InputVolumeLeft
];
662 MonVol
= min( max(MonVol
, MinMonVol
), MaxMonVol
);
663 OutVol
= min( max(OutVol
, MinOutVol
), MaxOutVol
);
664 Gain
= min( max(Gain
, MinGain
), MaxGain
);
666 switch(tprefs
.Input
) {
669 Input
= tprefs
.LineInput
;
673 Input
= tprefs
.Aux1Input
;
678 Input
= tprefs
.MicGainInput
;
681 Input
= tprefs
.MicInput
;
686 Input
= tprefs
.MixInput
;
690 rc
= AHI_ControlAudio(audioctrl
,
691 AHIC_MonitorVolume
, MonVol
,
692 AHIC_OutputVolume
, OutVol
,
693 AHIC_InputGain
, Gain
,
696 rc
= (rc
== AHIE_OK
? TRUE
: FALSE
);
704 * ControlAudio(): Start/Stop/Pause playing and recording
707 static BOOL
ControlAudio(void) {
710 DBG("(ControlAudio())\n");
713 rc
= AHI_ControlAudio(audioctrl
,
714 AHIC_Play
, (Playing
&& !Pausing
),
715 AHIC_Record
, (Recording
&& !Pausing
),
716 AHIA_PlayerFreq
, (tprefs
.Frequency
/ 512),
720 rc
= (rc
== AHIE_OK
? TRUE
: FALSE
);
726 * Pause(): Take care of the T_Pause() function
729 static void Pause(ULONG pause
) {
731 DVAL("(Pause %ld)\n", pause
);
738 * Stop(): Take care of the T_Stop() function
741 static void Stop(ULONG flags
) {
743 DVAL("Stop(%lx)...\n", flags
);
751 AHI_UnloadSound(0, audioctrl
);
755 AHI_UnloadSound(1, audioctrl
);
758 Sound0Loaded
= Sound1Loaded
= FALSE
;
768 RawBufferSize
= 32768;
772 ByteSkipCounter
= 2048;
775 Signal((struct Task
*)IOProcess
, SIGBREAKF_CTRL_C
);
781 if((flags
& TSF_DONTSAVECACHE
) == 0) {
782 /* Save cache here... */
785 /* Check if a record/play file is open, and close them if so */
791 * RawPlayback(): Take care of the T_RawPlayback() function
794 static BOOL
RawPlayback(struct TagItem
*tags
) {
796 BOOL newmode
= FALSE
;
797 struct TagItem
*tstate
;
800 DBG("RawPlayback()...\n");
802 /* Is this correct?? */
804 if(Playing
|| Recording
) {
808 /* Check arguments */
812 while (tag
= NextTagItem(&tstate
)) {
813 DVAL("%ld ", tag
->ti_Tag
- TT_Min
);
814 DVAL("0x%08lx,\n", tag
->ti_Data
);
815 switch (tag
->ti_Tag
) {
821 if(tag
->ti_Data
!= tprefs
.Mode
) {
822 tprefs
.Mode
= tag
->ti_Data
;
828 if(tag
->ti_Data
!= tprefs
.Frequency
) {
829 tprefs
.Frequency
= tag
->ti_Data
;
835 ErrorTask
= (struct Task
*) tag
->ti_Data
;
839 ErrorMask
= tag
->ti_Data
;
843 RawTask
= (struct Task
*) tag
->ti_Data
;
847 RawMask
= tag
->ti_Data
;
852 ULONG
*p
= (ULONG
*) tag
->ti_Data
;
854 *p
= GetRawReply(ToccataBase
);
855 DVAL("Rawreply is 0x%08lx\n", *p
);
860 RawInt
= (struct Interrupt
*) tag
->ti_Data
;
864 RawBuffer1
= (BYTE
*) tag
->ti_Data
;
868 RawBuffer2
= (BYTE
*) tag
->ti_Data
;
872 RawBufferSize
= tag
->ti_Data
;
876 RawIrqSize
= tag
->ti_Data
;
880 ByteCount
= (ULONG
*) tag
->ti_Data
;
884 ByteSkip
= tag
->ti_Data
;
888 SigTask
= (struct Task
*) tag
->ti_Data
;
892 SigMask
= tag
->ti_Data
;
900 if((ErrorTask
== NULL
) ||
901 ((RawTask
== NULL
) && (RawInt
== NULL
)) ||
902 (RawBuffer1
== NULL
) ||
903 (RawBuffer2
== NULL
)) {
909 if(rc
&& (newmode
|| !AudioInitialized
)) {
917 ULONG sampletype
= AHIST_NOTYPE
;
918 struct AHISampleInfo s0
, s1
;
920 switch(tprefs
.Mode
) {
922 sampletype
= AHIST_M8S
;
924 case TMODE_LINEAR_16
:
925 sampletype
= AHIST_M16S
;
932 case TMODE_LINEAR_8_S
:
933 sampletype
= AHIST_S8S
;
935 case TMODE_LINEAR_16_S
:
936 sampletype
= AHIST_S16S
;
948 if(sampletype
!= AHIST_NOTYPE
) {
951 s1
.ahisi_Type
= sampletype
;
952 s0
.ahisi_Address
= RawBuffer1
;
953 s1
.ahisi_Address
= RawBuffer2
;
955 s1
.ahisi_Length
= RawBufferSize
/ AHI_SampleFrameSize(sampletype
);
957 if(AHI_LoadSound(0, AHIST_DYNAMICSAMPLE
, &s0
, audioctrl
) == AHIE_OK
) {
961 if(AHI_LoadSound(1, AHIST_DYNAMICSAMPLE
, &s1
, audioctrl
) == AHIE_OK
) {
965 if(!(Sound0Loaded
&& Sound1Loaded
)) {
969 RawBufferLength
= RawBufferSize
/ AHI_SampleFrameSize(sampletype
);
983 AHIP_BeginChannel
, 0,
984 AHIP_Freq
, tprefs
.Frequency
,
989 AHIP_Length
, RawBufferLength
,
990 AHIP_EndChannel
, NULL
,
994 DVAL("ok %ld\n", rc
);
999 static BOOL
Playback(struct TagItem
*tags
) {
1001 struct TagItem
*tstate
;
1002 struct TagItem
*tag
;
1004 DBG("Playback()...\n");
1013 IoPri
= tprefs
.PlaybackIoPri
;
1014 BufferSize
= tprefs
.PlaybackBlockSize
;
1020 PreBlocks
= tprefs
.PlaybackStartBlocks
;
1021 PlayBlocks
= tprefs
.PlaybackBlocks
;
1024 Buffer1
= Buffer2
= NULL
;
1026 /* Check arguments */
1028 FileName
= (STRPTR
) GetTagData(TT_FileName
, NULL
, tags
);
1030 if(FileName
!= NULL
) {
1031 struct IFFHandle
*iff
;
1032 struct StoredProperty
*sp
;
1033 BOOL gotheader
= FALSE
;
1041 iff
->iff_Stream
= Open(FileName
, MODE_OLDFILE
);
1043 if(iff
->iff_Stream
) {
1047 if(!OpenIFF(iff
, IFFF_READ
)) {
1049 if(!(PropChunk(iff
, ID_MAUD
, ID_MHDR
)
1050 || StopOnExit(iff
,ID_MAUD
, ID_FORM
))) {
1052 while(ParseIFF(iff
,IFFPARSE_SCAN
) == IFFERR_EOC
) {
1054 sp
= FindProp(iff
, ID_MAUD
, ID_MHDR
);
1057 struct MaudHeader
*mhdr
= (struct MaudHeader
*) sp
->sp_Data
;
1061 Length
= mhdr
->mhdr_Samples
* mhdr
->mhdr_SampleSizeU
/ 8;
1063 tprefs
.Frequency
= mhdr
->mhdr_RateSource
/ mhdr
->mhdr_RateDevide
;
1065 switch(mhdr
->mhdr_Compression
) {
1068 if(mhdr
->mhdr_SampleSizeU
== 8) {
1069 tprefs
.Mode
= TMODE_LINEAR_8
;
1071 else if(mhdr
->mhdr_SampleSizeU
== 16) {
1072 tprefs
.Mode
= TMODE_LINEAR_16
;
1078 tprefs
.Mode
= TMODE_ALAW
;
1082 tprefs
.Mode
= TMODE_ULAW
;
1086 if(mhdr
->mhdr_ChannelInfo
== MCI_STEREO
) {
1087 tprefs
.Mode
|= TMODEF_STEREO
;
1089 else if(mhdr
->mhdr_ChannelInfo
!= MCI_MONO
) {
1095 break; /* We have what we want, no need to loop futher */
1101 Close(iff
->iff_Stream
);
1113 while (rc
&& (tag
= NextTagItem(&tstate
))) {
1114 //kprintf("%ld, 0x%08lx,\n", tag->ti_Tag - TT_Min, tag->ti_Data);
1115 switch (tag
->ti_Tag
) {
1118 Window
= (struct Window
*) tag
->ti_Data
;
1122 IoPri
= tag
->ti_Data
;
1129 BufferSize
= tag
->ti_Data
;
1133 Load
= (ASM
LONG (*)(REG(a0
) UBYTE
*, REG(d0
) ULONG
, REG(a1
) ULONG
)) tag
->ti_Data
;
1137 LoadParam
= tag
->ti_Data
;
1144 /* Already handled above!
1146 FileName = (STRPTR) tag->ti_Data;
1151 Length
= tag
->ti_Data
;
1159 SmartPlay
= tag
->ti_Data
;
1163 PreBlocks
= tag
->ti_Data
;
1167 PlayBlocks
= tag
->ti_Data
;
1171 Flags
= tag
->ti_Data
;
1175 EndTask
= (struct Task
*) tag
->ti_Data
;
1178 EndMask
= tag
->ti_Data
;
1182 case TT_StartOffset
:
1183 case TT_FieldsPerSecond
:
1187 /* RawPlayback takes care of these */
1197 if((Load
== 0) && (FileName
== NULL
)) {
1202 IOProcess
= CreateNewProcTags(
1203 NP_Entry
, IOTaskEntry
,
1206 NP_WindowPtr
, Window
,
1209 if(IOProcess
== NULL
) {
1215 struct TagItem rawtags
[] = {
1216 TT_RawTask
, 0, /* IOProcess */
1217 TT_RawMask
, SIGBREAKF_CTRL_D
,
1218 TT_RawBuffer1
, 0, /* Buffer1 */
1219 TT_RawBuffer2
, 0, /* Buffer2 */
1220 TT_BufferSize
, 0, /* BufferSize */
1221 TT_ErrorTask
, 0, /* IOProcess -- Can be overridded by users errortask */
1222 TT_ErrorMask
, SIGBREAKF_CTRL_E
,
1223 TAG_MORE
, 0, /* tags */
1227 Buffer1
= AllocVec(BufferSize
, MEMF_PUBLIC
);
1228 Buffer2
= AllocVec(BufferSize
, MEMF_PUBLIC
);
1230 rawtags
[0].ti_Data
= (ULONG
) IOProcess
;
1231 rawtags
[2].ti_Data
= (ULONG
) Buffer1
;
1232 rawtags
[3].ti_Data
= (ULONG
) Buffer2
;
1233 rawtags
[4].ti_Data
= (ULONG
) BufferSize
;
1234 rawtags
[5].ti_Data
= (ULONG
) IOProcess
;
1235 rawtags
[7].ti_Data
= (ULONG
) tags
;
1237 /* Make sure all buffers are preloaded */
1238 while((IOProcess
!= NULL
) && !IOInitialized
) {
1242 if(IOProcess
== NULL
) {
1247 rc
= RawPlayback((struct TagItem
*) &rawtags
);