source: cmedia/trunk/Vsd/AudioIF/vsdini.c@ 354

Last change on this file since 354 was 354, checked in by stevenhl, 17 years ago

Import untested baseline cmedia sources, work products and binaries
Binaries and work products should be deleted from repository.
once new builds are verified to work.

File size: 24.8 KB
Line 
1/************************* START OF SPECIinCATIONS ***
2*
3* SOURCE FILE NAME: VSDINI.C
4*
5* DESCRIPTIVE NAME: Ini file and resource file manipulator
6*
7* COPYRIGHT: IBM Confidential
8* Copyright (c) IBM Corporation 1991
9* All Rights Reserved
10*
11* STATUS: OS/2 Release 2.x
12*
13* FUNCTION: This source module contains routines to retrieve information
14* from the VSD resource file and MMPM2.INI file.
15*
16* ISV can manipulate their own ini files here.
17*
18* Notes: the following concepts are illustrated.
19*
20* 1. How to read in a resource dll and retrieve VSD specific info.
21* (SetupResourceTable)
22* 2. How to determine the amount of resource a particular device
23* consumes (GetClassInformation)
24*
25*
26* Change History:
27* DATE DEVELOPER CHANGE DESCRIPTION
28* 12/07/92 Linden deCarmo File created
29* 05/24/94 Linden deCarmo Moved CAPIOCTL to VSDIOCTL
30* 06/29/95 Linden deCarmo Cleanup Hardware mixer support (15552).
31*
32************************** END OF SPECIFICATIONS **************************/
33
34#define INCL_NOPMAPI
35#define INCL_DOS
36#define INCL_ERRORS
37#define INCL_AUDIO_VSD
38#include <os2.h>
39#include <os2me.h>
40#include <mcd.h>
41#include <audio.h>
42#include <stdio.h>
43#include <string.h>
44#include <hhpheap.h>
45#include <stdlib.h>
46
47#include <vsdcmds.h>
48#include <vsdaud.h>
49#include <mmdsload.h>
50
51// 15552
52#ifndef INCL_MM_WPOS
53RIFFTABLE RiffTable[NUMMODES] =
54 {
55 {DATATYPE_WAVEFORM, PCM},
56 {DATATYPE_ADPCM_AVC, ADPCM},
57 {DATATYPE_MULAW, MU_LAW},
58 {DATATYPE_ALAW, A_LAW},
59 {DATATYPE_MIDI, MIDI},
60 {DATATYPE_SPV2, SPV2},
61 {DATATYPE_CDXA_AUDIO, ADPCMXA},
62 {DATATYPE_CT_ADPCM, CT_ADPCM}
63 };
64
65
66
67/************************** START OF SPECIFICATIONS ************************
68* *
69* SUBROUTINE NAME: SetupResourceTable *
70* *
71* DESCRIPTIVE NAME: Retrives VSD Resource information obtained from ini *
72* *
73* FUNCTION: This function loads a resource dll (specified in the device *
74* specific parameters of the amp-mix device). It then parses *
75* the resource dll and sets up appropriate instance values. *
76* *
77* If you are writing your own VSD, you DO NOT have to utilize *
78* these ini functions, however, you are welcome to utilize the *
79* same functionality. *
80* INPUT: *
81* *
82* OUTPUT: VSDERR_SUCESS if there was a match *
83* An MCI error otherwise *
84* *
85* SIDE EFFECTS: *
86* *
87*************************** END OF SPECIFICATIONS **************************/
88
89
90
91ULONG SetupResourceTable( PVSD_INSTANCE pInstance )
92
93{
94ULONG rc;
95PULONG pulResourceWalker; // used to walk through the resource file
96
97
98HMODULE hModule; // module handle of dll where the resource
99 // stored.
100
101//ULONG ulOffset =1;
102
103 if (!strcmp(pInstance->pResourceDLL, "AUDIOIF") || //@LP01
104 !pInstance->pResourceDLL[0])
105 rc = MM_DosLoadModule( NULL, 0, "MMPM", &hModule ); //@LP01
106 else if (!pInstance->pResourceDLL[0])
107 rc = MM_DosLoadModule( NULL, 0, "AUDIOIF", &hModule ); //@LP01
108 else
109 rc = 1;
110
111 if ( rc ) //@LP01
112 rc = MM_DosLoadModule( NULL, 0, pInstance->pResourceDLL, &hModule );
113
114// rc = DosLoadModule( NULL, 0, pInstance->pResourceDLL, &hModule );
115
116 if ( rc )
117 return ( rc );
118
119 /*-----------------------------------
120 * It the device specific parameters of
121 * the amp, the user specified which
122 * card to use by the resource id. The
123 * amp placed this info in the instance.
124 --------------------------------------*/
125
126 rc = DosGetResource( hModule,
127 RT_RCDATA,
128 pInstance->ulResourceID,
129 &pInstance->pAudioModeData );
130
131 if ( rc )
132 return ( rc );
133
134 /*******************************************************
135 * Set up product information pointer--this must be the
136 * first item in the resource table.
137 ********************************************************/
138
139 pInstance->pProdInfo = (PSZ ) pInstance->pAudioModeData;
140
141 pulResourceWalker = (PULONG ) (pInstance->pProdInfo +
142 strlen(pInstance->pProdInfo) + 1);
143
144 /*******************************************************
145 * Set up device idnformation pointer--this follows right
146 * after the product information string.
147 ********************************************************/
148
149
150 pInstance->ulDeviceID = *(pulResourceWalker)++;
151
152
153 /*******************************************************
154 * Determine if the manufacturer has any RIFF->AUDIODD maps
155 * in the resource table (this mapping is necessary since
156 * RIFF format tags do not match with AUDIODD modes.
157 ********************************************************/
158
159 pInstance->ulNumMappingRows = *(pulResourceWalker)++;
160
161 if ( pInstance->ulNumMappingRows )
162 {
163 pInstance->pMapTable = ( RIFFTABLE * ) pulResourceWalker;
164 pulResourceWalker += ( 2 * pInstance->ulNumMappingRows) ;
165 }
166
167 /*******************************************************
168 * Access the data type table. This contains a description
169 * of the data types this device supports.
170 ********************************************************/
171
172
173 pInstance->ulNumDataTypes = *( pulResourceWalker)++;
174 pInstance->pDataTypeTable = ( PVOID ) pulResourceWalker;
175
176 return ( VSDERR_SUCCESS );
177
178} /* SetUpResourceTable */
179
180#endif
181
182// 15552
183
184
185
186
187
188/************************** START OF SPECIFICATIONS ************************
189* *
190* SUBROUTINE NAME: GetClassInformation *
191* *
192* DESCRIPTIVE NAME: Retrives VSD Resource information obtained from ini *
193* *
194* FUNCTION: This function examines an instance to see if a match can be *
195* found between what the device currently supports and what *
196* the user has requested. If a match cannot be found, then the *
197* best guess (best fit) will be returned. *
198* *
199* If you are writing your own VSD, you DO NOT have to utilize *
200* these ini functions, however, you are welcome to utilize the *
201* same functionality. *
202* *
203* INPUT: ulPort *
204* *
205* OUTPUT: VSDERR_SUCESS if there was a match *
206* An MCI error otherwise *
207* *
208* SIDE EFFECTS: *
209* *
210*************************** END OF SPECIFICATIONS **************************/
211
212
213
214
215ULONG GetClassInformation( PVSD_INSTANCE pInstance )
216
217{
218ULONG ulLoop;
219
220ULONG rc = VSDERR_SUCCESS;
221
222SHORT sModeBackup = pInstance->sMode;
223BOOL fContinousRate = FALSE;
224
225// these variables will be used to return an intelligent error
226
227BOOL fFoundBits = FALSE; // found bitspersample
228//BOOL fFoundOperation = FALSE; // found operation (either play or record)
229BOOL fFoundSamples = FALSE; // Found sampling rate
230BOOL fFoundChannels = FALSE; // Found channels
231BOOL fFoundTag = FALSE; // Found format tag
232
233VSD_BEST_FIT vsdBestFit; /* VSD best fit structure */
234
235CLASS_DATA *pDataTypeTable = ( CLASS_DATA * ) pInstance->pDataTypeTable;
236
237 if ( pInstance->fDriverCaps )
238 {
239
240 rc = CapIOCTL( pInstance);
241 if (!rc)
242 {
243 pInstance->ulHardwareMode = pInstance->ulDataType;
244 }
245 return ( rc );
246 }
247 else
248 {
249
250// 15552
251#ifndef INCL_MM_WPOS
252 /*---------------------------------------------------------
253 * Work around problems created by Microsoft (boy isn't this
254 * a common theme). They redefined mulaw and alaw. Map
255 * these to the defines we know about already.
256 *----------------------------------------------------------*/
257 if ( pInstance->sMode == DATATYPE_RIFF_MULAW )
258 {
259 pInstance->sMode = DATATYPE_MULAW;
260 }
261
262 if ( pInstance->sMode == DATATYPE_RIFF_ALAW )
263 {
264 pInstance->sMode = DATATYPE_ALAW;
265 }
266
267 memset( &vsdBestFit, '\0', sizeof( VSD_BEST_FIT ) );
268
269 pInstance->ulMatch = FALSE;
270
271 /************************************************************
272 * The caller has requested a specific data type, sampling rate,
273 * bps etc. We will search through the data type table until we
274 * either find a match or run out of table elements to compare.
275 **************************************************************/
276
277 for ( ulLoop = 0; ulLoop < pInstance->ulNumDataTypes; ulLoop++ )
278 {
279 /*---------------------------------------------------------
280 * Prepare for best fit just in case a match is not found
281 * This routine will give us the closest supported rate
282 * that the device supports given the sampling rate,
283 * bps and channels.
284 *---------------------------------------------------------*/
285
286 BestGuess( pInstance->lBitsPerSRate,
287 ( LONG ) pDataTypeTable->sBitsPerSRate,
288 ( LONG ) pInstance->sChannels,
289 ( LONG ) pDataTypeTable->usChannels,
290 pInstance->lSRate,
291 ( LONG ) pDataTypeTable->sSRate,
292 ( LONG ) pDataTypeTable->ulSamplingDescription,
293 &vsdBestFit );
294
295 if ( pInstance->sMode == pDataTypeTable->ulDataType )
296 {
297 fFoundTag = TRUE;
298
299 if ( pInstance->lBitsPerSRate == (LONG ) pDataTypeTable->sBitsPerSRate )
300 {
301 fFoundBits = TRUE;
302 if ( pInstance->sChannels == ( SHORT ) pDataTypeTable->usChannels )
303 {
304 fFoundChannels = TRUE;
305 if ( pInstance->lSRate == pDataTypeTable->sSRate ||
306 ( fContinousRate &&
307 pInstance->lSRate < pDataTypeTable->sSRate ) )
308 {
309
310 fFoundSamples = TRUE;
311
312 pInstance->ulDataType = pDataTypeTable->ulDataType;
313 pInstance->ulSubType = pDataTypeTable->ulSubType;
314
315 /* Translate RIFF mode to AUDIODD mode */
316
317 MapModes ( pInstance );
318
319 /***************************************************
320 * The resource file contains resource management
321 * information which is used by MDM. The playback
322 * mode may contain different resource management
323 * data than record mode so retrieve from the
324 * right spot.
325 ***************************************************/
326
327 if ( pInstance->ulOperation == OPERATION_RECORD )
328 {
329 if ( pDataTypeTable->usRecordClass == 0 )
330 {
331 return ( VSDERR_UNSUPP_FORMAT_MODE );
332 }
333
334 pInstance->ulClass = pDataTypeTable->usRecordClass;
335 pInstance->ulResourcesUsed = pDataTypeTable->usRecordUnits;
336 } /* Get playback resource information */
337 else
338 {
339
340 if ( pDataTypeTable->usPlayClass == 0 )
341 {
342 pInstance->ulClass = pDataTypeTable->usRecordClass;
343 pInstance->ulResourcesUsed = pDataTypeTable->usRecordUnits;
344 pInstance->ulOperation = OPERATION_RECORD;
345
346 }
347 else
348 {
349 pInstance->ulClass = pDataTypeTable->usPlayClass;
350 pInstance->ulResourcesUsed = pDataTypeTable->usPlayUnits;
351 }
352
353
354
355 } /* Get record resource information */
356
357 pInstance->ulCanRecord = ( pDataTypeTable->usRecordClass > 0 ) ? 1 : 0;
358 /* Set flag indicating that this mode is valid */
359
360 pInstance->ulMatch = TRUE;
361
362 /*-----------------------------------------------
363 * In our attempt to work around a Microsoft
364 * kludge, we may have overwritten the callers
365 * datatype. Restore before leaving.
366 *----------------------------------------------*/
367
368 pInstance->sMode = sModeBackup;
369
370
371 return ( VSDERR_SUCCESS );
372
373 } /* Sampling rate is the same */
374 else
375 {
376 if ( pInstance->lSRate > pDataTypeTable->sSRate &&
377 pDataTypeTable->ulSamplingDescription == BEGIN_CONTINUOUS )
378 {
379 fContinousRate = TRUE;
380 }
381 else
382 {
383 fContinousRate = FALSE;
384 }
385 } /* Sampling rate differs */
386
387 } /* if the channels are the same */
388 } /* if the bits/sample are the same */
389
390 } /* if the format tags are the same */
391
392 pDataTypeTable++;
393 } /* loop through each data type till we find a match */
394
395
396 /*-----------------------------------------------
397 * In our attempt to work around a Microsoft
398 * kludge, we may have overwritten the callers
399 * datatype. Restore before leaving.
400 *----------------------------------------------*/
401
402 pInstance->sMode = sModeBackup;
403
404 /* Setup best-fit info to the caller */
405
406 pInstance->sBestFitMode = DATATYPE_WAVEFORM;
407 pInstance->ulBestFitBPS = vsdBestFit.lBPSGuess;
408 pInstance->ulBestFitChan = vsdBestFit.lChanGuess;
409 pInstance->ulBestFitRate = vsdBestFit.lSampGuess;
410
411
412 /* Return non-zero value to indicate failure */
413
414
415 if ( !fFoundTag )
416 {
417 return ( VSDERR_UNSUPP_FORMAT_TAG );
418 }
419 else if ( !fFoundBits )
420 {
421 return ( VSDERR_UNSUPP_BITSPERSAMPLE );
422 }
423 else if ( !fFoundChannels )
424 {
425 return ( VSDERR_UNSUPP_CHANNELS );
426 }
427 else if ( !fFoundSamples )
428 {
429 return ( VSDERR_UNSUPP_SAMPLESPERSEC );
430 }
431
432 else
433 {
434 return ( VSDERR_UNSUPP_FORMAT_MODE );
435 }
436#endif
437// 15552
438 } /* Device driver does not support capabilities IOCTL */
439
440} /* GetClassInformation */
441
442
443// 15552
444#ifndef INCL_MM_WPOS
445/************************** START OF SPECIFICATIONS ************************
446* *
447* SUBROUTINE NAME: BestGuess *
448* *
449* DESCRIPTIVE NAME: Retrives VSD Resource information obtained from ini *
450* *
451* FUNCTION: This function tries to determine the closest mode a device *
452* supports compared to what the user requested. *
453* *
454* INPUT: pInstance *
455* *
456* OUTPUT: None. *
457* *
458* SIDE EFFECTS: *
459* *
460*************************** END OF SPECIFICATIONS **************************/
461
462void BestGuess ( LONG lBPSRequest,
463 LONG lBPSValue,
464 LONG lChanRequest,
465 LONG lChanValue,
466 LONG lSampRequest,
467 LONG lSampValue,
468 LONG lContinuous,
469 VSD_BEST_FIT *pvsdBestFit )
470
471{
472LONG lDifference;
473LONG lNewDifference;
474BOOL fContinuous = FALSE;
475
476
477
478 /*------------------------------------------------------
479 * If we have not guessed at the nearest supported
480 * bps value already, then the guess and the max and
481 * min supported rates must be the currently supported
482 * rate.
483 *-----------------------------------------------------*/
484
485 if ( !pvsdBestFit->lBPSGuess )
486 {
487 pvsdBestFit->lBPSGuess = lBPSValue;
488 }
489 else
490 {
491
492 /* Determine which is closer, our guess or the new # */
493
494 lDifference = abs( lBPSRequest - pvsdBestFit->lBPSGuess );
495 lNewDifference = abs( lBPSRequest - lBPSValue );
496
497 /* If our new number is closer, then use that as the guess */
498
499 if ( lNewDifference < lDifference )
500 {
501 pvsdBestFit->lBPSGuess = lBPSValue;
502 } /* New number is closer */
503
504 /* 4-bit actually means some type of ADPCM */
505
506 if ( lBPSRequest == 4 && lBPSValue == 16 )
507 {
508 pvsdBestFit->lBPSGuess = lBPSValue;
509 }
510 } /* else there was a best fit guess */
511
512 /*------------------------------------------------------
513 * If we have not guessed at the nearest supported
514 * bps value already, then the guess and the max and
515 * min supported rates must be the currently supported
516 * rate.
517 *-----------------------------------------------------*/
518
519 if ( !pvsdBestFit->lChanGuess )
520 {
521 pvsdBestFit->lChanGuess = lChanValue;
522 }
523 else
524 {
525 /* Determine which is closer, our guess or the new # */
526
527 lDifference = abs( lChanRequest - pvsdBestFit->lChanGuess );
528 lNewDifference = abs( lChanRequest - lChanValue );
529
530 /* If our new number is closer, then use that as the guess */
531
532 if ( lNewDifference < lDifference )
533 {
534 pvsdBestFit->lChanGuess = lChanValue;
535 } /* New number is closer */
536
537 } /* else there was a best fit guess */
538
539
540 if ( lContinuous == BEGIN_CONTINUOUS ||
541 lContinuous == END_CONTINUOUS )
542 {
543 fContinuous = TRUE;
544 }
545 /*------------------------------------------------------
546 * If we have not guessed at the nearest supported
547 * samp/rate value already, then the guess and the max and
548 * min supported rates must be the currently supported
549 * rate.
550 *-----------------------------------------------------*/
551
552 if ( fContinuous )
553 {
554 pvsdBestFit->lSampGuess = lSampRequest;
555 }
556
557 else
558 {
559 if ( !pvsdBestFit->lSampGuess )
560 {
561 pvsdBestFit->lSampGuess = lSampValue;
562 }
563 else
564 {
565 /* Determine which is closer, our guess or the new # */
566
567 lDifference = abs( lSampRequest - pvsdBestFit->lSampGuess );
568 lNewDifference = abs( lSampRequest - lSampValue );
569
570 /* If our new number is closer, then use that as the guess */
571
572 if ( lNewDifference < lDifference )
573 {
574 pvsdBestFit->lSampGuess = lSampValue;
575 } /* New number is closer */
576
577 } /* else there was a best fit guess */
578 } /* Not a device with integral sampling rates */
579
580} /* BestGuess */
581
582
583
584/************************** START OF SPECIFICATIONS ************************
585* *
586* SUBROUTINE NAME: MapModes *
587* *
588* DESCRIPTIVE NAME: Converts a Riff Mode to an AUDIODD mode. *
589* *
590* FUNCTION: Due to a very unfortunate choice (i.e. one out of our control) *
591* the AUDIODD architecture defines conflict with RIFF modes. *
592* This function maps from RIFF->AUDIODD mode *
593* Newer drivers can indicate that they support RIFF datatypes *
594* via the AUDIO capability ioctl. *
595* *
596* *
597* INPUT: pInstance *
598* *
599* OUTPUT: None. *
600* *
601* SIDE EFFECTS: *
602* *
603*************************** END OF SPECIFICATIONS **************************/
604
605
606
607void MapModes( PVSD_INSTANCE pInstance )
608
609{
610ULONG ulLoop = 0;
611
612RIFFTABLE *pMapTable = pInstance->pMapTable;
613
614
615
616
617 if ( !(pInstance->fDriverCaps & SUPPORT_RIFF_MODES) )
618 {
619 while ( ulLoop < KNOWN_AUDIODD_MAPS )
620 {
621
622 if ( pInstance->sMode == RiffTable[ ulLoop ].ulDataType )
623 {
624 pInstance->ulHardwareMode = RiffTable[ ulLoop ].ulAUDIODDMode;
625 return;
626 }
627 ulLoop++;
628 }
629
630 ulLoop = 0;
631
632 while ( ulLoop < pInstance->ulNumMappingRows )
633 {
634 if ( pInstance->sMode == (pMapTable + ulLoop)->ulDataType )
635 {
636 pInstance->ulHardwareMode = (pMapTable + ulLoop)->ulAUDIODDMode;
637 // ensure that we can stream this data.
638 pInstance->ulDataType = DATATYPE_WAVEFORM;
639
640 return;
641 }
642 ulLoop++;
643 }
644 } /* If the driver does not support RIFF datatypes */
645
646 /* Worst case, assume that they are the same */
647
648 pInstance->ulHardwareMode = pInstance->ulDataType;
649 return;
650
651} /* MapModes */
652
653
654/************************ START OF SPECIFICATIONS **************************
655*
656* SUBROUTINE NAME: ACPABestFit()
657*
658* FUNCTION: Since ACPA 1.02 has no best fit, best fit for it
659*
660* INPUT: pInstance - pointer to AMP/Mixer instance structure
661*
662* OUTPUT: returns VSDERR_SUCCESS if successful, otherwise it returns an
663* MCI error code.
664*
665* *
666*************************** END OF SPECIFICATIONS *************************/
667void ACPABestFit( PVSD_INSTANCE pInstance )
668
669{
670 if ( ( !pInstance->ulMatch &&
671 pInstance->sMode == DATATYPE_WAVEFORM ) )
672
673 {
674 if ( pInstance->lSRate < 9000 )
675 {
676 pInstance->lSRate = 8000;
677 }
678 else if ( pInstance->lSRate < 15000 )
679 {
680 pInstance->lSRate = 11025;
681 }
682 else if ( pInstance->lSRate < 33400 )
683 {
684 pInstance->lSRate = 22050;
685 }
686 else
687 {
688 pInstance->lSRate = 44100;
689 }
690
691 pInstance->ulHardwareMode = PCM;
692
693 GetClassInformation( pInstance );
694
695 } /* If sampling rate is not directly supported */
696
697
698} /* ACPABestFit */
699
700#endif
701// 15552
Note: See TracBrowser for help on using the repository browser.