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>
27 #include <proto/ahi.h>
28 #include <proto/dos.h>
29 #include <proto/exec.h>
30 #include <proto/utility.h>
31 #include <proto/iffparse.h>
32 #include <clib/toccata_protos.h>
33 #include <pragmas/toccata_pragmas.h>
40 #define ENVPREFS "ENV:toccata-emul.prefs"
41 #define ENVARCPREFS "ENVARC:toccata-emul.prefs"
42 #define IDCODE "TOCEMUL"
49 struct Library
*IFFParseBase
= NULL
;
50 struct Library
*UtilityBase
= NULL
;
51 struct Library
*AHIBase
= NULL
;
52 struct ToccataBase
*ToccataBase
= NULL
;
53 struct DosLibrary
*DOSBase
= NULL
;
55 struct Process
*SlaveProcess
= NULL
;
57 struct toccataprefs tprefs
= {
60 /* Toccata registers */
71 PATDEF_CAPTUREBUFFERPRI
,
72 PATDEF_CAPTUREBLOCKSIZE
,
73 PATDEF_MAXCAPTUREBLOCKS
,
75 PATDEF_PLAYBACKBUFFERPRI
,
76 PATDEF_PLAYBACKBLOCKSIZE
,
77 PATDEF_PLAYBACKSTARTBLOCKS
,
78 PATDEF_PLAYBACKBLOCKS
,
86 ULONG error
= TIOERR_UNKNOWN
;
94 * UserLibInit(): Library init
97 int ASM
__UserLibInit (REG(a6
) struct Library
*libbase
)
99 ToccataBase
= (struct ToccataBase
*) libbase
;
101 ToccataBase
->tb_BoardAddress
= (APTR
) 0xBADC0DED;
103 if(!(IFFParseBase
= OpenLibrary("iffparse.library",37)))
108 if(!(DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library",37)))
110 Alert(AN_Unknown
|AG_OpenLib
|AO_DOSLib
);
114 if(!(UtilityBase
= OpenLibrary("utility.library",37)))
116 Alert(AN_Unknown
|AG_OpenLib
|AO_UtilityLib
);
125 * UserLibCleanup(): Library cleanup
128 void ASM
__UserLibCleanup (REG(a6
) struct Library
*libbase
)
132 CloseLibrary(IFFParseBase
);
137 CloseLibrary((struct Library
*)DOSBase
);
142 CloseLibrary(UtilityBase
);
149 * UserLibOpen(): Called from OpenLibrary()
152 int ASM
__UserLibOpen (REG(a6
) struct Library
*libbase
) {
154 if(libbase
->lib_OpenCnt
== 1) {
155 /* Was 0, became 1 */
156 SlaveProcess
= CreateNewProcTags(
157 NP_Entry
, SlaveTaskEntry
,
162 /* Wait until our slave is ready */
163 while(SlaveProcess
&& !SlaveInitialized
) {
167 // DBG("Loading settings..\n");
168 // if(SlaveProcess && SlaveInitialized) {
169 // T_LoadSettings(0);
173 if(!SlaveInitialized
) {
182 * UserLibClose(): Called from CloseLibrary()
185 void ASM
__UserLibClose (REG(a6
) struct Library
*libbase
) {
186 if(libbase
->lib_OpenCnt
== 1) {
187 /* Is 1, will become 0 */
189 Signal((struct Task
*) SlaveProcess
, SIGBREAKF_CTRL_C
);
191 while(SlaveProcess
) {
199 * hardinfo & fillhardinfo()
202 static struct HardInfo hardinfo
;
204 void fillhardinfo(void) {
209 struct AHIAudioCtrl
*actrl
= NULL
;
216 if(tprefs
.Mode
& TMODEF_STEREO
) {
217 id
= tprefs
.StereoMode
;
220 id
= tprefs
.MonoMode
;
224 AHI_GetAudioAttrs(id
, actrl
,
225 AHIDB_Frequencies
, &freqs
,
226 AHIDB_MinMixFreq
, &minfreq
,
227 AHIDB_MaxMixFreq
, &maxfreq
,
230 hardinfo
.hi_Version
= 1;
231 hardinfo
.hi_Revision
= 0;
232 hardinfo
.hi_Frequencies
= freqs
;
233 hardinfo
.hi_MinFrequency
= minfreq
;
234 hardinfo
.hi_MaxFrequency
= maxfreq
;
235 hardinfo
.hi_Flags
= 0;
237 ToccataBase
->tb_HardInfo
= &hardinfo
;
242 * sendmessage(): Send a message to the slave and wait for reply
245 static ULONG
sendmessage(ULONG id
, APTR data
) {
246 struct MsgPort
*replyport
= NULL
;
247 struct slavemessage
*msg
= NULL
;
250 if(msg
= AllocVec(sizeof(struct slavemessage
), MEMF_PUBLIC
| MEMF_CLEAR
)) {
251 if(replyport
= CreateMsgPort()) {
252 msg
->Msg
.mn_ReplyPort
= replyport
;
253 msg
->Msg
.mn_Length
= sizeof(struct slavemessage
);
257 PutMsg(&SlaveProcess
->pr_MsgPort
, (struct Message
*) msg
);
261 rc
= (ULONG
) msg
->Data
;
262 DeleteMsgPort(replyport
);
275 ASM ULONG
t_IoErr(void) {
284 ASM BOOL
t_RawPlayback(REG(a0
) struct TagItem
*tags
) {
285 return (BOOL
) sendmessage(MSG_RAWPLAY
, tags
);
293 static BOOL
savesettings(STRPTR name
) {
297 file
= Open(name
, MODE_NEWFILE
);
299 if(Write(file
, &tprefs
, sizeof tprefs
) == sizeof tprefs
) {
307 ASM BOOL
t_SaveSettings(REG(d0
) ULONG flags
) {
311 rc
= savesettings(ENVARCPREFS
);
315 rc
= savesettings(ENVPREFS
);
326 static BOOL
loadsettings(STRPTR name
) {
329 struct toccataprefs tempprefs
;
331 file
= Open(name
, MODE_OLDFILE
);
333 if(Read(file
, &tempprefs
, sizeof tempprefs
) == sizeof tempprefs
) {
334 if(strcmp(tempprefs
.ID
, IDCODE
) == 0) {
335 memcpy(&tprefs
, &tempprefs
, sizeof tempprefs
);
344 ASM BOOL
t_LoadSettings(REG(d0
) ULONG flags
) {
348 rc
= loadsettings(ENVARCPREFS
);
350 else if(flags
== 0) {
351 rc
= loadsettings(ENVPREFS
);
355 PAT_InputVolumeLeft
, tprefs
.InputVolumeLeft
,
356 PAT_InputVolumeRight
, tprefs
.InputVolumeLeft
,
357 PAT_OutputVolumeLeft
, tprefs
.OutputVolumeLeft
,
358 PAT_OutputVolumeRight
,tprefs
.OutputVolumeRight
,
359 PAT_LoopbackVolume
, tprefs
.LoopbackVolume
,
360 PAT_Input
, tprefs
.Input
,
361 PAT_MicGain
, tprefs
.MicGain
,
362 PAT_Mode
, tprefs
.Mode
,
363 PAT_Frequency
, tprefs
.Frequency
,
374 ASM WORD
t_Expand(REG(d0
) UBYTE value
, REG(d1
) ULONG mode
) {
383 ASM BOOL
t_StartLevel(REG(a0
) struct TagItem
*tags
) {
384 return (BOOL
) sendmessage(MSG_LEVELON
, tags
);
392 ASM BOOL
t_Capture(REG(a0
) struct TagItem
*tags
) {
393 return (BOOL
) sendmessage(MSG_RECORD
, tags
);
401 ASM BOOL
t_Playback(REG(a0
) struct TagItem
*tags
) {
402 return (BOOL
) sendmessage(MSG_PLAY
, tags
);
410 ASM
void t_Pause(REG(d0
) ULONG pause
) {
412 sendmessage(MSG_PAUSE
, &p
);
420 ASM
void t_Stop(REG(d0
) ULONG flags
) {
422 sendmessage(MSG_STOP
, &f
);
430 ASM
void t_StopLevel(void) {
431 sendmessage(MSG_LEVELOFF
, NULL
);
439 ASM ULONG
t_FindFrequency(REG(d0
) ULONG frequency
) {
443 struct AHIAudioCtrl
*actrl
= NULL
;
450 if(tprefs
.Mode
& TMODEF_STEREO
) {
451 id
= tprefs
.StereoMode
;
454 id
= tprefs
.MonoMode
;
459 AHI_GetAudioAttrs(id
, actrl
,
460 AHIDB_IndexArg
, frequency
,
464 AHI_GetAudioAttrs(id
, actrl
,
465 AHIDB_FrequencyArg
, index
,
466 AHIDB_Frequency
, &freq
,
477 ASM ULONG
t_NextFrequency(REG(d0
) ULONG frequency
) {
478 LONG frequencies
= 1;
482 struct AHIAudioCtrl
*actrl
= NULL
;
489 if(tprefs
.Mode
& TMODEF_STEREO
) {
490 id
= tprefs
.StereoMode
;
493 id
= tprefs
.MonoMode
;
497 if(frequency
< ToccataBase
->tb_HardInfo
->hi_MinFrequency
) {
501 AHI_GetAudioAttrs(id
, actrl
,
502 AHIDB_IndexArg
, frequency
,
504 AHIDB_Frequencies
, &frequencies
,
507 if(index
< (frequencies
- 1 )) {
515 AHI_GetAudioAttrs(id
, actrl
,
516 AHIDB_FrequencyArg
, index
,
517 AHIDB_Frequency
, &freq
,
528 ASM
void t_SetPart(REG(a0
) struct TagItem
*tags
) {
529 struct TagItem
*tstate
;
532 BOOL newmode
= FALSE
;
533 BOOL newhwprop
= FALSE
;
537 while (tag
= NextTagItem(&tstate
)) {
538 switch (tag
->ti_Tag
) {
539 case PAT_MixAux1Left
:
540 tprefs
.MixAux1Left
= tag
->ti_Data
;
543 case PAT_MixAux1Right
:
544 tprefs
.MixAux1Right
= tag
->ti_Data
;
547 case PAT_MixAux2Left
:
548 tprefs
.MixAux2Left
= tag
->ti_Data
;
551 case PAT_MixAux2Right
:
552 tprefs
.MixAux2Right
= tag
->ti_Data
;
555 case PAT_InputVolumeLeft
:
556 tprefs
.InputVolumeLeft
= tag
->ti_Data
;
559 case PAT_InputVolumeRight
:
560 tprefs
.InputVolumeRight
= tag
->ti_Data
;
563 case PAT_OutputVolumeLeft
:
564 tprefs
.OutputVolumeLeft
= tag
->ti_Data
;
567 case PAT_OutputVolumeRight
:
568 tprefs
.OutputVolumeRight
= tag
->ti_Data
;
571 case PAT_LoopbackVolume
:
572 tprefs
.LoopbackVolume
= tag
->ti_Data
;
576 tprefs
.Mode
= tag
->ti_Data
;
580 tprefs
.Frequency
= tag
->ti_Data
;
584 tprefs
.Input
= tag
->ti_Data
;
588 tprefs
.MicGain
= tag
->ti_Data
;
592 /* These are unsupported */
593 case PAT_CaptureIoPri
:
594 tprefs
.CaptureIoPri
= tag
->ti_Data
;
596 case PAT_CaptureBufferPri
:
597 tprefs
.CaptureBufferPri
= tag
->ti_Data
;
599 case PAT_CaptureBlockSize
:
600 tprefs
.CaptureBlockSize
= tag
->ti_Data
;
602 case PAT_MaxCaptureBlocks
:
603 tprefs
.MaxCaptureBlocks
= tag
->ti_Data
;
605 case PAT_PlaybackIoPri
:
606 tprefs
.PlaybackIoPri
= tag
->ti_Data
;
608 case PAT_PlaybackBufferPri
:
609 tprefs
.PlaybackBufferPri
= tag
->ti_Data
;
611 case PAT_PlaybackBlockSize
:
612 tprefs
.PlaybackBlockSize
= tag
->ti_Data
;
614 case PAT_PlaybackStartBlocks
:
615 tprefs
.PlaybackStartBlocks
= tag
->ti_Data
;
617 case PAT_PlaybackBlocks
:
618 tprefs
.PlaybackBlocks
= tag
->ti_Data
;
624 sendmessage(MSG_MODE
, NULL
);
627 sendmessage(MSG_HWPROP
, NULL
);
636 ASM
void t_GetPart(REG(a0
) struct TagItem
*tags
) {
637 struct TagItem
*tstate
;
643 while (tag
= NextTagItem(&tstate
)) {
646 dst
= (ULONG
*) tag
->ti_Data
;
648 switch (tag
->ti_Tag
) {
649 case PAT_MixAux1Left
:
650 *dst
= tprefs
.MixAux1Left
;
652 case PAT_MixAux1Right
:
653 *dst
= tprefs
.MixAux1Right
;
655 case PAT_MixAux2Left
:
656 *dst
= tprefs
.MixAux2Left
;
658 case PAT_MixAux2Right
:
659 *dst
= tprefs
.MixAux2Right
;
661 case PAT_InputVolumeLeft
:
662 *dst
= tprefs
.InputVolumeLeft
;
664 case PAT_InputVolumeRight
:
665 *dst
= tprefs
.InputVolumeRight
;
667 case PAT_OutputVolumeLeft
:
668 *dst
= tprefs
.OutputVolumeLeft
;
670 case PAT_OutputVolumeRight
:
671 *dst
= tprefs
.OutputVolumeRight
;
673 case PAT_LoopbackVolume
:
674 *dst
= tprefs
.LoopbackVolume
;
680 *dst
= tprefs
.Frequency
;
686 *dst
= tprefs
.MicGain
;
688 case PAT_CaptureIoPri
:
689 *dst
= tprefs
.CaptureIoPri
;
691 case PAT_CaptureBufferPri
:
692 *dst
= tprefs
.CaptureBufferPri
;
694 case PAT_CaptureBlockSize
:
695 *dst
= tprefs
.CaptureBlockSize
;
697 case PAT_MaxCaptureBlocks
:
698 *dst
= tprefs
.MaxCaptureBlocks
;
700 case PAT_PlaybackIoPri
:
701 *dst
= tprefs
.PlaybackIoPri
;
703 case PAT_PlaybackBufferPri
:
704 *dst
= tprefs
.PlaybackBufferPri
;
706 case PAT_PlaybackBlockSize
:
707 *dst
= tprefs
.PlaybackBlockSize
;
709 case PAT_PlaybackStartBlocks
:
710 *dst
= tprefs
.PlaybackStartBlocks
;
712 case PAT_PlaybackBlocks
:
713 *dst
= tprefs
.PlaybackBlocks
;
723 ASM
struct TocHandle
* t_Open(REG(a0
) UBYTE
*name
, REG(a1
) struct TagItem
*tags
) {
732 ASM
void t_Close(REG(a0
) struct TocHandle
*handle
) {
740 ASM BOOL
t_Play(REG(a0
) struct TocHandle
*handle
, REG(a1
) struct TagItem
*tags
) {
749 ASM BOOL
t_Record(REG(a0
) struct TocHandle
*handle
, REG(a1
) struct TagItem
*tags
) {
757 ASM
void t_Convert(REG(a0
) APTR src
, REG(a1
) APTR dest
, REG(d0
) ULONG samples
,
758 REG(d1
) ULONG srcmode
, REG(d2
) ULONG destmode
) {
766 ASM ULONG
t_BytesPerSample(REG(d0
) ULONG mode
) {
767 const static ULONG table
[] = {
769 2, // TMODE_LINEAR_16
776 2, // TMODE_LINEAR_8_S
777 4, // TMODE_LINEAR_16_S
792 /* No documentation available for the following functions */
799 ASM
struct MultiSoundHandle
* t_OpenFile(REG(a0
) UBYTE
*name
, REG(d0
) ULONG flags
) {
808 ASM
void t_CloseFile(REG(a0
) struct MultiSoundHandle
*handle
) {
816 ASM LONG
t_ReadFile(REG(a0
) struct MultiSoundHandle
*handle
,
817 REG(a1
) UBYTE
*dest
, REG(d0
) ULONG length
) {
825 /* No prototypes available for the following functions... */
832 ASM ULONG
t_WriteSmpte(void) {
841 ASM ULONG
t_StopSmpte(void) {
850 ASM ULONG
t_Reserved1(void) {
859 ASM ULONG
t_Reserved2(void) {
868 ASM ULONG
t_Reserved3(void) {
877 ASM ULONG
t_Reserved4(void) {
886 ASM
void t_Own(void) {
894 ASM
void t_Disown(void) {
902 ASM
void t_SetReg(void) {
910 ASM ULONG
t_GetReg(void) {