alsa.audio: implement skeleton playback
[AROS.git] / workbench / devs / AHI / Drivers / Alsa / alsa-main.c
blob072e3bcb2814010649043d594423a9f3bfef7770
1 #include <config.h>
3 #include <devices/ahi.h>
4 #include <dos/dostags.h>
5 #include <exec/memory.h>
6 #include <libraries/ahi_sub.h>
7 #include <proto/ahi_sub.h>
8 #include <proto/exec.h>
9 #include <proto/dos.h>
10 #include <proto/utility.h>
12 #include <stddef.h>
14 #include "library.h"
15 #include "DriverData.h"
17 #define dd ((struct AlsaData*) AudioCtrl->ahiac_DriverData)
19 void
20 SlaveEntry( void );
22 PROCGW( static, void, slaveentry, SlaveEntry );
25 //TODO
26 /* There is probably no reason to support all these frequencies. If,
27 * for example, your hardware is locked at 48 kHz, it's ok to only
28 * present one single mixing/recording frequency to the user. If your
29 * hardware has internal resamples and accept any frequency, select a
30 * few common ones.
33 static const LONG frequencies[] =
35 5513, // CD/8
36 8000, // ยต- and A-Law (telephone)
37 9600, // DAT/5
38 10000, // VHS monaural track
39 11025, // CD/4
40 12000, // DAT/4
41 14700, // CD/3
42 16000, // DAT/3, FM/2
43 17640, // CD/2.5
44 18900,
45 19200, // DAT/2.5
46 20000, // VHS Hi-Fi/Video track
47 22050, // CD/2
48 24000, // DAT/2
49 27429, // Highest Paula/OCS frequency
50 29400, // CD/1.5
51 31968, // NTSC FM 2-3 pull-down
52 32000, // DAT/1.5
53 32032, // NTSC FM 2-3 pull-up
54 33075,
55 37800,
56 44056, // NTSC CD 2-3 pull-down
57 44100, // CD
58 44144, // NTSC CD 2-3 pull-up
59 47952, // NTSC DAT 2-3 pull-down
60 48000, // DAT
61 48048, // NTSC DAT 2-3 pull-up
62 88200, // CD*2
63 96000 // DAT*2
66 #define FREQUENCIES (sizeof frequencies / sizeof frequencies[ 0 ])
68 /******************************************************************************
69 ** AHIsub_AllocAudio **********************************************************
70 ******************************************************************************/
72 ULONG
73 _AHIsub_AllocAudio( struct TagItem* taglist,
74 struct AHIAudioCtrlDrv* AudioCtrl,
75 struct DriverBase* AHIsubBase )
77 struct AlsaBase* AlsaBase = (struct AlsaBase*) AHIsubBase;
78 ULONG freq = AudioCtrl->ahiac_MixFreq;
80 AudioCtrl->ahiac_DriverData = AllocVec( sizeof( struct AlsaData ),
81 MEMF_CLEAR | MEMF_PUBLIC );
83 if( dd != NULL )
85 dd->slavesignal = -1;
86 dd->mastersignal = AllocSignal( -1 );
87 dd->mastertask = (struct Process*) FindTask( NULL );
88 dd->ahisubbase = AlsaBase;
90 else
92 return AHISF_ERROR;
95 if( dd->mastersignal == -1 )
97 return AHISF_ERROR;
100 dd->alsahandle = ALSA_Open();
102 if (dd->alsahandle == NULL)
104 return AHISF_ERROR;
107 if (!ALSA_SetHWParams(dd->alsahandle, &freq))
109 ALSA_Close(dd->alsahandle);
110 dd->alsahandle = NULL;
111 return AHISF_ERROR;
114 AudioCtrl->ahiac_MixFreq = freq;
116 return ( AHISF_KNOWSTEREO | AHISF_MIXING | AHISF_TIMING );
120 /******************************************************************************
121 ** AHIsub_FreeAudio ***********************************************************
122 ******************************************************************************/
124 void
125 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv* AudioCtrl,
126 struct DriverBase* AHIsubBase )
128 struct AlsaBase* AlsaBase = (struct AlsaBase*) AHIsubBase;
130 if( AudioCtrl->ahiac_DriverData != NULL )
132 ALSA_Close(dd->alsahandle);
133 FreeSignal( dd->mastersignal );
134 FreeVec( AudioCtrl->ahiac_DriverData );
135 AudioCtrl->ahiac_DriverData = NULL;
140 /******************************************************************************
141 ** AHIsub_Disable *************************************************************
142 ******************************************************************************/
144 void
145 _AHIsub_Disable( struct AHIAudioCtrlDrv* AudioCtrl,
146 struct DriverBase* AHIsubBase )
148 struct AlsaBase* AlsaBase = (struct AlsaBase*) AHIsubBase;
150 // V6 drivers do not have to preserve all registers
152 Forbid();
156 /******************************************************************************
157 ** AHIsub_Enable **************************************************************
158 ******************************************************************************/
160 void
161 _AHIsub_Enable( struct AHIAudioCtrlDrv* AudioCtrl,
162 struct DriverBase* AHIsubBase )
164 struct AlsaBase* AlsaBase = (struct AlsaBase*) AHIsubBase;
166 // V6 drivers do not have to preserve all registers
168 Permit();
172 /******************************************************************************
173 ** AHIsub_Start ***************************************************************
174 ******************************************************************************/
176 ULONG
177 _AHIsub_Start( ULONG flags,
178 struct AHIAudioCtrlDrv* AudioCtrl,
179 struct DriverBase* AHIsubBase )
181 struct AlsaBase* AlsaBase = (struct AlsaBase*) AHIsubBase;
183 AHIsub_Stop( flags, AudioCtrl );
185 if(flags & AHISF_PLAY)
187 struct TagItem proctags[] =
189 { NP_Entry, (IPTR) &slaveentry },
190 { NP_Name, (IPTR) LibName },
191 { NP_Priority, -1 },
192 { TAG_DONE, 0 }
195 dd->mixbuffer = AllocVec( AudioCtrl->ahiac_BuffSize,
196 MEMF_ANY | MEMF_PUBLIC );
198 if( dd->mixbuffer == NULL ) return AHIE_NOMEM;
200 Forbid();
202 dd->slavetask = CreateNewProc( proctags );
204 if( dd->slavetask != NULL )
206 dd->slavetask->pr_Task.tc_UserData = AudioCtrl;
209 Permit();
211 if( dd->slavetask != NULL )
213 Wait( 1L << dd->mastersignal ); // Wait for slave to come alive
215 if( dd->slavetask == NULL ) // Is slave alive or dead?
217 return AHIE_UNKNOWN;
220 else
222 return AHIE_NOMEM; // Well, out of memory or whatever...
226 if( flags & AHISF_RECORD )
228 return AHIE_UNKNOWN;
231 return AHIE_OK;
235 /******************************************************************************
236 ** AHIsub_Update **************************************************************
237 ******************************************************************************/
239 void
240 _AHIsub_Update( ULONG flags,
241 struct AHIAudioCtrlDrv* AudioCtrl,
242 struct DriverBase* AHIsubBase )
244 struct AlsaBase* AlsaBase = (struct AlsaBase*) AHIsubBase;
246 // Empty function
250 /******************************************************************************
251 ** AHIsub_Stop ****************************************************************
252 ******************************************************************************/
254 void
255 _AHIsub_Stop( ULONG flags,
256 struct AHIAudioCtrlDrv* AudioCtrl,
257 struct DriverBase* AHIsubBase )
259 struct AlsaBase* AlsaBase = (struct AlsaBase*) AHIsubBase;
261 if( flags & AHISF_PLAY )
263 if( dd->slavetask != NULL )
265 if( dd->slavesignal != -1 )
267 Signal( (struct Task*) dd->slavetask,
268 1L << dd->slavesignal ); // Kill him!
271 Wait( 1L << dd->mastersignal ); // Wait for slave to die
274 FreeVec( dd->mixbuffer );
275 dd->mixbuffer = NULL;
278 if(flags & AHISF_RECORD)
280 // Do nothing
285 /******************************************************************************
286 ** AHIsub_GetAttr *************************************************************
287 ******************************************************************************/
289 IPTR
290 _AHIsub_GetAttr( ULONG attribute,
291 LONG argument,
292 IPTR def,
293 struct TagItem* taglist,
294 struct AHIAudioCtrlDrv* AudioCtrl,
295 struct DriverBase* AHIsubBase )
297 struct AlsaBase* AlsaBase = (struct AlsaBase*) AHIsubBase;
298 size_t i;
300 switch( attribute )
302 case AHIDB_Bits:
303 return 32;
305 case AHIDB_Frequencies:
306 return FREQUENCIES;
308 case AHIDB_Frequency: // Index->Frequency
309 return (LONG) frequencies[ argument ];
311 case AHIDB_Index: // Frequency->Index
312 if( argument <= frequencies[ 0 ] )
314 return 0;
317 if( argument >= frequencies[ FREQUENCIES - 1 ] )
319 return FREQUENCIES - 1;
322 for( i = 1; i < FREQUENCIES; i++ )
324 if( frequencies[ i ] > argument )
326 if( ( argument - frequencies[ i - 1 ] ) <
327 ( frequencies[ i ] - argument ) )
329 return i-1;
331 else
333 return i;
338 return 0; // Will not happen
340 case AHIDB_Author:
341 return (IPTR) "Krzysztof Smiechowicz";
343 case AHIDB_Copyright:
344 return (IPTR) "APL";
346 case AHIDB_Version:
347 return (IPTR) LibIDString;
349 case AHIDB_Record:
350 return FALSE;
352 case AHIDB_Realtime:
353 return TRUE;
355 case AHIDB_Outputs:
356 return 1;
358 case AHIDB_Output:
359 return (IPTR) "Alsa"; // We have only one "output"!
361 default:
362 return def;
367 /******************************************************************************
368 ** AHIsub_HardwareControl *****************************************************
369 ******************************************************************************/
371 ULONG
372 _AHIsub_HardwareControl( ULONG attribute,
373 LONG argument,
374 struct AHIAudioCtrlDrv* AudioCtrl,
375 struct DriverBase* AHIsubBase )
377 struct AlsaBase* AlsaBase = (struct AlsaBase*) AHIsubBase;
379 return 0;