Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / AHI / Drivers / Alsa / alsa-playslave.c
blobfb7c011c818fc60f944ea766d6a0deaf20f37c3c
1 /*
2 Copyright © 2015-2016, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/debug.h>
7 #include <config.h>
9 #include <devices/ahi.h>
10 #include <exec/execbase.h>
11 #include <libraries/ahi_sub.h>
13 #include "DriverData.h"
14 #include "library.h"
16 #include "alsa-bridge/alsa.h"
18 #define dd ((struct AlsaData*) AudioCtrl->ahiac_DriverData)
20 #define min(a,b) ( (a) < (b) ? (a) : (b) )
22 /******************************************************************************
23 ** The slave process **********************************************************
24 ******************************************************************************/
26 #undef SysBase
28 void Slave( struct ExecBase* SysBase );
30 #include <aros/asmcall.h>
32 AROS_UFH3(LONG, SlaveEntry,
33 AROS_UFHA(STRPTR, argPtr, A0),
34 AROS_UFHA(ULONG, argSize, D0),
35 AROS_UFHA(struct ExecBase *, SysBase, A6))
37 AROS_USERFUNC_INIT
38 Slave( SysBase );
39 return 0;
40 AROS_USERFUNC_EXIT
43 #include <hardware/intbits.h>
44 #include <proto/timer.h>
46 AROS_INTH1(AHITimerTickCode, struct Task *, task)
48 AROS_INTFUNC_INIT
49 Signal(task, SIGBREAKF_CTRL_F);
50 return 0;
52 AROS_INTFUNC_EXIT
57 static void SmallDelay(struct ExecBase *SysBase)
59 struct Interrupt i;
61 i.is_Code = (APTR)AHITimerTickCode;
62 i.is_Data = FindTask(0);
63 i.is_Node.ln_Name = "AROS AHI Driver Timer Tick Server";
64 i.is_Node.ln_Pri = 0;
65 i.is_Node.ln_Type = NT_INTERRUPT;
67 SetSignal(0, SIGBREAKF_CTRL_F);
68 AddIntServer(INTB_VERTB, &i);
69 Wait(SIGBREAKF_CTRL_F);
70 RemIntServer(INTB_VERTB, &i);
73 void
74 Slave( struct ExecBase* SysBase )
76 struct AHIAudioCtrlDrv* AudioCtrl;
77 struct DriverBase* AHIsubBase;
78 BOOL running;
79 ULONG signals;
80 LONG framesready = 0;
81 APTR framesptr = NULL;
83 AudioCtrl = (struct AHIAudioCtrlDrv*) FindTask(NULL)->tc_UserData;
84 AHIsubBase = (struct DriverBase*) dd->ahisubbase;
85 dd->slavesignal = AllocSignal( -1 );
87 if( dd->slavesignal != -1 )
89 // Everything set up. Tell Master we're alive and healthy.
91 Signal( (struct Task*) dd->mastertask,
92 1L << dd->mastersignal );
94 running = TRUE;
96 while( running )
98 signals = SetSignal(0L,0L);
100 if( signals & ( SIGBREAKF_CTRL_C | (1L << dd->slavesignal) ) )
102 running = FALSE;
104 else
106 LONG framesfree = 0;
107 LONG readcycles = 0;
109 while(TRUE)
111 framesfree = ALSA_Avail(dd->alsahandle);
112 if (framesfree == ALSA_XRUN)
114 D(bug("[Alsa] ALSA_Avail() == XRUN\n"));
115 ALSA_Prepare(dd->alsahandle);
116 framesfree = ALSA_Avail(dd->alsahandle);
119 if (framesfree >= 64)
121 readcycles++;
122 if (framesfree >= AudioCtrl->ahiac_BuffSamples)
123 readcycles++;
124 break;
127 SmallDelay(SysBase);
130 /* Loop until alsa buffer is filled */
131 while (framesfree > 0)
133 LONG written;
135 if (framesready == 0)
137 if (readcycles == 0)
138 break;
140 CallHookPkt(AudioCtrl->ahiac_PlayerFunc, AudioCtrl, NULL );
141 CallHookPkt(AudioCtrl->ahiac_MixerFunc, AudioCtrl, dd->mixbuffer );
142 framesready = AudioCtrl->ahiac_BuffSamples;
143 framesptr = dd->mixbuffer;
144 readcycles--;
147 written = ALSA_Write(dd->alsahandle, framesptr, min(framesready,
148 framesfree));
149 if (written == ALSA_XRUN)
151 D(bug("[Alsa] ALSA_Write() == XRUN %d, %d\n", framesfree, framesready));
152 ALSA_Prepare(dd->alsahandle);
153 written = ALSA_Write(dd->alsahandle, framesptr, min(framesready,
154 framesfree));
157 framesready -= written;
158 framesfree -= written;
159 framesptr += written * 4;
161 CallHookA(AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0);
167 FreeSignal( dd->slavesignal );
168 dd->slavesignal = -1;
170 Forbid();
172 // Tell the Master we're dying
174 Signal( (struct Task*) dd->mastertask, 1L << dd->mastersignal );
176 dd->slavetask = NULL;
178 // Multitaking will resume when we are dead.