4 #include <devices/ahi.h>
5 #include <libraries/ahi_sub.h>
7 #include "DriverData.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 ******************************************************************************/
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
))
43 struct ExecBase
* SysBase
= *((struct ExecBase
**) 4);
53 #include <hardware/intbits.h>
55 AROS_INTH1(AHITimerTickCode
, struct Task
*, task
)
59 Signal(task
, SIGBREAKF_CTRL_F
);
65 static void SmallDelay(struct ExecBase
*SysBase
)
69 i
.is_Code
= (APTR
)AHITimerTickCode
;
70 i
.is_Data
= FindTask(0);
71 i
.is_Node
.ln_Name
= "AROS AHI Driver Timer Tick Server";
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
);
84 Slave( struct ExecBase
* SysBase
)
86 struct AHIAudioCtrlDrv
* AudioCtrl
;
87 struct DriverBase
* AHIsubBase
;
88 struct AROSBase
* AROSBase
;
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
);
110 // The main playback loop follow
114 signals
= SetSignal(0L,0L);
116 // KPrintF("++++ arosdriver_after signal checking\n");
117 if( signals
& ( SIGBREAKF_CTRL_C
| (1L << dd
->slavesignal
) ) )
126 // First Delay() until there is at least one fragment free
130 int frag_avail
, frag_alloc
, frag_size
;
132 OSS_GetOutputInfo( &frag_avail
, &frag_alloc
, &frag_size
,
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
142 // KPrintF("Delay\n");
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 )
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
)
207 bytes_in_buffer
= bytes
;
208 offset_in_buffer
= 0;
212 CallHookPkt( AudioCtrl
->ahiac_MixerFunc
, AudioCtrl
,
216 src
= ((WORD
*) dd
->mixbuffer
) + offset
;
219 for( i
= 0; i
< samples
; ++i
)
225 // KPrintF( "Mixed %ld/%ld new bytes/samples\n", bytes, samples );
228 while( bytes_in_buffer
> 0 &&
235 written
= OSS_Write( dd
->mixbuffer
+ offset_in_buffer
,
236 min( bytes_in_buffer
, bytes_avail
) );
239 if (written
< 0) written
= 0;
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
);
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;
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.