includes: AROS_UFIxx -> AROS_INTxx change
[AROS.git] / workbench / devs / AHI / Drivers / AROS / aros-playslave.c
blob94ccf4a47f7c9c7f3d6b91321c5f277656adc66b
2 #include <config.h>
4 #include <devices/ahi.h>
5 #include <libraries/ahi_sub.h>
7 #include "DriverData.h"
8 #include "library.h"
10 #define dd ((struct AROSData*) AudioCtrl->ahiac_DriverData)
12 #define min(a,b) ( (a) < (b) ? (a) : (b) )
14 #define USE_TIMERTICK 1
16 /******************************************************************************
17 ** The slave process **********************************************************
18 ******************************************************************************/
20 #undef SysBase
22 static void Slave( struct ExecBase* SysBase );
24 #if defined( __AROS__ )
26 #include <aros/asmcall.h>
28 AROS_UFH3(LONG, SlaveEntry,
29 AROS_UFHA(STRPTR, argPtr, A0),
30 AROS_UFHA(ULONG, argSize, D0),
31 AROS_UFHA(struct ExecBase *, SysBase, A6))
33 AROS_INTFUNC_INIT
34 Slave( SysBase );
35 return 0;
36 AROS_INTFUNC_EXIT
39 #else
41 void SlaveEntry(void)
43 struct ExecBase* SysBase = *((struct ExecBase**) 4);
45 Slave( SysBase );
48 #endif
51 #if USE_TIMERTICK
53 #include <hardware/intbits.h>
55 AROS_INTH1(AHITimerTickCode, struct Task *, task)
57 AROS_INTFUNC_INIT
59 Signal(task, SIGBREAKF_CTRL_F);
60 return 0;
62 AROS_INTFUNC_EXIT
65 static void SmallDelay(struct ExecBase *SysBase)
67 struct Interrupt i;
69 i.is_Code = (APTR)AHITimerTickCode;
70 i.is_Data = FindTask(0);
71 i.is_Node.ln_Name = "AROS AHI Driver Timer Tick Server";
72 i.is_Node.ln_Pri = 0;
73 i.is_Node.ln_Type = NT_INTERRUPT;
75 SetSignal(0, SIGBREAKF_CTRL_F);
76 AddIntServer(INTB_VERTB, &i);
77 Wait(SIGBREAKF_CTRL_F);
78 RemIntServer(INTB_VERTB, &i);
81 #endif
83 static void
84 Slave( struct ExecBase* SysBase )
86 struct AHIAudioCtrlDrv* AudioCtrl;
87 struct DriverBase* AHIsubBase;
88 struct AROSBase* AROSBase;
89 BOOL running;
90 ULONG signals;
92 int bytes_in_buffer = 0;
93 int offset_in_buffer = 0;
95 AudioCtrl = (struct AHIAudioCtrlDrv*) FindTask( NULL )->tc_UserData;
96 AHIsubBase = (struct DriverBase*) dd->ahisubbase;
97 AROSBase = (struct AROSBase*) AHIsubBase;
99 dd->slavesignal = AllocSignal( -1 );
101 if( dd->slavesignal != -1 )
103 // Everything set up. Tell Master we're alive and healthy.
105 Signal( (struct Task*) dd->mastertask,
106 1L << dd->mastersignal );
108 running = TRUE;
110 // The main playback loop follow
112 while( running )
114 signals = SetSignal(0L,0L);
116 // KPrintF("++++ arosdriver_after signal checking\n");
117 if( signals & ( SIGBREAKF_CTRL_C | (1L << dd->slavesignal) ) )
119 running = FALSE;
121 else
123 int skip_mix;
124 int bytes_avail;
126 // First Delay() until there is at least one fragment free
128 while( TRUE )
130 int frag_avail, frag_alloc, frag_size;
132 OSS_GetOutputInfo( &frag_avail, &frag_alloc, &frag_size,
133 &bytes_avail );
135 // KPrintF( "%ld fragments available, %ld alloced (%ld bytes each). %ld bytes total\n", frag_avail, frag_alloc, frag_size, bytes_avail );
137 if( frag_avail == 0 )
139 // This is actually quite a bit too long delay :-( For
140 // comparison, the SB Live/Audigy driver uses 1/1000 s
141 // polling ...
142 // KPrintF("Delay\n");
143 #if USE_TIMERTICK
144 SmallDelay(SysBase);
145 #else
146 Delay( 1 );
147 #endif
149 else
151 break;
155 skip_mix = 0;/*CallHookA( AudioCtrl->ahiac_PreTimerFunc,
156 (Object*) AudioCtrl, 0 );*/
158 while( bytes_avail > 0 )
160 // KPrintF( "%ld bytes in current buffer.\n", bytes_in_buffer );
162 if( bytes_in_buffer == 0 )
164 int skip = 0;
165 int offset = 0;
167 int samples = 0;
168 int bytes = 0;
170 int i;
172 WORD* src;
173 WORD* dst;
175 CallHookPkt( AudioCtrl->ahiac_PlayerFunc, AudioCtrl, NULL );
177 samples = AudioCtrl->ahiac_BuffSamples;
178 bytes = samples * 2; // one 16 bit sample is 2 bytes
180 switch( AudioCtrl->ahiac_BuffType )
182 case AHIST_M16S:
183 skip = 1;
184 offset = 0;
185 break;
187 case AHIST_M32S:
188 skip = 2;
189 offset = 1;
190 break;
192 case AHIST_S16S:
193 skip = 1;
194 offset = 0;
195 samples *= 2;
196 bytes *= 2;
197 break;
199 case AHIST_S32S:
200 skip = 2;
201 offset = 1;
202 samples *= 2;
203 bytes *= 2;
204 break;
207 bytes_in_buffer = bytes;
208 offset_in_buffer = 0;
210 if( ! skip_mix )
212 CallHookPkt( AudioCtrl->ahiac_MixerFunc, AudioCtrl,
213 dd->mixbuffer );
216 src = ((WORD*) dd->mixbuffer) + offset;
217 dst = dd->mixbuffer;
219 for( i = 0; i < samples; ++i )
221 *dst++ = *src;
222 src += skip;
225 // KPrintF( "Mixed %ld/%ld new bytes/samples\n", bytes, samples );
228 while( bytes_in_buffer > 0 &&
229 bytes_avail > 0 )
231 int written;
232 int counter = 0;
235 written = OSS_Write( dd->mixbuffer + offset_in_buffer,
236 min( bytes_in_buffer, bytes_avail ) );
237 if (counter > 10)
239 if (written < 0) written = 0;
240 break;
243 if (written < 0) KPrintF("OSS_Write returned %ld. counter %ld bytes_in_buffer %ld bytes_avail %ld\n",
244 written, counter, bytes_in_buffer, bytes_avail);
246 counter++;
248 } while (written < 0);
250 bytes_in_buffer -= written;
251 offset_in_buffer += written;
252 bytes_avail -= written;
254 // KPrintF( "Wrote %ld bytes (%ld bytes in buffer, offset=%ld, %ld bytes available in OSS buffers\n",
255 // written, bytes_in_buffer, offset_in_buffer, bytes_avail );
259 CallHookA( AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0 );
264 FreeSignal( dd->slavesignal );
265 dd->slavesignal = -1;
267 Forbid();
269 // Tell the Master we're dying
271 Signal( (struct Task*) dd->mastertask,
272 1L << dd->mastersignal );
274 dd->slavetask = NULL;
276 // Multitaking will resume when we are dead.