1 #include <aros/debug.h>
4 #include <devices/ahi.h>
5 #include <dos/dostags.h>
6 #include <exec/memory.h>
7 #include <libraries/ahi_sub.h>
8 #include <proto/ahi_sub.h>
9 #include <proto/exec.h>
10 #include <proto/dos.h>
11 #include <proto/utility.h>
16 #include "DriverData.h"
17 #include "alsa-bridge/alsa.h"
19 #define dd ((struct AlsaData*) AudioCtrl->ahiac_DriverData)
24 PROCGW( static, void, slaveentry
, SlaveEntry
);
26 static const LONG frequencies
[] =
28 8000, // ยต- and A-Law (telephone)
35 #define FREQUENCIES (sizeof frequencies / sizeof frequencies[ 0 ])
37 static const ULONG table_5bit
[] = {
72 static UWORD
LinToLog(ULONG vol
)
76 if (!vol
) return 0x20;
78 for (i
= 0; i
< 32; i
++)
80 if (vol
> table_5bit
[i
])
88 static ULONG
LogToLin(UWORD i
)
90 if (i
> 31) return 0x10000;
94 /******************************************************************************
95 ** AHIsub_AllocAudio **********************************************************
96 ******************************************************************************/
99 _AHIsub_AllocAudio( struct TagItem
* taglist
,
100 struct AHIAudioCtrlDrv
* AudioCtrl
,
101 struct DriverBase
* AHIsubBase
)
103 struct AlsaBase
* AlsaBase
= (struct AlsaBase
*) AHIsubBase
;
104 ULONG freq
= AudioCtrl
->ahiac_MixFreq
;
106 D(bug("[Alsa]: AllocAudio enter\n"));
108 AudioCtrl
->ahiac_DriverData
= AllocVec( sizeof( struct AlsaData
),
109 MEMF_CLEAR
| MEMF_PUBLIC
);
113 dd
->slavesignal
= -1;
114 dd
->mastersignal
= AllocSignal( -1 );
115 dd
->mastertask
= (struct Process
*) FindTask( NULL
);
116 dd
->ahisubbase
= AlsaBase
;
123 if( dd
->mastersignal
== -1 )
128 dd
->alsahandle
= ALSA_Open();
130 if (dd
->alsahandle
== NULL
)
132 bug("[Alsa]: Failed opening ALSA\n");
136 if (!ALSA_SetHWParams(dd
->alsahandle
, &freq
))
138 bug("[Alsa]: Failed setting ALSA hardware parameters\n");
139 ALSA_DropAndClose(dd
->alsahandle
);
140 dd
->alsahandle
= NULL
;
144 AudioCtrl
->ahiac_MixFreq
= freq
;
146 D(bug("[Alsa]: AllocAudio completed\n"));
148 return ( AHISF_KNOWSTEREO
| AHISF_MIXING
| AHISF_TIMING
);
152 /******************************************************************************
153 ** AHIsub_FreeAudio ***********************************************************
154 ******************************************************************************/
157 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv
* AudioCtrl
,
158 struct DriverBase
* AHIsubBase
)
160 if( AudioCtrl
->ahiac_DriverData
!= NULL
)
162 ALSA_DropAndClose(dd
->alsahandle
);
163 FreeSignal( dd
->mastersignal
);
164 FreeVec( AudioCtrl
->ahiac_DriverData
);
165 AudioCtrl
->ahiac_DriverData
= NULL
;
170 /******************************************************************************
171 ** AHIsub_Disable *************************************************************
172 ******************************************************************************/
175 _AHIsub_Disable( struct AHIAudioCtrlDrv
* AudioCtrl
,
176 struct DriverBase
* AHIsubBase
)
178 // V6 drivers do not have to preserve all registers
184 /******************************************************************************
185 ** AHIsub_Enable **************************************************************
186 ******************************************************************************/
189 _AHIsub_Enable( struct AHIAudioCtrlDrv
* AudioCtrl
,
190 struct DriverBase
* AHIsubBase
)
192 // V6 drivers do not have to preserve all registers
198 /******************************************************************************
199 ** AHIsub_Start ***************************************************************
200 ******************************************************************************/
203 _AHIsub_Start( ULONG flags
,
204 struct AHIAudioCtrlDrv
* AudioCtrl
,
205 struct DriverBase
* AHIsubBase
)
207 struct AlsaBase
* AlsaBase
= (struct AlsaBase
*) AHIsubBase
;
209 AHIsub_Stop( flags
, AudioCtrl
);
211 if(flags
& AHISF_PLAY
)
213 struct TagItem proctags
[] =
215 { NP_Entry
, (IPTR
) &slaveentry
},
216 { NP_Name
, (IPTR
) LibName
},
217 { NP_Priority
, 127 },
221 dd
->mixbuffer
= AllocVec( AudioCtrl
->ahiac_BuffSize
,
222 MEMF_ANY
| MEMF_PUBLIC
);
224 if( dd
->mixbuffer
== NULL
) return AHIE_NOMEM
;
226 D(bug("[Alsa]: AHIsub_Start\n"));
230 dd
->slavetask
= CreateNewProc( proctags
);
232 if( dd
->slavetask
!= NULL
)
234 dd
->slavetask
->pr_Task
.tc_UserData
= AudioCtrl
;
239 if( dd
->slavetask
!= NULL
)
241 Wait( 1L << dd
->mastersignal
); // Wait for slave to come alive
243 if( dd
->slavetask
== NULL
) // Is slave alive or dead?
250 return AHIE_NOMEM
; // Well, out of memory or whatever...
254 if( flags
& AHISF_RECORD
)
263 /******************************************************************************
264 ** AHIsub_Update **************************************************************
265 ******************************************************************************/
268 _AHIsub_Update( ULONG flags
,
269 struct AHIAudioCtrlDrv
* AudioCtrl
,
270 struct DriverBase
* AHIsubBase
)
276 /******************************************************************************
277 ** AHIsub_Stop ****************************************************************
278 ******************************************************************************/
281 _AHIsub_Stop( ULONG flags
,
282 struct AHIAudioCtrlDrv
* AudioCtrl
,
283 struct DriverBase
* AHIsubBase
)
285 if( flags
& AHISF_PLAY
)
287 if( dd
->slavetask
!= NULL
)
289 if( dd
->slavesignal
!= -1 )
291 Signal( (struct Task
*) dd
->slavetask
,
292 1L << dd
->slavesignal
); // Kill him!
293 D(bug("[Alsa]: AHIsub_Stop\n"));
296 Wait( 1L << dd
->mastersignal
); // Wait for slave to die
299 FreeVec( dd
->mixbuffer
);
300 dd
->mixbuffer
= NULL
;
303 if(flags
& AHISF_RECORD
)
310 /******************************************************************************
311 ** AHIsub_GetAttr *************************************************************
312 ******************************************************************************/
315 _AHIsub_GetAttr( ULONG attribute
,
318 struct TagItem
* taglist
,
319 struct AHIAudioCtrlDrv
* AudioCtrl
,
320 struct DriverBase
* AHIsubBase
)
322 struct AlsaBase
* AlsaBase
= (struct AlsaBase
*) AHIsubBase
;
330 case AHIDB_Frequencies
:
333 case AHIDB_Frequency
: // Index->Frequency
334 return (LONG
) frequencies
[ argument
];
336 case AHIDB_Index
: // Frequency->Index
337 if( argument
<= frequencies
[ 0 ] )
342 if( argument
>= frequencies
[ FREQUENCIES
- 1 ] )
344 return FREQUENCIES
- 1;
347 for( i
= 1; i
< FREQUENCIES
; i
++ )
349 if( frequencies
[ i
] > argument
)
351 if( ( argument
- frequencies
[ i
- 1 ] ) <
352 ( frequencies
[ i
] - argument
) )
363 return 0; // Will not happen
366 return (IPTR
) "Krzysztof Smiechowicz";
368 case AHIDB_Copyright
:
372 return (IPTR
) LibIDString
;
384 return (IPTR
) "Alsa"; // We have only one "output"!
386 case AHIDB_MinOutputVolume
:
389 case AHIDB_MaxOutputVolume
:
390 if (AlsaBase
->al_MixerElem
)
401 /******************************************************************************
402 ** AHIsub_HardwareControl *****************************************************
403 ******************************************************************************/
406 _AHIsub_HardwareControl( ULONG attribute
,
408 struct AHIAudioCtrlDrv
* AudioCtrl
,
409 struct DriverBase
* AHIsubBase
)
411 struct AlsaBase
* AlsaBase
= (struct AlsaBase
*) AHIsubBase
;
415 case AHIC_OutputVolume
:
416 if (AlsaBase
->al_MixerElem
)
418 LONG val
= (0x20 - LinToLog(argument
)) * AlsaBase
->al_MaxVolume
/ 0x20;
419 ALSA_MixerSetVolume(AlsaBase
->al_MixerElem
, (LONG
)val
);
424 case AHIC_OutputVolume_Query
:
425 if (AlsaBase
->al_MixerElem
)
427 LONG val
= ALSA_MixerGetVolume(AlsaBase
->al_MixerElem
);
428 val
= val
* 0x20 / AlsaBase
->al_MaxVolume
;
429 return LogToLin(0x20 - val
);