Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / AHI / Toccata / toccata.c
blob68b0094046418a75714429392734449b86ed38a1
1 /*
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,
18 MA 02139, USA.
22 #include <devices/ahi.h>
23 #include <dos/dos.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>
35 #include <string.h>
36 #include <stdio.h>
38 #include "toccata.h"
40 #define ENVPREFS "ENV:toccata-emul.prefs"
41 #define ENVARCPREFS "ENVARC:toccata-emul.prefs"
42 #define IDCODE "TOCEMUL"
45 /* Globals */
47 #include "version.h"
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 = {
58 IDCODE,
60 /* Toccata registers */
61 -24, -24,
62 -24, -24,
63 0, 0,
64 0, 0,
66 TMODE_LINEAR_8,
67 11025,
68 TINPUT_Line,
69 FALSE,
70 PATDEF_CAPTUREIOPRI,
71 PATDEF_CAPTUREBUFFERPRI,
72 PATDEF_CAPTUREBLOCKSIZE,
73 PATDEF_MAXCAPTUREBLOCKS,
74 PATDEF_PLAYBACKIOPRI,
75 PATDEF_PLAYBACKBUFFERPRI,
76 PATDEF_PLAYBACKBLOCKSIZE,
77 PATDEF_PLAYBACKSTARTBLOCKS,
78 PATDEF_PLAYBACKBLOCKS,
80 /* AHI prefs */
81 0x00100006,
82 0x00100002,
83 0, 0, 0, 0, 0
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)))
105 return 1;
108 if(!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",37)))
110 Alert(AN_Unknown|AG_OpenLib|AO_DOSLib);
111 return 1;
114 if(!(UtilityBase = OpenLibrary("utility.library",37)))
116 Alert(AN_Unknown|AG_OpenLib|AO_UtilityLib);
117 return 1;
120 puta4();
121 return 0;
125 * UserLibCleanup(): Library cleanup
128 void ASM __UserLibCleanup (REG(a6) struct Library *libbase)
131 if(IFFParseBase) {
132 CloseLibrary(IFFParseBase);
133 IFFParseBase = NULL;
136 if(DOSBase) {
137 CloseLibrary((struct Library *)DOSBase);
138 DOSBase = NULL;
141 if(UtilityBase) {
142 CloseLibrary(UtilityBase);
143 UtilityBase = NULL;
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,
158 NP_Name, _LibName,
159 NP_Priority, 3,
160 TAG_DONE);
162 /* Wait until our slave is ready */
163 while(SlaveProcess && !SlaveInitialized) {
164 Delay(1);
167 // DBG("Loading settings..\n");
168 // if(SlaveProcess && SlaveInitialized) {
169 // T_LoadSettings(0);
170 // }
173 if(!SlaveInitialized) {
174 return 1;
177 return 0;
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 */
188 if(SlaveProcess) {
189 Signal((struct Task *) SlaveProcess, SIGBREAKF_CTRL_C);
191 while(SlaveProcess) {
192 Delay(1);
199 * hardinfo & fillhardinfo()
202 static struct HardInfo hardinfo;
204 void fillhardinfo(void) {
205 LONG freqs = 1;
206 ULONG minfreq = 0;
207 ULONG maxfreq = 0;
208 ULONG id;
209 struct AHIAudioCtrl *actrl = NULL;
211 if(audioctrl) {
212 id = AHI_INVALID_ID;
213 actrl = audioctrl;
215 else {
216 if(tprefs.Mode & TMODEF_STEREO) {
217 id = tprefs.StereoMode;
219 else {
220 id = tprefs.MonoMode;
224 AHI_GetAudioAttrs(id, actrl,
225 AHIDB_Frequencies, &freqs,
226 AHIDB_MinMixFreq, &minfreq,
227 AHIDB_MaxMixFreq, &maxfreq,
228 TAG_DONE);
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;
248 ULONG rc = 0;
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);
254 msg->ID = id;
255 msg->Data = data;
257 PutMsg(&SlaveProcess->pr_MsgPort, (struct Message *) msg);
259 WaitPort(replyport);
260 GetMsg(replyport);
261 rc = (ULONG) msg->Data;
262 DeleteMsgPort(replyport);
263 FreeVec(msg);
267 return rc;
272 * IoErr()
275 ASM ULONG t_IoErr(void) {
276 return error;
281 * RawPlayback()
284 ASM BOOL t_RawPlayback(REG(a0) struct TagItem *tags) {
285 return (BOOL) sendmessage(MSG_RAWPLAY, tags);
290 * SaveSettings()
293 static BOOL savesettings(STRPTR name) {
294 BOOL rc = FALSE;
295 BPTR file;
297 file = Open(name, MODE_NEWFILE);
298 if(file) {
299 if(Write(file, &tprefs, sizeof tprefs) == sizeof tprefs) {
300 rc = TRUE;
302 Close(file);
304 return rc;
307 ASM BOOL t_SaveSettings(REG(d0) ULONG flags) {
308 BOOL rc = TRUE;
310 if(flags == 1) {
311 rc = savesettings(ENVARCPREFS);
314 if(rc) {
315 rc = savesettings(ENVPREFS);
318 return rc;
323 * LoadSettings()
326 static BOOL loadsettings(STRPTR name) {
327 BOOL rc = FALSE;
328 BPTR file;
329 struct toccataprefs tempprefs;
331 file = Open(name, MODE_OLDFILE);
332 if(file) {
333 if(Read(file, &tempprefs, sizeof tempprefs) == sizeof tempprefs) {
334 if(strcmp(tempprefs.ID, IDCODE) == 0) {
335 memcpy(&tprefs, &tempprefs, sizeof tempprefs);
336 rc = TRUE;
339 Close(file);
341 return rc;
344 ASM BOOL t_LoadSettings(REG(d0) ULONG flags) {
345 BOOL rc = FALSE;
347 if(flags == 1) {
348 rc = loadsettings(ENVARCPREFS);
350 else if(flags == 0) {
351 rc = loadsettings(ENVPREFS);
354 T_SetPartTags(
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,
364 TAG_DONE);
366 return rc;
371 * Expand()
374 ASM WORD t_Expand(REG(d0) UBYTE value, REG(d1) ULONG mode) {
375 return 0;
380 * StartLevel()
383 ASM BOOL t_StartLevel(REG(a0) struct TagItem *tags) {
384 return (BOOL) sendmessage(MSG_LEVELON, tags);
389 * Capture()
392 ASM BOOL t_Capture(REG(a0) struct TagItem *tags) {
393 return (BOOL) sendmessage(MSG_RECORD, tags);
398 * Playback()
401 ASM BOOL t_Playback(REG(a0) struct TagItem *tags) {
402 return (BOOL) sendmessage(MSG_PLAY, tags);
407 * Pause()
410 ASM void t_Pause(REG(d0) ULONG pause) {
411 ULONG p = pause;
412 sendmessage(MSG_PAUSE, &p);
417 * Stop()
420 ASM void t_Stop(REG(d0) ULONG flags) {
421 ULONG f = flags;
422 sendmessage(MSG_STOP, &f);
427 * StopLevel()
430 ASM void t_StopLevel(void) {
431 sendmessage(MSG_LEVELOFF, NULL);
436 * FindFrequency()
439 ASM ULONG t_FindFrequency(REG(d0) ULONG frequency) {
440 ULONG index = 0;
441 ULONG freq = 0;
442 ULONG id;
443 struct AHIAudioCtrl *actrl = NULL;
445 if(audioctrl) {
446 id = AHI_INVALID_ID;
447 actrl = audioctrl;
449 else {
450 if(tprefs.Mode & TMODEF_STEREO) {
451 id = tprefs.StereoMode;
453 else {
454 id = tprefs.MonoMode;
459 AHI_GetAudioAttrs(id, actrl,
460 AHIDB_IndexArg, frequency,
461 AHIDB_Index, &index,
462 TAG_DONE);
464 AHI_GetAudioAttrs(id, actrl,
465 AHIDB_FrequencyArg, index,
466 AHIDB_Frequency, &freq,
467 TAG_DONE);
469 return freq;
474 * NextFrequency()
477 ASM ULONG t_NextFrequency(REG(d0) ULONG frequency) {
478 LONG frequencies = 1;
479 ULONG index = 0;
480 ULONG freq = 0;
481 ULONG id;
482 struct AHIAudioCtrl *actrl = NULL;
484 if(audioctrl) {
485 id = AHI_INVALID_ID;
486 actrl = audioctrl;
488 else {
489 if(tprefs.Mode & TMODEF_STEREO) {
490 id = tprefs.StereoMode;
492 else {
493 id = tprefs.MonoMode;
497 if(frequency < ToccataBase->tb_HardInfo->hi_MinFrequency) {
498 index = 0;
500 else {
501 AHI_GetAudioAttrs(id, actrl,
502 AHIDB_IndexArg, frequency,
503 AHIDB_Index, &index,
504 AHIDB_Frequencies, &frequencies,
505 TAG_DONE);
507 if(index < (frequencies - 1 )) {
508 index++;
510 else {
511 return 0;
515 AHI_GetAudioAttrs(id, actrl,
516 AHIDB_FrequencyArg, index,
517 AHIDB_Frequency, &freq,
518 TAG_DONE);
520 return freq;
525 * SetPart()
528 ASM void t_SetPart(REG(a0) struct TagItem *tags) {
529 struct TagItem *tstate;
530 struct TagItem *tag;
532 BOOL newmode = FALSE;
533 BOOL newhwprop = FALSE;
535 tstate = tags;
537 while (tag = NextTagItem(&tstate)) {
538 switch (tag->ti_Tag) {
539 case PAT_MixAux1Left:
540 tprefs.MixAux1Left = tag->ti_Data;
541 newhwprop = TRUE;
542 break;
543 case PAT_MixAux1Right:
544 tprefs.MixAux1Right = tag->ti_Data;
545 newhwprop = TRUE;
546 break;
547 case PAT_MixAux2Left:
548 tprefs.MixAux2Left = tag->ti_Data;
549 newhwprop = TRUE;
550 break;
551 case PAT_MixAux2Right:
552 tprefs.MixAux2Right = tag->ti_Data;
553 newhwprop = TRUE;
554 break;
555 case PAT_InputVolumeLeft:
556 tprefs.InputVolumeLeft = tag->ti_Data;
557 newhwprop = TRUE;
558 break;
559 case PAT_InputVolumeRight:
560 tprefs.InputVolumeRight = tag->ti_Data;
561 newhwprop = TRUE;
562 break;
563 case PAT_OutputVolumeLeft:
564 tprefs.OutputVolumeLeft = tag->ti_Data;
565 newhwprop = TRUE;
566 break;
567 case PAT_OutputVolumeRight:
568 tprefs.OutputVolumeRight = tag->ti_Data;
569 newhwprop = TRUE;
570 break;
571 case PAT_LoopbackVolume:
572 tprefs.LoopbackVolume = tag->ti_Data;
573 newhwprop = TRUE;
574 break;
575 case PAT_Mode:
576 tprefs.Mode = tag->ti_Data;
577 newmode = TRUE;
578 break;
579 case PAT_Frequency:
580 tprefs.Frequency = tag->ti_Data;
581 newmode = TRUE;
582 break;
583 case PAT_Input:
584 tprefs.Input = tag->ti_Data;
585 newhwprop = TRUE;
586 break;
587 case PAT_MicGain:
588 tprefs.MicGain = tag->ti_Data;
589 newhwprop = TRUE;
590 break;
592 /* These are unsupported */
593 case PAT_CaptureIoPri:
594 tprefs.CaptureIoPri = tag->ti_Data;
595 break;
596 case PAT_CaptureBufferPri:
597 tprefs.CaptureBufferPri = tag->ti_Data;
598 break;
599 case PAT_CaptureBlockSize:
600 tprefs.CaptureBlockSize = tag->ti_Data;
601 break;
602 case PAT_MaxCaptureBlocks:
603 tprefs.MaxCaptureBlocks = tag->ti_Data;
604 break;
605 case PAT_PlaybackIoPri:
606 tprefs.PlaybackIoPri = tag->ti_Data;
607 break;
608 case PAT_PlaybackBufferPri:
609 tprefs.PlaybackBufferPri = tag->ti_Data;
610 break;
611 case PAT_PlaybackBlockSize:
612 tprefs.PlaybackBlockSize = tag->ti_Data;
613 break;
614 case PAT_PlaybackStartBlocks:
615 tprefs.PlaybackStartBlocks = tag->ti_Data;
616 break;
617 case PAT_PlaybackBlocks:
618 tprefs.PlaybackBlocks = tag->ti_Data;
619 break;
623 if(newmode) {
624 sendmessage(MSG_MODE, NULL);
626 else if(newhwprop) {
627 sendmessage(MSG_HWPROP, NULL);
633 * GetPart()
636 ASM void t_GetPart(REG(a0) struct TagItem *tags) {
637 struct TagItem *tstate;
638 struct TagItem *tag;
640 tstate = tags;
643 while (tag = NextTagItem(&tstate)) {
644 ULONG *dst;
646 dst = (ULONG *) tag->ti_Data;
648 switch (tag->ti_Tag) {
649 case PAT_MixAux1Left:
650 *dst = tprefs.MixAux1Left;
651 break;
652 case PAT_MixAux1Right:
653 *dst = tprefs.MixAux1Right;
654 break;
655 case PAT_MixAux2Left:
656 *dst = tprefs.MixAux2Left;
657 break;
658 case PAT_MixAux2Right:
659 *dst = tprefs.MixAux2Right;
660 break;
661 case PAT_InputVolumeLeft:
662 *dst = tprefs.InputVolumeLeft;
663 break;
664 case PAT_InputVolumeRight:
665 *dst = tprefs.InputVolumeRight;
666 break;
667 case PAT_OutputVolumeLeft:
668 *dst = tprefs.OutputVolumeLeft;
669 break;
670 case PAT_OutputVolumeRight:
671 *dst = tprefs.OutputVolumeRight;
672 break;
673 case PAT_LoopbackVolume:
674 *dst = tprefs.LoopbackVolume;
675 break;
676 case PAT_Mode:
677 *dst = tprefs.Mode;
678 break;
679 case PAT_Frequency:
680 *dst = tprefs.Frequency;
681 break;
682 case PAT_Input:
683 *dst = tprefs.Input;
684 break;
685 case PAT_MicGain:
686 *dst = tprefs.MicGain;
687 break;
688 case PAT_CaptureIoPri:
689 *dst = tprefs.CaptureIoPri;
690 break;
691 case PAT_CaptureBufferPri:
692 *dst = tprefs.CaptureBufferPri;
693 break;
694 case PAT_CaptureBlockSize:
695 *dst = tprefs.CaptureBlockSize;
696 break;
697 case PAT_MaxCaptureBlocks:
698 *dst = tprefs.MaxCaptureBlocks;
699 break;
700 case PAT_PlaybackIoPri:
701 *dst = tprefs.PlaybackIoPri;
702 break;
703 case PAT_PlaybackBufferPri:
704 *dst = tprefs.PlaybackBufferPri;
705 break;
706 case PAT_PlaybackBlockSize:
707 *dst = tprefs.PlaybackBlockSize;
708 break;
709 case PAT_PlaybackStartBlocks:
710 *dst = tprefs.PlaybackStartBlocks;
711 break;
712 case PAT_PlaybackBlocks:
713 *dst = tprefs.PlaybackBlocks;
714 break;
720 * Open()
723 ASM struct TocHandle * t_Open(REG(a0) UBYTE *name, REG(a1) struct TagItem *tags) {
724 return NULL;
729 * Close()
732 ASM void t_Close(REG(a0) struct TocHandle *handle) {
737 * Play()
740 ASM BOOL t_Play(REG(a0) struct TocHandle *handle, REG(a1) struct TagItem *tags) {
741 return FALSE;
746 * Record()
749 ASM BOOL t_Record(REG(a0) struct TocHandle *handle, REG(a1) struct TagItem *tags) {
750 return FALSE;
754 * Convert()
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) {
763 * BytesPerSample()
766 ASM ULONG t_BytesPerSample(REG(d0) ULONG mode) {
767 const static ULONG table[] = {
768 1, // TMODE_LINEAR_8
769 2, // TMODE_LINEAR_16
770 1, // TMODE_ALAW
771 1, // TMODE_ULAW
772 2, // TMODE_RAW_16
776 2, // TMODE_LINEAR_8_S
777 4, // TMODE_LINEAR_16_S
778 2, // TMODE_ALAW_S
779 2, // TMODE_ULAW_S
780 4, // TMODE_RAW_16_S
786 return table[mode];
792 /* No documentation available for the following functions */
796 * OpenFile()
799 ASM struct MultiSoundHandle * t_OpenFile(REG(a0) UBYTE *name, REG(d0) ULONG flags) {
800 return NULL;
805 * CloseFile()
808 ASM void t_CloseFile(REG(a0) struct MultiSoundHandle *handle) {
813 * ReadFile()
816 ASM LONG t_ReadFile(REG(a0) struct MultiSoundHandle *handle,
817 REG(a1) UBYTE *dest, REG(d0) ULONG length) {
818 return 0;
825 /* No prototypes available for the following functions... */
829 * WriteSmpte()
832 ASM ULONG t_WriteSmpte(void) {
833 return 0;
838 * StopSmpte()
841 ASM ULONG t_StopSmpte(void) {
842 return 0;
847 * Reserved1()
850 ASM ULONG t_Reserved1(void) {
851 return 0;
856 * Reserved2()
859 ASM ULONG t_Reserved2(void) {
860 return 0;
865 * Reserved3()
868 ASM ULONG t_Reserved3(void) {
869 return 0;
874 * Reserved4()
877 ASM ULONG t_Reserved4(void) {
878 return 0;
883 * Own()
886 ASM void t_Own(void) {
891 * Disown()
894 ASM void t_Disown(void) {
899 * SetReg()
902 ASM void t_SetReg(void) {
907 * GetReg()
910 ASM ULONG t_GetReg(void) {
911 return 0;