Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / AHI / Drivers / AROS / aros-main.c
blob5e0c655ae29d6d125c5974a233469ca0d234b498
2 /*
3 * This is a driver for hosted AROS, using oss.library.
4 */
6 #include <config.h>
8 #include <devices/ahi.h>
9 #include <dos/dostags.h>
10 #include <exec/memory.h>
11 #include <libraries/ahi_sub.h>
12 #include <proto/ahi_sub.h>
13 #include <proto/exec.h>
14 #include <proto/dos.h>
15 #include <proto/utility.h>
17 #include <stddef.h>
19 #include "library.h"
20 #include "DriverData.h"
22 void
23 SlaveEntry( void );
25 PROCGW( static, void, slaveentry, SlaveEntry );
28 /* Since I have no idea what frequencies OSS supports, and there
29 * doesn't seem to be an easy way to find out either, I've just
30 * selected a few common frequencies that are likely to work.
33 static const LONG frequencies[] =
35 8000, // ยต- and A-Law (telephone)
36 11025, // CD/4
37 22050, // CD/2
38 44100, // CD
39 48000, // DAT
42 #define FREQUENCIES (sizeof frequencies / sizeof frequencies[ 0 ])
44 /******************************************************************************
45 ** AHIsub_AllocAudio **********************************************************
46 ******************************************************************************/
48 ULONG
49 _AHIsub_AllocAudio( struct TagItem* taglist,
50 struct AHIAudioCtrlDrv* AudioCtrl,
51 struct DriverBase* AHIsubBase )
53 struct AROSBase* AROSBase = (struct AROSBase*) AHIsubBase;
54 int freq = AudioCtrl->ahiac_MixFreq;
56 AudioCtrl->ahiac_DriverData = AllocVec( sizeof( struct AROSData ),
57 MEMF_CLEAR | MEMF_PUBLIC );
59 #define dd ((struct AROSData*) AudioCtrl->ahiac_DriverData)
61 if( dd != NULL )
63 dd->slavesignal = -1;
64 dd->mastersignal = AllocSignal( -1 );
65 dd->mastertask = (struct Process*) FindTask( NULL );
66 dd->ahisubbase = AROSBase;
68 else
70 return AHISF_ERROR;
73 if( dd->mastersignal == -1 )
75 return AHISF_ERROR;
78 if( ! OSS_Open( "/dev/dsp", FALSE, TRUE, FALSE ) )
80 return AHISF_ERROR;
83 // 32 fragments times 256 bytes each
85 if( ! OSS_SetFragmentSize( 32, 8 ) )
87 Req( "OSS device does not support a fragment size of 1024." );
88 return AHIE_UNKNOWN;
91 if( ! OSS_FormatSupported_S16LE() || ! OSS_SetFormat_S16LE() )
93 Req( "OSS device does not support 16 bit little endian samples!" );
94 return AHISF_ERROR;
97 if( ! OSS_SetWriteRate( freq, &freq ) )
99 Req( "OSS device does not support the requested frequency." );
100 return AHISF_ERROR;
103 AudioCtrl->ahiac_MixFreq = freq;
105 return ( AHISF_KNOWHIFI |
106 AHISF_KNOWSTEREO |
107 AHISF_MIXING |
108 AHISF_TIMING );
112 /******************************************************************************
113 ** AHIsub_FreeAudio ***********************************************************
114 ******************************************************************************/
116 void
117 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv* AudioCtrl,
118 struct DriverBase* AHIsubBase )
120 struct AROSBase* AROSBase = (struct AROSBase*) AHIsubBase;
122 if( AudioCtrl->ahiac_DriverData != NULL )
124 OSS_Reset();
125 OSS_Close();
126 FreeSignal( dd->mastersignal );
127 FreeVec( AudioCtrl->ahiac_DriverData );
128 AudioCtrl->ahiac_DriverData = NULL;
133 /******************************************************************************
134 ** AHIsub_Disable *************************************************************
135 ******************************************************************************/
137 void
138 _AHIsub_Disable( struct AHIAudioCtrlDrv* AudioCtrl,
139 struct DriverBase* AHIsubBase )
141 struct AROSBase* AROSBase = (struct AROSBase*) AHIsubBase;
143 // V6 drivers do not have to preserve all registers
145 Forbid();
149 /******************************************************************************
150 ** AHIsub_Enable **************************************************************
151 ******************************************************************************/
153 void
154 _AHIsub_Enable( struct AHIAudioCtrlDrv* AudioCtrl,
155 struct DriverBase* AHIsubBase )
157 struct AROSBase* AROSBase = (struct AROSBase*) AHIsubBase;
159 // V6 drivers do not have to preserve all registers
161 Permit();
165 /******************************************************************************
166 ** AHIsub_Start ***************************************************************
167 ******************************************************************************/
169 ULONG
170 _AHIsub_Start( ULONG flags,
171 struct AHIAudioCtrlDrv* AudioCtrl,
172 struct DriverBase* AHIsubBase )
174 struct AROSBase* AROSBase = (struct AROSBase*) AHIsubBase;
176 AHIsub_Stop( flags, AudioCtrl );
178 if(flags & AHISF_PLAY)
180 int freq = AudioCtrl->ahiac_MixFreq;
182 struct TagItem proctags[] =
184 { NP_Entry, (IPTR) &slaveentry },
185 { NP_Name, (IPTR) LibName },
186 { NP_Priority, 127 },
187 { TAG_DONE, 0 }
191 dd->mixbuffer = AllocVec( AudioCtrl->ahiac_BuffSize,
192 MEMF_ANY | MEMF_PUBLIC );
194 if( dd->mixbuffer == NULL ) return AHIE_NOMEM;
196 Forbid();
198 dd->slavetask = CreateNewProc( proctags );
200 if( dd->slavetask != NULL )
202 dd->slavetask->pr_Task.tc_UserData = AudioCtrl;
205 Permit();
207 if( dd->slavetask != NULL )
209 Wait( 1L << dd->mastersignal ); // Wait for slave to come alive
211 if( dd->slavetask == NULL ) // Is slave alive or dead?
213 return AHIE_UNKNOWN;
216 else
218 return AHIE_NOMEM; // Well, out of memory or whatever...
221 // Since OSS kind of sucks, we have to close and reopen it here ...
223 Forbid(); /* To prevent slave task from calling OSS_GetOutputInfo
224 inbetween OSS_Open/OSS_Close */
225 OSS_Close();
227 if( ! OSS_Open( "/dev/dsp", FALSE, TRUE, FALSE ) )
229 Req( "OSS device would not reopen." );
230 return AHIE_UNKNOWN;
232 Permit();
234 // 32 fragments times 256 bytes each
236 if( ! OSS_SetFragmentSize( 32, 8 ) )
238 Req( "OSS device does not support a fragment size of 1024." );
239 return AHIE_UNKNOWN;
242 switch( AudioCtrl->ahiac_BuffType )
244 case AHIST_M16S:
245 case AHIST_M32S:
246 if( ! OSS_SetMono() )
248 Req( "OSS device does not support mono samples." );
249 return AHIE_UNKNOWN;
251 break;
253 case AHIST_S16S:
254 case AHIST_S32S:
255 if( ! OSS_SetStereo() )
257 Req( "OSS device does not support stereo samples." );
258 return AHIE_UNKNOWN;
260 break;
262 default:
263 Req( "Unknown sample format requested: %08lx",
264 AudioCtrl->ahiac_BuffType );
265 return AHIE_UNKNOWN;
268 if( ! OSS_SetFormat_S16LE() )
270 Req( "OSS device does not support 16 bit little endian samples!" );
271 return AHIE_UNKNOWN;
274 if( ! OSS_SetWriteRate( freq, &freq ) )
276 Req( "OSS device does not support the requested frequency." );
277 return AHIE_UNKNOWN;
281 if( flags & AHISF_RECORD )
283 return AHIE_UNKNOWN;
286 return AHIE_OK;
290 /******************************************************************************
291 ** AHIsub_Update **************************************************************
292 ******************************************************************************/
294 void
295 _AHIsub_Update( ULONG flags,
296 struct AHIAudioCtrlDrv* AudioCtrl,
297 struct DriverBase* AHIsubBase )
299 struct AROSBase* AROSBase = (struct AROSBase*) AHIsubBase;
301 // Empty function
305 /******************************************************************************
306 ** AHIsub_Stop ****************************************************************
307 ******************************************************************************/
309 void
310 _AHIsub_Stop( ULONG flags,
311 struct AHIAudioCtrlDrv* AudioCtrl,
312 struct DriverBase* AHIsubBase )
314 struct AROSBase* AROSBase = (struct AROSBase*) AHIsubBase;
316 if( flags & AHISF_PLAY )
318 if( dd->slavetask != NULL )
320 if( dd->slavesignal != -1 )
322 Signal( (struct Task*) dd->slavetask,
323 1L << dd->slavesignal ); // Kill him!
326 Wait( 1L << dd->mastersignal ); // Wait for slave to die
329 FreeVec( dd->mixbuffer );
330 dd->mixbuffer = NULL;
333 if(flags & AHISF_RECORD)
335 // Do nothing
340 /******************************************************************************
341 ** AHIsub_GetAttr *************************************************************
342 ******************************************************************************/
344 IPTR
345 _AHIsub_GetAttr( ULONG attribute,
346 LONG argument,
347 IPTR def,
348 struct TagItem* taglist,
349 struct AHIAudioCtrlDrv* AudioCtrl,
350 struct DriverBase* AHIsubBase )
352 struct AROSBase* AROSBase = (struct AROSBase*) AHIsubBase;
353 size_t i;
355 switch( attribute )
357 case AHIDB_Bits:
358 return 16;
360 case AHIDB_Frequencies:
361 return FREQUENCIES;
363 case AHIDB_Frequency: // Index->Frequency
364 return (LONG) frequencies[ argument ];
366 case AHIDB_Index: // Frequency->Index
367 if( argument <= frequencies[ 0 ] )
369 return 0;
372 if( argument >= frequencies[ FREQUENCIES - 1 ] )
374 return FREQUENCIES - 1;
377 for( i = 1; i < FREQUENCIES; i++ )
379 if( frequencies[ i ] > argument )
381 if( ( argument - frequencies[ i - 1 ] ) <
382 ( frequencies[ i ] - argument ) )
384 return i-1;
386 else
388 return i;
393 return 0; // Will not happen
395 case AHIDB_Author:
396 return (IPTR) "Martin 'Leviticus' Blom";
398 case AHIDB_Copyright:
399 return (IPTR) "Public Domain";
401 case AHIDB_Version:
402 return (IPTR) LibIDString;
404 case AHIDB_Record:
405 return FALSE;
407 case AHIDB_Realtime:
408 return TRUE;
410 case AHIDB_Outputs:
411 return 1;
413 case AHIDB_Output:
414 return (IPTR) "AROS"; // We have only one "output"!
416 default:
417 return def;
422 /******************************************************************************
423 ** AHIsub_HardwareControl *****************************************************
424 ******************************************************************************/
426 ULONG
427 _AHIsub_HardwareControl( ULONG attribute,
428 LONG argument,
429 struct AHIAudioCtrlDrv* AudioCtrl,
430 struct DriverBase* AHIsubBase )
432 struct AROSBase* AROSBase = (struct AROSBase*) AHIsubBase;
434 return 0;