source: cmedia/trunk/Vsd/AudioIF/vsdioctl.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: 88.5 KB
Line 
1/************************ START OF SPECIFICATIONS ***
2*
3* SOURCE FILE NAME: VSDIOCTL.C
4*
5* DESCRIPTIVE NAME: AUDIODD interface routines
6*
7* COPYRIGHT: IBM Confidential
8* Copyright (c) IBM Corporation 1991
9* All Rights Reserved
10*
11* STATUS: OS/2 Release 2.0
12*
13* FUNCTION: This source module contains the Operating System dependent
14* calls to access the associated device driver. In the case
15* of OS/2 2.x, and AUDIODD driver is assumed and the
16* DosDevIOCTL interface is used. If other hardware or OSes
17* are in use, then these routines must be modified.
18*
19* NOTES:
20* DEPENDENCIES: ACPA PDD
21* RESTRICTIONS: Runs in 32 bit protect mode (OS/2 2.0)
22*
23* ENTRY POINT:
24* AUDIOIFDriverEntry
25*
26* EXTERNAL REFERENCES: Sends IOCTL request to ACPA audio board
27*
28* Change History:
29* DATE DEVELOPER CHANGE DESCRIPTION
30* 12/07/92 Linden deCarmo File created
31* 05/24/94 Linden deCarmo Added OpenDevice abstraction
32* 05/24/94 Linden deCarmo Moved VSDSet from vsdset.c file
33* 05/24/94 Linden deCarmo Improved comments.
34* 07/22/94 Mike Koval WPOS Changes for WorkPlace OS
35* 10/11/94 Linden deCarmo Moved DosOpen/DosClose to vsdioctl.c
36* 10/12/94 Linden deCarmo Added code to ModifyAudioAttributes to
37* correctly use mixer interface.
38* 10/12/94 Linden deCarmo Added InitMixer to ensure lines are
39* correctly enabled for recording.
40* 04/11/95 Linden deCarmo Ensure that audio attributes on a given
41* line are supported before sending message
42* 06/29/95 Linden deCarmo Cleanup Hardware mixer support (15552).
43************************** END OF SPECIFICATIONS **************************/
44
45#define INCL_NOPMAPI
46#define INCL_DOS
47#define INCL_ERRORS
48#define INCL_AUDIO_VSD
49
50//-----------------------------------------------------------------------------
51
52
53#ifdef INCL_MM_WPOS
54//#include <mach.h>
55#include <mk.h>
56//#include <pns\dd_debug.h>
57//#include <pns\dd_audio.h>
58#include <dd_audio.h>
59#include <pns\dd_error.h>
60
61#ifdef GOT_BUILD
62 #include <pns/pns.h>
63// #include <pns/names.h>
64// #include <pns/ns_proto.h>
65// #include <pns/ns.h>
66#else
67 #include <pns\nameserver.h>
68 #include <pns\ns_proto.h>
69#endif
70
71#ifdef GOT_BUILD
72// mach_port_t rns_port;
73// extern mach_port_t DosGetRnsPort();
74 port_t rns_port;
75 extern port_t DosGetRnsPort();
76#else
77// mach_port_t rns_port;
78// extern mach_port_t DosGetRnsPort();
79 port_t rns_port;
80 extern port_t DosGetRnsPort();
81#endif
82
83#endif
84
85//-----------------------------------------------------------------------------
86
87
88#include <os2.h>
89#include <os2me.h>
90#include <mcd.h>
91#include <audio.h>
92#include <stdio.h>
93#include <string.h>
94#include <hhpheap.h>
95
96
97#ifdef INCL_MM_WPOS
98typedef struct _DRIVER_PORT
99 {
100 CHAR szDeviceName[MAX_DEVICE_NAME]; // INPUT--NAME of device driver in MMPM2.INI
101 port_t AudioDrvPort; // now global
102 port_t rns_port; // root name server port
103 BOOL fFlags;
104 struct _DRIVER_PORT *pNext;
105 } DRIVER_PORT;
106
107typedef DRIVER_PORT *PDRIVER_PORT;
108
109PDRIVER_PORT pDriverPort = (PDRIVER_PORT) NULL ;
110#endif
111
112
113
114
115#include <vsdcmds.h>
116#include <vsdaud.h>
117#include <os2mixer.h>
118#include "vsdmix.h"
119
120
121#ifdef INCL_MM_WPOS
122ULONG AddDevicePort( PVSD_INSTANCE pInstance,
123 port_t AudioDrvPort,
124 port_t rns_port);
125
126BOOL FindDevicePort( PVSD_INSTANCE pInstance,
127 port_t *pAudioDrvPort,
128 port_t *rns_port);
129
130#endif
131
132
133
134#ifdef MMDEBUG
135#include <stdio.h>
136#endif
137
138
139
140//ULONG mixSetControl( HMIXER hMixer, PMIXERCONTROL pMixControl );
141ULONG DetermineSubType( ULONG, ULONG, ULONG, ULONG );
142
143/************************** START OF SPECIFICATIONS ************************
144* *
145* SUBROUTINE NAME: NewPortLookup *
146* *
147* DESCRIPTIVE NAME: Get audio device port. *
148* *
149* FUNCTION: Returns the audio device port for the requested audio name. *
150* *
151* NOTES: This will init the DSP and load any necessary code. *
152* *
153* INPUT: nameSrvName - audio device name *
154* servicePort - area to return port number *
155* *
156* OUTPUT: *
157* *
158* SIDE EFFECTS: *
159* *
160*************************** END OF SPECIFICATIONS **************************/
161//-----------------------------------------------------------------------------
162#ifdef INCL_MM_WPOS
163#ifdef GOT_BUILD
164
165 #define UNI_STR_MAX 256
166 #define DELIM_MAX 10
167
168//APIRET EXPENTRY NewPortLookup(char *nameSrvName, mach_port_t *servicePort)
169APIRET EXPENTRY NewPortLookup(char *nameSrvName, port_t *servicePort)
170{
171 UniChar unicharStr[UNI_STR_MAX];
172 UniChar delimiters[DELIM_MAX];
173 ns_path_t unicharPath;
174 vm_size_t nodeSize=0, pathSize=0;
175 ULONG flags;
176 kern_return_t rc = KERN_SUCCESS;
177 UniChar uniUnresPathName[UNI_STR_MAX];
178 ns_link_name_t linkUnresPathName;
179 ns_path_t unresolvedPath;
180 vm_size_t unresPathSize=0;
181 ns_node_type_t nodeType;
182 ns_handle_t nodeHandle;
183 ns_node_handle_t localRnsHandle = DosGetRnsPort();
184
185 linkUnresPathName.name = uniUnresPathName;
186 unresolvedPath = &linkUnresPathName;
187
188 if (nameSrvName == (char *) NULL)
189 return ( VSDERR_NO_DEVICE_DRIVER );
190// Vivek changed this, really it should be cannot find the device driver
191// return(ERR_EWS_BAD_PORTNAME);
192
193 char_to_UniChar( unicharStr, nameSrvName, strlen(nameSrvName) + 1);
194
195 // Make this the default delimiter
196 char_to_UniChar(delimiters, "/\\ ", strlen("/\\ ") + 1);
197
198 pathSize = 0; // Size of unicode buffer, have NS allocate path buffer
199 flags = NS_IGNORE_ENDING_DELIMITERS; // Default Behavior
200
201 /* No change under GOT BUILD for microkernel 9438.3, for this call. */
202
203 rc = NS_ConvertUnicodeToPath(
204 unicharStr, // I - input path name
205 delimiters, // I - delimiters
206 flags, // I - flags
207 &pathSize, // I/O - path size
208 &unicharPath); // O - new path name
209
210 if (rc != KERN_SUCCESS)
211 return(rc);
212
213 unresPathSize = sizeof(ns_link_name_t) + sizeof(UniChar);
214
215 /* Changed under GOT BUILD for microkernel 9438.3, for this call and
216 and more changes anticipated for microkernel 9440.1 */
217
218 rc = NS_Resolve( localRnsHandle, // I - starting node
219 unicharPath, // I - path
220 NS_COMPLETE_RESOLUTION|NS_FOLLOW_LEAF, // I - flags
221 &nodeType, // O - node type
222 &nodeHandle, // O - handle
223 &unresPathSize, // I/O - size of path
224 &unresolvedPath ); // O - pointer to unres path
225
226 (*servicePort) = nodeHandle.port;
227
228 if (rc != KERN_SUCCESS)
229 return(rc);
230
231 return(rc);
232}
233#endif
234#endif
235//-----------------------------------------------------------------------------
236
237/************************** START OF SPECIFICATIONS ************************
238* *
239* SUBROUTINE NAME: DoIOCTLLoad *
240* *
241* DESCRIPTIVE NAME: Status for a port *
242* *
243* FUNCTION: Returns if a particular port is currently active. *
244* *
245* NOTES: This will init the DSP and load any necessary code. *
246* *
247* INPUT: ulPort *
248* *
249* OUTPUT: MCI_TRUE *
250* MCI_FALSE *
251* *
252* SIDE EFFECTS: *
253* *
254*************************** END OF SPECIFICATIONS **************************/
255
256LONG DoIOCTLLoad( PVSD_INSTANCE pInstance,
257 SHORT sMode )
258
259
260
261{
262extern HMTX hmtxProcessSemVSD; // Semaphore global to all processes
263 // which controls ioctl access
264
265LONG rc;
266LONG lError = VSDERR_SUCCESS;
267ULONG ulParmLengthInOut = 0L;
268ULONG ulDataLengthInOut = (ULONG) sizeof(MCI_AUDIO_INIT);
269
270MCI_AUDIO_INIT AudioInit;
271#ifdef PERFORMANCE_TRACE
272// ULONG ulTime = 0;
273// CHAR LoadError[100];
274// CHAR DebugBuf[256];
275// console_printf("DoIOCTL entry\n");
276// PerfStartTime();
277#endif
278
279
280 // Perform Audio Init IOCTL
281
282 /*-------------------------------------------------------
283 * AUDIODD has a tremendous limitation--the modes don't map
284 * with RIFF datatypes. We must perform mapping here.
285 * Drivers that support the new capability IOCTL will indicate
286 * that this mapping is not necessary.
287 *------------------------------------------------------*/
288
289//-----------------------------------------------------------------------------
290#ifdef INCL_MM_OS2
291 // For WorkPlace, use the RIFF type passed in.
292 if ( !pInstance->ulMatch )
293 {
294 MapModes( pInstance );
295 }
296//-----------------------------------------------------------------------------
297
298 /*-------------------------------------------------------
299 * Because the ACPA device driver is older, it has bugs that
300 * must be worked around. You will see numerous comments
301 * like if ( pInstance->ulDeviceID == MACPA ),
302 * you can safely remove these from your VSD code.
303 *------------------------------------------------------*/
304
305
306 if ( pInstance->ulDeviceID == MACPA )
307 {
308 /*-------------------------------------------------------
309 * Until the 1.03 M-AUDIO driver drops, we will have to
310 * do the BEST-FIT in the VSD.
311 *------------------------------------------------------*/
312
313 if ( ( !pInstance->ulMatch &&
314 pInstance->sMode == DATATYPE_WAVEFORM ) )
315
316 {
317 ACPABestFit( pInstance );
318 } /* if best fit is required */
319
320 } /* If this is an ACPA before the 1.03 drop */
321
322
323 /* Fill in AUDIO INIT structure */
324
325 AudioInit.lResolution = 0L;
326 AudioInit.lSRate = pInstance->lSRate;
327 AudioInit.lBitsPerSRate = pInstance->lBitsPerSRate;
328 AudioInit.sMode = sMode;
329
330 AudioInit.ulOperation = (SHORT) pInstance->ulOperation;
331 AudioInit.sChannels = pInstance->sChannels;
332
333 AudioInit.ulFlags = pInstance->ulFlags;
334 if ( pInstance->fDriverCaps & SUPPORT_RIFF_MODES )
335 {
336 AudioInit.ulFlags |= RIFF_DATATYPE;
337 }
338
339
340 AudioInit.sDeviceID = pInstance->ulDeviceID;
341 AudioInit.sReturnCode = 0;
342 AudioInit.pvReserved = NULL;
343 AudioInit.ulVersionLevel= CURRENT_VERSION;
344
345 if ( AudioInit.sMode == PCM && AudioInit.lBitsPerSRate == 16)
346 AudioInit.ulFlags |= TWOS_COMPLEMENT;
347 else
348 AudioInit.ulFlags &= ~TWOS_COMPLEMENT;
349
350
351
352
353
354 /*---------------------------------------------------------*
355 * Do Audio Init IOCtl call
356 *---------------------------------------------------------*/
357
358 ulParmLengthInOut = 0L;
359 ulDataLengthInOut = (ULONG) sizeof(MCI_AUDIO_INIT);
360
361
362#endif
363//-----------------------------------------------------------------------------
364#ifdef INCL_MM_OS2
365
366
367 /*---------------------------------------------------------*
368 * Utilize a process wide semaphore to prevent more than
369 * one process from accessing the device driver at the same
370 * time.
371 *
372 * This is necessary since the amp has instance based
373 * semaphores, but not cross process semaphores.
374 *---------------------------------------------------------*/
375
376 DosRequestMutexSem( hmtxProcessSemVSD, -1 );
377 rc = DosDevIOCtl( pInstance->hFile,
378 AUDIO_IOCTL_CAT,
379 AUDIO_INIT,
380 NULL,
381 0L,
382 &ulParmLengthInOut,
383 &AudioInit,
384 (LONG) sizeof(MCI_AUDIO_INIT),
385 &ulDataLengthInOut);
386
387 DosReleaseMutexSem( hmtxProcessSemVSD );
388
389
390 if ( rc || AudioInit.sReturnCode )
391 {
392 if ( AudioInit.sReturnCode == OVERLOADED )
393 {
394 return ( VSDERR_RESOURCE_NOT_AVAILABLE );
395 }
396 else
397 {
398 return ( VSDERR_HARDWARE );
399 }
400 }
401 else
402 {
403 pInstance->ulGlobalFile = (ULONG) AudioInit.pvReserved;
404
405 if ( AudioInit.ulFlags & BESTFIT_PROVIDED )
406 {
407 pInstance->lSRate = AudioInit.lSRate;
408 if ( pInstance->lBitsPerSRate != AudioInit.lBitsPerSRate ||
409 pInstance->sChannels != AudioInit.sChannels )
410 {
411 return ( VSDERR_HARDWARE );
412 }
413
414 /* Get resource information, class data etc. */
415
416 GetClassInformation( pInstance );
417
418 } /* Best fit flag was set */
419
420 if ( AudioInit.ulFlags & VOLUME )
421 {
422 pInstance->ulVolControl = TRUE;
423 }
424 else
425 {
426 pInstance->ulVolControl = FALSE;
427 }
428 }
429
430 // if a DSP module has not been loaded, then bring it in
431
432 //WPOS - Will LOAD_CODE ever be set for business audio card. If so, need
433 //WPOS - to change LoadDSP to not issue a DosDevIOCTL call.
434
435 if (AudioInit.ulFlags & LOAD_CODE)
436 {
437 lError = LoadDSP(pInstance, &AudioInit);
438 }
439
440// 10253
441
442 return ( lError );
443
444#endif
445//-----------------------------------------------------------------------------
446
447//-----------------------------------------------------------------------------
448#ifdef INCL_MM_WPOS
449 // 15552
450 // note: on PPC, this call is unnecssary. Update DDCMD.DLL
451 // and remove this call to the driver.
452 // 15552
453 return ( MCIERR_SUCCESS );
454
455///kern_return_t krc;
456///audio_device_info_t dev_info;
457///
458///dev_info.operation = AUDIO_OPERATION_PLAY;
459///if (pInstance->ulOperation == OPERATION_RECORD)
460/// dev_info.operation = AUDIO_OPERATION_RECORD;
461///
462/// // Insure the sMode is the RIFF type, and not the hardware mapped type.
463/// dev_info.data_description.format = sMode;
464///
465/// dev_info.device_class = AUDIO_DEV_CLASS_WAVE;
466/// if (sMode == DATATYPE_MIDI)
467/// dev_info.device_class = AUDIO_DEV_CLASS_MIDI;
468///
469/// // Set MIDI fields to O since they will already be set
470/// // up by SYSEX midi command contained with midi data.
471/// dev_info.data_description.tempo = 0;
472/// dev_info.data_description.cpqn = 0;
473///
474/// dev_info.data_description.sample_rate = pInstance->lSRate;
475/// dev_info.data_description.bits_per_sample = pInstance->lBitsPerSRate;
476/// dev_info.data_description.channel_count = pInstance->sChannels;
477///
478/// dev_info.data_description.flags = 0;
479///
480/// if (dev_info.data_description.bits_per_sample == 16) //16 bit data
481/// dev_info.data_description.flags |= AUDIO_DATA_SIGNED; //signed, two's complement
482///
483/// // AUDIO_DATA_PACKED flag not currently used.
484///
485/// krc = DD_SetInfo((port_t) pInstance->hFile, // probably wrong handle (port)
486/// ADF_DEVICE_PARMS,
487/// 0,
488/// 0,
489/// (dd_data_ptr_t) &dev_info,
490/// (mach_msg_type_number_t) sizeof(dev_info));
491/// rc = (LONG) krc;
492///
493/// // Set the stream port to be used in the SpiCreateStream call.
494/// pInstance->ulGlobalFile = pInstance->hFile;
495/// DosReleaseMutexSem( hmtxProcessSemVSD );
496///
497///
498/// return ( rc) ;
499#endif
500//-----------------------------------------------------------------------------
501
502
503} /* DoIOCTLLoad */
504
505
506#ifdef INCL_MM_OS2
507/************************ START OF SPECIFICATIONS **************************
508*
509* SUBROUTINE NAME: LoadDSP()
510*
511* FUNCTION: Loads DSP module.
512*
513* INPUT:
514*
515* OUTPUT:
516*
517* OS/2 CALLS: None
518*
519* C CALLS: None
520*
521*************************** END OF SPECIFICATIONS *************************/
522
523
524LONG LoadDSP( PVSD_INSTANCE pInstance,
525 LPMCI_AUDIO_INIT pAudioInit)
526 {
527 LONG rc;
528 LONG lError = VSDERR_SUCCESS;
529 HFILE hDSPFile;
530 ULONG ulParmLengthInOut;
531 ULONG ulDataLengthInOut;
532 ULONG ulAction;
533 ULONG ulDSPFileSize;
534 ULONG ulBytesRead;
535// USHORT usDSPFound = MCI_FALSE;
536 SHORT sDSPFileOpen;
537 CHAR szDSPFile[261], *pEnv;
538 FILESTATUS rFileInfo;
539 ULONG *pulDSPBase32;
540 ULONG *pulDSPBase16;
541 CHAR abParmList[128];
542 MCI_AUDIO_LOAD rAudioLoad;
543
544 /*-----------------------------------------------------------------*
545 * Find and open DSP file
546 *-----------------------------------------------------------------*/
547
548 rc = DosScanEnv("MMBASE", &pEnv);
549
550 strcpy(szDSPFile, pEnv);
551
552 if (strlen(szDSPFile))
553 {
554 if (szDSPFile[strlen(szDSPFile) - 1] == ';')
555 szDSPFile[strlen(szDSPFile) - 1] = 0;
556
557 if (strlen(szDSPFile))
558 {
559 if (szDSPFile[strlen(szDSPFile) - 1] != '\\')
560 strcat(szDSPFile,"\\DSP\\");
561 }
562 }
563
564 strcat(szDSPFile,pAudioInit->abLoadPath);
565
566 rc = DosOpen(szDSPFile,
567 &hDSPFile,
568 &ulAction,
569 0L,
570 FILE_NORMAL,
571 FILE_OPEN,
572 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE,
573 0);
574
575 if (rc)
576 lError = VSDERR_CANNOT_LOAD_DSP_MOD;
577
578 if (lError)
579 {
580 sDSPFileOpen = MCI_FALSE;
581 }
582 else
583 sDSPFileOpen = MCI_TRUE;
584
585 /*-----------------------------------------------------------------*
586 * Get DSP File Size
587 *-----------------------------------------------------------------*/
588
589 if (!lError)
590 {
591 rc = DosQueryFileInfo(hDSPFile,
592 1L,
593 &rFileInfo,
594 sizeof(FILESTATUS));
595
596 lError = MCI_Error(rc);
597 ulDSPFileSize = rFileInfo.cbFile;
598 }
599
600 /*-------------------------------------------------*
601 * Allocate Buffer to Store DSP Code
602 *-------------------------------------------------*/
603
604 if (!lError && ulDSPFileSize > 0)
605 {
606 rc = DosAllocSharedMem((PVOID)&pulDSPBase32,
607 NULL,
608 ulDSPFileSize,
609 PAG_COMMIT | OBJ_GIVEABLE |
610 PAG_READ | PAG_WRITE);
611
612 lError = MCI_Error(rc);
613 }
614
615 /*-------------------------------------------------*
616 * Read DSP File into Buffer
617 *-------------------------------------------------*/
618
619 if (!lError && ulDSPFileSize > 0)
620 {
621 rc = DosRead(hDSPFile,
622 pulDSPBase32,
623 ulDSPFileSize,
624 &ulBytesRead);
625
626
627 lError = MCI_Error(rc);
628 }
629
630 /*-------------------------------------------------*
631 * Convert 32 bit address to 16 bit address
632 *-------------------------------------------------*/
633
634 /*
635 * Cant seem to get MAKEP work reliably under C-Set/2 so
636 * wrote my own conversion, note, this may not be the best
637 * solution
638 */
639
640 pulDSPBase16 = ( PULONG ) MAKEULONG( LOUSHORT( pulDSPBase32 ),
641 (HIUSHORT( pulDSPBase32 ) << 3) + 7);
642
643 /*-------------------------------------------------*
644 * Call AUDIO_LOAD IOCtl
645 *-------------------------------------------------*/
646
647 if (!lError && ulDSPFileSize > 0)
648 {
649 rAudioLoad.pbBuffer = (CHAR FAR *) pulDSPBase16;
650 rAudioLoad.ulSize = (USHORT) ulBytesRead;
651 rAudioLoad.ulFlags = LOAD_START | LOAD_END;
652
653 ulParmLengthInOut = 0L;
654 ulDataLengthInOut = (LONG) sizeof(MCI_AUDIO_LOAD);
655
656//-----------------------------------------------------------------------------
657#ifdef INCL_MM_OS2
658 rc = DosDevIOCtl(pInstance->hFile,
659 AUDIO_IOCTL_CAT,
660 AUDIO_LOAD,
661 abParmList,
662 128L,
663 &ulParmLengthInOut,
664 &rAudioLoad,
665 (LONG) sizeof(MCI_AUDIO_LOAD),
666 &ulDataLengthInOut);
667#endif
668//-----------------------------------------------------------------------------
669
670//-----------------------------------------------------------------------------
671#ifdef INCL_MM_WPOS
672 //WPOS - this code should not be executed for Workplace OS.
673#endif
674//-----------------------------------------------------------------------------
675
676 lError = MCI_Error(rc);
677 DosFreeMem(pulDSPBase32);
678 }
679
680 /*-------------------------------------------------*
681 * Close DSP File
682 *-------------------------------------------------*/
683
684 if (sDSPFileOpen)
685 DosClose(hDSPFile);
686
687 return(lError);
688
689 } /* LoadDSP */
690#endif
691
692
693/************************ START OF SPECIFICATIONS **************************
694*
695* SUBROUTINE NAME: OpenDevice()
696*
697* FUNCTION: Opens the device driver
698*
699* INPUT:
700*
701* OUTPUT:
702*
703* OS/2 CALLS: None
704*
705* C CALLS: None
706*
707*************************** END OF SPECIFICATIONS *************************/
708
709ULONG OpenDevice ( PVSD_INSTANCE pInstance )
710
711{
712 ULONG rc;
713
714//-----------------------------------------------------------------------------
715#ifdef INCL_MM_OS2
716 ULONG ulAction;
717#endif
718//-----------------------------------------------------------------------------
719
720//-----------------------------------------------------------------------------
721#ifdef INCL_MM_WPOS
722 kern_return_t krc;
723 mach_port_t AudioDrvPort = MACH_PORT_NULL; // now global
724 CHAR szAudioDevName[128] = "devices/";
725// CHAR szAudioDevName[128] = "/devices/audio0";
726 CHAR *pszAudioDevName = szAudioDevName;
727 CHAR *ptr = 0;
728 int ch = ' ';
729#endif
730//-----------------------------------------------------------------------------
731
732#ifdef PERFORMANCE_TRACE
733 ULONG ulTime = 0;
734 CHAR LoadError[100];
735 CHAR DebugBuf[256];
736 PerfStartTime();
737#endif
738
739 /*-----------------------------------------------------------------*
740 * Open the device driver--and see if it is there
741 * NOTE: It is essential to use the noinherit flag. If you do not
742 * use this flag, child processes spawned from this one will duplicate
743 * all open handles causing resource to be placed on the device that
744 * will never leave it.
745 *-----------------------------------------------------------------*/
746
747//-----------------------------------------------------------------------------
748#ifdef INCL_MM_OS2
749 rc = DosOpen( pInstance->szDeviceName,
750 &pInstance->hFile,
751 &ulAction,
752 0,
753 FILE_NORMAL,
754 FILE_OPEN,
755 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE |
756 OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NOINHERIT,
757 0);
758#endif
759//-----------------------------------------------------------------------------
760
761//-----------------------------------------------------------------------------
762#ifdef INCL_MM_WPOS
763 /*---------------------------------------------*
764 * Get the root name server port.
765 *----------------------------------------------*/
766
767
768 //WPOS - This will have to change depending on how
769 // the MCD's eventually pass the Device name.
770 // If MCD passes a "AUDIO0$", or "AUDIO1$" etc.,
771 // may need a table since
772 // "/devices/audio0" needs to be opened,
773 // or hard code a test here for it.
774 //
775 // NO, the MMPM2.INI will be updated with an
776 // entry for the business audio card containing
777 // the "/devices/audio0" device name, which will
778 // be passed to the VSD.
779
780 strcat( pszAudioDevName, pInstance->szDeviceName);
781 ptr = strchr(pszAudioDevName,ch);
782 if (ptr)
783 *ptr = 0;
784
785 /*---------------------------------------------*
786 * Look up the device driver port.
787 * Each device has PER process information (such
788 * as the port information) and global data (such
789 * as its name and capabilities).
790 * Look up the per-process stuff now.
791 *----------------------------------------------*/
792
793#ifdef PERFORMANCE_TRACE
794///ulTime += PerfGetTime();
795///strcpy(DebugBuf, "Before port lookup: ");
796///_ltoa((ULONG)ulTime, LoadError, 10);
797///strcat(DebugBuf, LoadError);
798///console_printf(DebugBuf );
799///PerfStartTime();
800#endif
801 if ( !(FindDevicePort( pInstance, &AudioDrvPort, &rns_port ) ) )
802
803 {
804
805 rns_port = DosGetRnsPort();
806
807#ifdef GOT_BUILD
808 krc = (kern_return_t) NewPortLookup(pszAudioDevName, &AudioDrvPort);
809#else
810 krc = NS_LookupServerAscii( rns_port, pszAudioDevName, &AudioDrvPort );
811// krc = NS_LookupServerAscii( rns_port, pInstance->szDeviceName, &AudioDrvPort );
812#endif
813
814 AddDevicePort( pInstance, AudioDrvPort, rns_port );
815 }
816 else
817 {
818 krc = KERN_SUCCESS;
819 }
820#ifdef PERFORMANCE_TRACE
821///ulTime += PerfGetTime();
822///strcpy(DebugBuf, "After port lookup: ");
823///_ltoa((ULONG)ulTime, LoadError, 10);
824///strcat(DebugBuf, LoadError);
825///
826///console_printf(DebugBuf );
827
828#endif
829
830#ifdef PERFORMANCE_TRACE
831///strcpy(DebugBuf, "Name server name: ");
832///strcat(DebugBuf, pszAudioDevName);
833///strcat(DebugBuf, " port number: ");
834///_ltoa((ULONG)AudioDrvPort, LoadError, 10);
835///strcat(DebugBuf, LoadError);
836///strcat(DebugBuf, " \n");
837///console_printf(DebugBuf );
838///PerfStartTime();
839#endif
840 /*---------------------------------------------*
841 * Open the device driver.
842 *----------------------------------------------*/
843 if (krc == KERN_SUCCESS)
844 {
845
846 //WPOS -- Should mach_port_t be kept in a new field (devInstPort) in
847 // pInstance, or just use the hFile field???
848
849#ifdef PERFORMANCE_TRACE
850///ulTime += PerfGetTime();
851///strcpy(DebugBuf, "Before open: ");
852///_ltoa((ULONG)ulTime, LoadError, 10);
853///strcat(DebugBuf, LoadError);
854///console_printf(DebugBuf );
855///PerfStartTime();
856#endif
857// krc = DD_Open( pInstance->AudioDrvPort, 0, (mach_port_t *) &pInstance->hFile);
858 krc = DD_Open( AudioDrvPort, 0, (port_t *) &pInstance->hFile);
859#ifdef PERFORMANCE_TRACE
860///ulTime += PerfGetTime();
861///strcpy(DebugBuf, "After open: ");
862///_ltoa((ULONG)ulTime, LoadError, 10);
863///strcat(DebugBuf, LoadError);
864///console_printf(DebugBuf );
865///PerfStartTime();
866#endif
867 }
868
869 if (krc != KERN_SUCCESS)
870 return ( VSDERR_NO_DEVICE_DRIVER );
871 else rc = 0;
872
873 // Set the stream port to be used in the SpiCreateStream call.
874 pInstance->ulGlobalFile = pInstance->hFile;
875#endif
876//-----------------------------------------------------------------------------
877
878 if ( !rc )
879 {
880 /***********************************************
881 * Speed improvement, keep the device open--there
882 * is no penalty if we do so.
883 ************************************************/
884 pInstance->ulDosOpened = TRUE;
885
886 }
887
888 else
889 {
890 /*-------------------------------------------------
891 * Single-instance device drivers will
892 * reject multiple opens :-(. Handle as necessary.
893 *-------------------------------------------------*/
894
895 if ( rc == ERROR_WRITE_PROTECT )
896 {
897 return ( VSDERR_RESOURCE_NOT_AVAILABLE );
898 }
899
900 return ( VSDERR_NO_DEVICE_DRIVER );
901 }
902
903#ifdef PERFORMANCE_TRACE
904///ulTime += PerfGetTime();
905///strcpy(DebugBuf, "Audio open exit: Time microseconds consumed ");
906///_ltoa((ULONG)ulTime, LoadError, 10);
907///strcat(DebugBuf, LoadError);
908///
909///console_printf(DebugBuf );
910#endif
911 return ( VSDERR_SUCCESS );
912
913} /* OpenDevice */
914
915/************************** START OF SPECIFICATIONS ************************
916* *
917* SUBROUTINE NAME: CapabilityIOCTL *
918* *
919* DESCRIPTIVE NAME: Determines if the device can perform certain actions *
920* *
921* FUNCTION: This fucntion calls the new capability IOCTL. If an error is *
922* returns, it is assumed that the device supports the older *
923* resource management version of capabilities (see OS/2 2.1 docs)*
924* *
925* OUTPUT: VSDERR_SUCESS if there was a match *
926* An MCI error otherwise *
927* *
928* SIDE EFFECTS: *
929* *
930*************************** END OF SPECIFICATIONS **************************/
931
932
933ULONG CapIOCTL( PVSD_INSTANCE pInstance )
934{
935
936 ULONG ulParmLengthInOut = 0L;
937 ULONG ulDataLengthInOut = sizeof(MCI_AUDIO_CAPS );
938 ULONG rc;
939 MCI_AUDIO_CAPS audiocap;
940#ifdef PERFORMANCE_TRACE
941// ULONG ulTime = 0;
942// CHAR LoadError[100];
943// CHAR DebugBuf[256];
944// console_printf("Capability entry\n");
945// PerfStartTime();
946#endif
947
948//-----------------------------------------------------------------------------
949#ifdef INCL_MM_WPOS
950 kern_return_t krc;
951 audio_resource_request_t aud_request;
952 audio_resource_require_t aud_require;
953#endif
954//-----------------------------------------------------------------------------
955
956 /*---------------------------------------------------------
957 * Determine if the device supports the mode that we requested
958 *----------------------------------------------------------*/
959
960 audiocap.ulSamplingRate = pInstance->lSRate;
961 audiocap.ulChannels = pInstance->sChannels;
962 audiocap.ulBitsPerSample= pInstance->lBitsPerSRate;
963 audiocap.ulDataType = pInstance->sMode;
964 audiocap.ulOperation = pInstance->ulOperation;
965
966//-----------------------------------------------------------------------------
967#ifdef INCL_MM_OS2
968 rc = DosDevIOCtl( pInstance->hFile,
969 AUDIO_IOCTL_CAT,
970 AUDIO_CAPABILITY,
971 NULL,
972 0L,
973 &ulParmLengthInOut,
974 &audiocap,
975 (LONG) sizeof(MCI_AUDIO_CAPS),
976 &ulDataLengthInOut);
977
978 /*---------------------------------------------------------
979 * If the IOCTL failed, or if the card doesn't support this
980 * mode, inform the caller of the problem.
981 *----------------------------------------------------------*/
982 if ( rc || audiocap.ulSupport )
983 {
984 if ( rc )
985 {
986 // 10253 --this error is less than optimal
987 pInstance->fDriverCaps = FALSE;
988 return (VSDERR_HARDWARE );
989 }
990
991 switch ( audiocap.ulSupport )
992 {
993 case UNSUPPORTED_RATE :
994 rc = VSDERR_UNSUPP_SAMPLESPERSEC;
995 break;
996 case UNSUPPORTED_CHANNELS :
997 rc = VSDERR_UNSUPP_CHANNELS;
998 break;
999 case UNSUPPORTED_BPS :
1000 rc = VSDERR_UNSUPP_BITSPERSAMPLE;
1001 break;
1002 case UNSUPPORTED_DATATYPE :
1003 rc = VSDERR_UNSUPP_FORMAT_TAG;
1004 break;
1005 case UNSUPPORTED_OPERATION :
1006 rc = VSDERR_UNSUPP_FORMAT_MODE;
1007 break;
1008 } /* Switch error returned from the device driver */
1009
1010 /* let calling function know the closest matching data type */
1011
1012 pInstance->sBestFitMode = audiocap.ulDataType;
1013 pInstance->ulBestFitBPS = audiocap.ulBitsPerSample;
1014 pInstance->ulBestFitChan = audiocap.ulChannels;
1015 pInstance->ulBestFitRate = audiocap.ulSamplingRate;
1016
1017 return ( rc );
1018 }
1019
1020 /*---------------------------------------------------------
1021 * The device driver will return the following information
1022 * describing streaming capabilities and resource management
1023 * information.
1024 *----------------------------------------------------------*/
1025
1026 pInstance->ulSubType = audiocap.ulDataSubType;
1027
1028 // WPOS/OS2 - Determine subtype based on sampling rate, channels etc.
1029// pInstance->ulSubType = DetermineSubType( audiocap.ulDataType,
1030// audiocap.ulBitsPerSample,
1031// audiocap.ulChannels,
1032// audiocap.ulSamplingRate );
1033
1034 pInstance->ulClass = audiocap.ulResourceClass;
1035 pInstance->ulResourcesUsed = audiocap.ulResourceUnits;
1036 pInstance->ulCanRecord = audiocap.fCanRecord;
1037 pInstance->fDriverCaps = audiocap.ulCapability | SUPPORT_CAP;
1038
1039 return (VSDERR_SUCCESS );
1040#endif
1041//-----------------------------------------------------------------------------
1042
1043//-----------------------------------------------------------------------------
1044#ifdef INCL_MM_WPOS
1045
1046 aud_request.operation = AUDIO_OPERATION_PLAY;
1047 if (pInstance->ulOperation == OPERATION_RECORD)
1048 aud_request.operation = AUDIO_OPERATION_RECORD;
1049
1050 // WPOS - Insure the sMode is the RIFF type, and not the hardware mapped
1051 // type.
1052 aud_request.data_description.format = pInstance->sMode;
1053
1054 aud_request.device_class = AUDIO_DEV_CLASS_WAVE;
1055 if (pInstance->sMode == DATATYPE_MIDI)
1056 aud_request.device_class = AUDIO_DEV_CLASS_MIDI;
1057
1058 // Set MIDI fields to O since they will already be set
1059 // up by SYSEX midi command contained with midi data.
1060 aud_request.data_description.tempo = 0;
1061 aud_request.data_description.cpqn = 0;
1062
1063 aud_request.data_description.sample_rate = pInstance->lSRate;
1064 aud_request.data_description.bits_per_sample = pInstance->lBitsPerSRate;
1065 aud_request.data_description.channel_count = pInstance->sChannels;
1066
1067 aud_request.data_description.flags = 0;
1068// if (pInstance->ulFlags & LEFT_ALIGNED)
1069// aud_request.data_description.flags |= AUDIO_DATA_LEFT_ALIGNED;
1070
1071// if (pInstance->ulFlags & BIG_ENDIAN)
1072// aud_request.data_description.flags |= AUDIO_DATA_BIG_ENDIAN;
1073
1074// if (pInstance->ulFlags & SIGNED)
1075// aud_request.data_description.flags |= AUDIO_DATA_SIGNED;
1076
1077 if (aud_request.data_description.bits_per_sample == 16) //16 bit data
1078 aud_request.data_description.flags |= AUDIO_DATA_SIGNED; //signed, two's complement
1079
1080 // AUDIO_DATA_PACKED flag not currently used.
1081
1082// krc = DD_ResourceInquire( (mach_port_t) pInstance->hFile,
1083 krc = DD_ResourceInquire( (port_t) pInstance->hFile,
1084 aud_request,
1085 &aud_require);
1086#ifdef PERFORMANCE_TRACE
1087// ulTime += PerfGetTime();
1088// strcpy(DebugBuf, "Audio capability exit: Time microseconds consumed ");
1089// _ltoa((ULONG)ulTime, LoadError, 10);
1090// strcat(DebugBuf, LoadError);
1091//
1092// console_printf(DebugBuf );
1093#endif
1094 rc = (ULONG) krc;
1095
1096 /*---------------------------------------------------------
1097 * If the IOCTL failed, or if the card doesn't support this
1098 * mode, inform the caller of the problem.
1099 *----------------------------------------------------------*/
1100
1101 //WPOS -- Should (aud_require.supported) field be checked for WPOS
1102 // to be equivalent to OS2 audiocap.ulSupport, but it can't
1103 // contain the values contained in the SWITCH statement???
1104
1105 if ( rc || aud_require.supported )
1106 {
1107 if ( rc )
1108 {
1109 // 10253 --this error is less than optimal
1110 pInstance->fDriverCaps = FALSE;
1111 return (VSDERR_HARDWARE );
1112 }
1113
1114 if( aud_require.supported & AUDIO_RES_UNSUPPORTED_RATE )
1115 {
1116 rc = VSDERR_UNSUPP_SAMPLESPERSEC;
1117 }
1118 if( aud_require.supported & AUDIO_RES_UNSUPPORTED_CHANNELS )
1119 {
1120 rc = VSDERR_UNSUPP_CHANNELS;
1121 }
1122 if( aud_require.supported & AUDIO_RES_UNSUPPORTED_BPS )
1123 {
1124 rc = VSDERR_UNSUPP_BITSPERSAMPLE;
1125 }
1126 if( aud_require.supported & AUDIO_RES_UNSUPPORTED_OPERATION )
1127 {
1128 rc = VSDERR_UNSUPP_FORMAT_MODE;
1129 }
1130 if( aud_require.supported & AUDIO_RES_UNSUPPORTED_CLASS )
1131 {
1132 rc = VSDERR_UNSUPP_CLASS;
1133 }
1134 if( aud_require.supported & AUDIO_RES_UNSUPPORTED_FORMAT )
1135 {
1136 rc = VSDERR_UNSUPP_FORMAT_TAG;
1137 }
1138 /* let calling function know the closest matching data type */
1139#ifdef MMHACK
1140 // major hack--driver not returning nearest supported rate
1141 if ( rc == VSDERR_UNSUPP_FORMAT_TAG ||
1142 rc == VSDERR_UNSUPP_BITSPERSAMPLE )
1143 {
1144 aud_require.data_description.format = DATATYPE_WAVEFORM;
1145 aud_require.data_description.bits_per_sample = 16;
1146
1147 }
1148#endif
1149
1150
1151 pInstance->sBestFitMode = aud_require.data_description.format;
1152 pInstance->ulBestFitBPS = aud_require.data_description.bits_per_sample;
1153 pInstance->ulBestFitChan = aud_require.data_description.channel_count;
1154 pInstance->ulBestFitRate = aud_require.data_description.sample_rate;
1155
1156 // If only the sampling rate was unsupported and the device driver //D15317
1157 // can support a new rate, use the new rate. //D15317
1158 if ((rc == VSDERR_UNSUPP_SAMPLESPERSEC) && //D15317
1159 (aud_request.data_description.sample_rate != aud_require.data_description.sample_rate)) //D15317
1160 { //D15317
1161 pInstance->lSRate = aud_require.data_description.sample_rate; //D15317
1162 rc = VSDERR_SUCCESS; //D15317
1163 }
1164 else //D15317
1165 return ( rc );
1166 }
1167
1168 /*---------------------------------------------------------
1169 * The device driver will return the following information
1170 * describing streaming capabilities and resource management
1171 * information.
1172 *----------------------------------------------------------*/
1173// pInstance->ulSubType = aud_require.subtype;
1174
1175 // WPOS/OS2 - Determine subtype based on sampling rate, channels etc.
1176 pInstance->ulSubType = DetermineSubType( aud_require.data_description.format,
1177 aud_require.data_description.bits_per_sample,
1178 aud_require.data_description.channel_count,
1179 aud_require.data_description.sample_rate );
1180
1181 pInstance->ulClass = aud_require.resource_class;
1182 pInstance->ulResourcesUsed = aud_require.resource_units;
1183
1184 //WPOS - Should CanRecord flag be used in Workplace???
1185// pInstance->ulCanRecord = aud_require.can_record; //removed from spec.
1186
1187 // This is always supported in Workplace.
1188 pInstance->fDriverCaps = (SUPPORT_MIX | SUPPORT_RIFF_MODES | SUPPORT_CAP);
1189
1190 return (VSDERR_SUCCESS );
1191#endif
1192//-----------------------------------------------------------------------------
1193
1194} /* CapIOCTL */
1195
1196GAINTABLE GainTable[ NUMGAINENTRIES ] =
1197
1198 { { 0 },
1199 { 6 },
1200 { 12 },
1201 { 18 },
1202 { 24 },
1203 { 30 },
1204 { 36 },
1205 { 42 },
1206 { 48 },
1207 { 54 },
1208 { 60 },
1209 { 66 },
1210 { 72 },
1211 { 78 },
1212 { 84 },
1213 { 90 },
1214 { 96 },
1215 { 100 },
1216 };
1217
1218
1219typedef struct
1220 {
1221 ULONG ulGainValue;
1222 } BOOSTGAINTABLE;
1223
1224GAINTABLE BoostGainTable[ 7 ] =
1225
1226 { { 102 },
1227 { 104 },
1228 { 106 },
1229 { 108 },
1230 { 112 },
1231 { 114 },
1232 { 116 }
1233 };
1234
1235
1236
1237
1238/************************ START OF SPECIFICATIONS **************************
1239*
1240* SUBROUTINE NAME: ModifyAudioAttributes
1241*
1242* FUNCTION: Sends IOCTL request to ACPA PDD to change audio settings
1243* Items will only be changed if the appropriate VSD_SET_xxx flag
1244* is set (i.e. VSD_SET_VOLUME, VSD_SET_TREBLE etc.). If a flag
1245* is not sent, then the AUDIO_IGNORE flag is sent to the PDD>
1246*
1247* INPUT: pInstance - pointer to VSD instance
1248*
1249* SUCCESS: VSDERR_SUCCESS
1250*
1251* FAILURE: VSD error code.
1252*
1253* OS/2 CALLS: DosDevIOCtl()
1254*
1255* C CALLS: None
1256*
1257* INTERNAL CALLS:
1258*
1259*************************** END OF SPECIFICATIONS *************************/
1260
1261LONG ModifyAudioAttributes( PVSD_INSTANCE pInstance,
1262 ULONG ulFlags )
1263{
1264
1265 LONG lError = VSDERR_SUCCESS;
1266 ULONG ulDataLen;
1267 ULONG ulParmLengthInOut = 0L;
1268 LONG rc = 0;
1269 LONG l64kCheck;
1270
1271 ULONG ulVolume;
1272 ULONG ulMicType;
1273 ULONG ulNewBalance;
1274 ULONG ulHoldVolPercentage;
1275 ULONG ulGainPercentage;
1276
1277
1278 MCI_AUDIO_CONTROL AudioControl;
1279 MCI_AUDIO_CHANGE AudioChange;
1280
1281 LPMCI_AUDIO_CHANGE prAudioChange32;
1282 LPMCI_AUDIO_CHANGE prAudioChange16;
1283
1284 MCI_TRACK_INFO rTrackInfo;
1285
1286 LPMCI_TRACK_INFO prTrackInfo16;
1287 LPMCI_TRACK_INFO prTrackInfo32;
1288
1289 BOOL fAllocatedChangeMemory = FALSE;
1290 BOOL fAllocatedTrackMemory = FALSE;
1291 extern ULONG MixMultTable[];
1292
1293
1294 if ( !pInstance->ulActive )
1295 {
1296 return ( MCIERR_SUCCESS );
1297 }
1298
1299#ifdef PERFORMANCE_TRACE
1300// console_printf("Audio change IOCTL\n");
1301#endif
1302
1303
1304 /*-----------------------------------------------------------------*
1305 * The audio card either supports the new mixer IOCTLs or it doesn't.
1306 *-----------------------------------------------------------------*/
1307
1308
1309 if ( pInstance->fHardwareMix )
1310 {
1311 MIXERCONTROL MixerControl;
1312 MixerControl.ulLength = sizeof ( MIXERCONTROL );
1313// 15552
1314 // all effects, unless specifically indicated, are local
1315 // effects.
1316 MixerControl.ulFlags = 0;
1317// 15552
1318 InitMixer( pInstance );
1319
1320 if ( ulFlags == VSD_SET_ALL )
1321 {
1322 ulFlags = VSD_SET_VOLUME;
1323 }
1324
1325 if ( ulFlags & VSD_SET_MASTER )
1326 {
1327 MixerControl.ulControl = MIX_VOLUME;
1328
1329 // if we are recording, master volume should ALWAYS be at 100,
1330 // this can affect the recording negatively if it is not @ 100%
1331
1332 MixerControl.ulLine = SINK_ALL;
1333
1334 if ( pInstance->ulOperation == OPERATION_RECORD )
1335 {
1336// MixerControl.ulLine = pInstance->ulInputDev;
1337 MixerControl.ulSetting = 100 * MIXER_MULTIPLIER;
1338
1339 }
1340 else
1341 {
1342// MixerControl.ulSetting = pInstance->ulMasterVolume * MIXER_MULTIPLIER;
1343
1344 // PPC instruction timing: 1 cycle for interger load versus
1345 // between 5 to 9 cycles for an interger multiplication
1346
1347 MixerControl.ulSetting = MixMultTable[pInstance->ulMasterVolume];
1348// MixerControl.ulLine = pInstance->ulLine;
1349 }
1350
1351 // lad--capabilty addition
1352 // ensure that line has this capability
1353
1354 if ( LineSupport( pInstance, &MixerControl ) )
1355 {
1356
1357 MixerControl.ulFlags = MIX_MASTER;
1358 lError = mixSetControl( pInstance->hMix, &MixerControl );
1359 }
1360 else
1361 {
1362 lError = MCIERR_UNSUPPORTED_FLAG;
1363 }
1364 // lad--capabilty addition
1365 }
1366
1367
1368 MixerControl.ulFlags = 0;
1369 if ( ulFlags & VSD_SET_VOLUME )
1370 {
1371
1372 MixerControl.ulControl = MIX_VOLUME;
1373 // PPC instruction timing: 1 cycle for interger load versus
1374 // between 5 to 9 cycles for an interger multiplication
1375 MixerControl.ulSetting = MixMultTable[pInstance->lLeftVolume];
1376
1377 // LAD--note, this will have to become a define.
1378
1379// MixerControl.ulSetting = pInstance->lLeftVolume * MIXER_MULTIPLIER;
1380
1381
1382 #ifdef MMHACK
1383 if ( pInstance->ulOperation == OPERATION_RECORD )
1384 {
1385 MixerControl.ulLine = pInstance->ulInputDev;
1386 }
1387 else
1388 {
1389 MixerControl.ulLine = pInstance->ulLine;
1390 }
1391 #else
1392 MixerControl.ulLine = pInstance->ulLine;
1393 #endif
1394
1395 // ensure that line has this capability
1396 // lad--capabilty addition
1397
1398 if ( LineSupport( pInstance, &MixerControl ) )
1399 {
1400 lError = mixSetControl( pInstance->hMix, &MixerControl );
1401 }
1402 else
1403 {
1404 lError = MCIERR_UNSUPPORTED_FLAG;
1405 }
1406
1407 // lad--capabilty addition
1408 }
1409
1410 if ( ulFlags & VSD_SET_MUTE )
1411 {
1412 MixerControl.ulControl = MIX_MUTE;
1413 if ( pInstance->fMute )
1414 {
1415 MixerControl.ulSetting = MixMultTable[100];
1416 }
1417 else
1418 {
1419 MixerControl.ulSetting = 0;
1420 }
1421#ifdef MMHACK
1422 if ( pInstance->ulOperation == OPERATION_RECORD )
1423 {
1424 MixerControl.ulLine = pInstance->ulInputDev;
1425 }
1426 else
1427 {
1428 MixerControl.ulLine = pInstance->ulLine;
1429 }
1430#else
1431 MixerControl.ulLine = pInstance->ulLine;
1432#endif
1433
1434 // ensure that line has this capability
1435 // lad--capabilty addition
1436
1437 if ( LineSupport( pInstance, &MixerControl ) )
1438 {
1439 lError = mixSetControl( pInstance->hMix, &MixerControl );
1440 }
1441 else
1442 {
1443 lError = MCIERR_UNSUPPORTED_FLAG;
1444 }
1445 } // set mute state
1446
1447
1448
1449 if ( ulFlags & VSD_SET_BALANCE )
1450 {
1451 MixerControl.ulControl = MIX_BALANCE;
1452
1453 // LAD--note, this will have to become a define.
1454
1455// MixerControl.ulSetting = pInstance->lBalance * MIXER_MULTIPLIER;
1456 // PPC instruction timing: 1 cycle for interger load versus
1457 // between 5 to 9 cycles for an interger multiplication
1458
1459 MixerControl.ulSetting = MixMultTable[pInstance->lBalance];
1460
1461#ifdef MMHACK
1462 if ( pInstance->ulOperation == OPERATION_RECORD )
1463 {
1464 MixerControl.ulLine = pInstance->ulInputDev;
1465 }
1466 else
1467 {
1468 MixerControl.ulLine = pInstance->ulLine;
1469 }
1470#else
1471 MixerControl.ulLine = pInstance->ulLine;
1472#endif
1473
1474 // ensure that line has this capability
1475 // lad--capabilty addition
1476
1477 if ( LineSupport( pInstance, &MixerControl ) )
1478 {
1479 lError = mixSetControl( pInstance->hMix, &MixerControl );
1480 }
1481 else
1482 {
1483 lError = MCIERR_UNSUPPORTED_FLAG;
1484 }
1485 // lad--capabilty addition
1486 }
1487
1488 // 10253 -- new mixer interface will redefine treble/bass--wait till
1489 // drivers are ready
1490
1491 if ( ulFlags & VSD_SET_TREBLE )
1492 {
1493 MixerControl.ulControl = MIX_TREBLE;
1494
1495 // LAD--note, this will have to become a define.
1496
1497// MixerControl.ulSetting = pInstance->lTreble * MIXER_MULTIPLIER;
1498 // PPC instruction timing: 1 cycle for interger load versus
1499 // between 5 to 9 cycles for an interger multiplication
1500
1501 MixerControl.ulSetting = MixMultTable[pInstance->lTreble];
1502
1503#ifdef MMHACK
1504 if ( pInstance->ulOperation == OPERATION_RECORD )
1505 {
1506 MixerControl.ulLine = pInstance->ulInputDev;
1507 }
1508 else
1509 {
1510 MixerControl.ulLine = pInstance->ulLine;
1511 }
1512#else
1513 MixerControl.ulLine = pInstance->ulLine;
1514#endif
1515
1516 // ensure that line has this capability
1517 // lad--capabilty addition
1518
1519 if ( LineSupport( pInstance, &MixerControl ) )
1520 {
1521 lError = mixSetControl( pInstance->hMix, &MixerControl );
1522 }
1523 else
1524 {
1525 lError = MCIERR_UNSUPPORTED_FLAG;
1526 }
1527 // lad--capabilty addition
1528 }
1529
1530
1531 // 10253 -- new mixer interface will redefine treble/bass--wait till
1532 // drivers are ready
1533
1534 if ( ulFlags & VSD_SET_GAIN )
1535 {
1536 MixerControl.ulControl = MIX_GAIN;
1537
1538 // LAD--note, this will have to become a define.
1539
1540// MixerControl.ulSetting = pInstance->ulGainLevel * MIXER_MULTIPLIER;
1541 // PPC instruction timing: 1 cycle for interger load versus
1542 // between 5 to 9 cycles for an interger multiplication
1543
1544 MixerControl.ulSetting = MixMultTable[pInstance->ulGainLevel];
1545
1546// 16235
1547 MixerControl.ulLine = pInstance->ulInputDev;
1548
1549// 16235
1550 // ensure that line has this capability
1551 // lad--capabilty addition
1552
1553 if ( LineSupport( pInstance, &MixerControl ) )
1554 {
1555 lError = mixSetControl( pInstance->hMix, &MixerControl );
1556 }
1557 else
1558 {
1559 lError = MCIERR_UNSUPPORTED_FLAG;
1560 }
1561 // lad--capabilty addition
1562 }
1563
1564
1565 if ( ulFlags & VSD_SET_BASS )
1566 {
1567 MixerControl.ulControl = MIX_BASS;
1568
1569 // LAD--note, this will have to become a define.
1570
1571// MixerControl.ulSetting = pInstance->lBass * MIXER_MULTIPLIER;
1572 // PPC instruction timing: 1 cycle for interger load versus
1573 // between 5 to 9 cycles for an interger multiplication
1574
1575 MixerControl.ulSetting = MixMultTable[pInstance->lBass];
1576
1577#ifdef MMHACK
1578 if ( pInstance->ulOperation == OPERATION_RECORD )
1579 {
1580 MixerControl.ulLine = pInstance->ulInputDev;
1581 }
1582 else
1583 {
1584 MixerControl.ulLine = pInstance->ulLine;
1585 }
1586#else
1587 MixerControl.ulLine = pInstance->ulLine;
1588#endif
1589
1590 // ensure that line has this capability
1591 // lad--capabilty addition
1592
1593 if ( LineSupport( pInstance, &MixerControl ) )
1594 {
1595 lError = mixSetControl( pInstance->hMix, &MixerControl );
1596 }
1597 else
1598 {
1599 lError = MCIERR_UNSUPPORTED_FLAG;
1600 }
1601 // lad--capabilty addition
1602 }
1603
1604 // 10253 -- this is still to be determined
1605
1606 if ( ulFlags & VSD_SET_MONITOR )
1607 {
1608 MixerControl.ulControl = MIX_MONITOR;
1609
1610 // LAD--note, this will have to become a define.
1611
1612 if ( pInstance->lMonitor )
1613 {
1614 MixerControl.ulSetting = 100 * MIXER_MULTIPLIER;
1615 }
1616 else
1617 {
1618 MixerControl.ulSetting = 0;
1619 }
1620
1621
1622// 16235
1623 MixerControl.ulLine = pInstance->ulInputDev;
1624// 16235
1625
1626 // ensure that line has this capability
1627 // lad--capabilty addition
1628
1629 if ( LineSupport( pInstance, &MixerControl ) )
1630 {
1631 lError = mixSetControl( pInstance->hMix, &MixerControl );
1632 }
1633 else
1634 {
1635 lError = MCIERR_UNSUPPORTED_FLAG;
1636 }
1637 // lad--capabilty addition
1638 }
1639
1640 if ( ulFlags & VSD_SET_PITCH )
1641 {
1642 MixerControl.ulControl = MIX_PITCH;
1643
1644 // LAD--note, this will have to become a define.
1645
1646// MixerControl.ulSetting = pInstance->lPitch * MIXER_MULTIPLIER;
1647 // PPC instruction timing: 1 cycle for interger load versus
1648 // between 5 to 9 cycles for an interger multiplication
1649
1650 MixerControl.ulSetting = MixMultTable[pInstance->lPitch];
1651
1652#ifdef MMHACK
1653 if ( pInstance->ulOperation == OPERATION_RECORD )
1654 {
1655 MixerControl.ulLine = pInstance->ulInputDev;
1656 }
1657 else
1658 {
1659 MixerControl.ulLine = pInstance->ulLine;
1660 }
1661#else
1662 MixerControl.ulLine = pInstance->ulLine;
1663#endif
1664
1665 // ensure that line has this capability
1666 // lad--capabilty addition
1667
1668 if ( LineSupport( pInstance, &MixerControl ) )
1669 {
1670 lError = mixSetControl( pInstance->hMix, &MixerControl );
1671 }
1672 else
1673 {
1674 lError = MCIERR_UNSUPPORTED_FLAG;
1675 }
1676 // lad--capabilty addition
1677 }
1678
1679 } // if new hardware mixer is active
1680
1681 else
1682
1683 //WPOS - This path should not be taken for WPOS code, only OS/2 code.
1684 {
1685// 15552--need to allocate memory
1686#ifndef INCL_MM_WPOS
1687
1688 memset(&AudioChange, 0, sizeof(MCI_AUDIO_CHANGE)); //@12258
1689
1690 if ( ulFlags == VSD_SET_MASTER )
1691 {
1692 ulFlags = VSD_SET_ALL;
1693 }
1694
1695 if ( ulFlags & VSD_SET_VOLUME )
1696 {
1697 /*-----------------------------------------------------------------*
1698 * Place level values in ACPA control structures
1699 *-----------------------------------------------------------------*/
1700
1701
1702 ulVolume = pInstance->lLeftVolume;
1703
1704 /*-----------------------------------------------------------------*
1705 * If the user has turned off the audio, set the volume to zero
1706 * so nothing can be heard.
1707 *-----------------------------------------------------------------*/
1708
1709 if ( pInstance->fMute )
1710 {
1711 ulVolume = 0;
1712 }
1713
1714 ulNewBalance = pInstance->lBalance;
1715
1716 ulVolume *= AUDIOIF_MULTIPLIER;
1717 ulHoldVolPercentage = ulVolume / 100;
1718
1719 rTrackInfo.usDitherPct = 0;
1720
1721 if ( pInstance->ulDeviceID == MACPA )
1722 {
1723
1724 // if the line in port is enable, increase recording quality
1725
1726 if (StatusIOPort( STEREO_LINE_INPUT, pInstance, INPUT_PORT ) == MCI_TRUE )
1727 {
1728 // we only want to adjust the volume if we are below 70
1729 if ( pInstance->ulGainLevel <= 70 )
1730 {
1731 ulGainPercentage = GainTable[ pInstance->ulGainLevel / 4 ].ulGainValue;
1732 ulVolume = ulHoldVolPercentage * ulGainPercentage;
1733 rTrackInfo.usMasterVolume = ( USHORT ) (pInstance->ulMasterVolume * AUDIOIF_DIVISOR);
1734 }
1735 else
1736 {
1737 ulGainPercentage = BoostGainTable[ (pInstance->ulGainLevel - 70) / 5 ].ulGainValue;
1738 rTrackInfo.usMasterVolume = ( USHORT ) (ulGainPercentage * AUDIOIF_DIVISOR);
1739 } /* else gain > 70 */
1740
1741 }
1742 else
1743 {
1744 if ( pInstance->ulGainLevel >= 70 )
1745 {
1746 ulMicType = BOOSTED_MIC_INPUT;
1747 }
1748 else
1749 {
1750 ulMicType = MIC_INPUT;
1751 }
1752 if ( StatusIOPort( ulMicType, pInstance, INPUT_PORT ) != MCI_TRUE )
1753 {
1754 lError = AddIOPort( ulMicType,
1755 pInstance,
1756 INPUT_PORT );
1757 }
1758
1759 rTrackInfo.usMasterVolume = ( USHORT ) (pInstance->ulMasterVolume * AUDIOIF_DIVISOR);
1760
1761 }
1762 } /* If we are working around acpa gain problems */
1763 else
1764 {
1765 // if we are recording, master volume should ALWAYS be at 100,
1766 // this can affect the recording negatively if it is not @ 100%
1767
1768 if ( pInstance->ulOperation == OPERATION_RECORD )
1769 {
1770 rTrackInfo.usMasterVolume = ( USHORT ) (100 * AUDIOIF_DIVISOR);
1771 }
1772 else
1773 {
1774 rTrackInfo.usMasterVolume = ( USHORT ) (pInstance->ulMasterVolume * AUDIOIF_DIVISOR);
1775 }
1776
1777 AudioChange.lGain = pInstance->ulGainLevel * AUDIOIF_MULTIPLIER;
1778
1779 } /* The card should be able to handle gain */
1780
1781 // if the amp stream connector is currently active, then set the volume
1782 // otherwise ensure that it is 0
1783
1784 AudioChange.lVolume = (LONG) ulVolume;
1785
1786
1787 AudioChange.lVolumeDelay = pInstance->lVolumeDelay ;
1788
1789
1790 } /* if the caller wants to set the volume field */
1791 else
1792 {
1793 AudioChange.lVolume = AUDIO_IGNORE;
1794 AudioChange.lVolumeDelay = AUDIO_IGNORE;
1795
1796 } /* Caller does not want to set balance */
1797
1798 if ( ulFlags & VSD_SET_BALANCE )
1799 {
1800 // if we exceed the correct amount reduce the quantity
1801 AudioChange.lBalance = (LONG) ulNewBalance * AUDIOIF_MULTIPLIER;
1802 rTrackInfo.usMasterBalance = (LONG) ulNewBalance * AUDIOIF_MULTIPLIER;
1803
1804 if ( !pInstance->lBalanceDelay )
1805 {
1806 AudioChange.lBalanceDelay = pInstance->lVolumeDelay;
1807 }
1808 else
1809 {
1810 AudioChange.lBalanceDelay = pInstance->lBalanceDelay;
1811 }
1812
1813 }
1814 else
1815 {
1816 rTrackInfo.usMasterVolume = AUDIO_IGNORE;
1817 rTrackInfo.usMasterBalance = AUDIO_IGNORE;
1818 AudioChange.lBalance = AUDIO_IGNORE;
1819 AudioChange.lBalanceDelay = AUDIO_IGNORE;
1820 } /* caller did not want to set the treble option */
1821
1822
1823
1824
1825 if ( ulFlags & VSD_SET_TREBLE )
1826 {
1827
1828 AudioChange.lTreble = (LONG) pInstance->lTreble * AUDIOIF_MULTIPLIER;
1829 }
1830 else
1831 {
1832 AudioChange.lTreble = AUDIO_IGNORE;
1833 } /* caller did not want to set the treble option */
1834
1835 if ( ulFlags & VSD_SET_BASS )
1836 {
1837 AudioChange.lBass = (LONG) pInstance->lBass * AUDIOIF_MULTIPLIER ;
1838 }
1839 else
1840 {
1841 AudioChange.lBass = AUDIO_IGNORE;
1842 }
1843
1844 if ( ulFlags & VSD_SET_PITCH )
1845 {
1846
1847 AudioChange.lPitch = (LONG) pInstance->lPitch * AUDIOIF_MULTIPLIER;
1848 }
1849 else
1850 {
1851 AudioChange.lPitch = AUDIO_IGNORE;
1852 } /* Caller wants to set pitch */
1853
1854 if ( ulFlags & VSD_SET_MONITOR )
1855 {
1856
1857
1858 if ( pInstance->lMonitor )
1859 {
1860 AudioChange.lMonitor = MONITOR_UNCOMPRESSED;
1861 }
1862 else
1863 {
1864 AudioChange.lMonitor = MONITOR_OFF;
1865 }
1866 } /* caller wants to set monitor flag */
1867 else
1868 {
1869 AudioChange.lMonitor = AUDIO_IGNORE;
1870
1871 } /* Caller wants to set monitor */
1872
1873 /*-----------------------------------------------------------------*
1874 * Convert pointers to 16 bit
1875 *-----------------------------------------------------------------*/
1876
1877 prAudioChange32 = &AudioChange;
1878
1879 /* Check to see if pointer crosses 64k boundary */
1880
1881 l64kCheck = LOUSHORT(prAudioChange32) ;
1882
1883 /* If the address crosses a 64k boundary--allocate the memory instead */
1884
1885 if ( l64kCheck > 65500 )
1886 {
1887 rc = DosAllocSharedMem((PVOID)&prAudioChange32,
1888 NULL,
1889 sizeof( MCI_AUDIO_CHANGE ),
1890 PAG_COMMIT | OBJ_GIVEABLE |
1891 PAG_READ | PAG_WRITE);
1892
1893 lError = MCI_Error(rc);
1894 if ( lError )
1895 {
1896 return ( lError );
1897 }
1898
1899
1900 fAllocatedChangeMemory = TRUE;
1901 /* Copy the data into the allocated buffer */
1902
1903 memmove(prAudioChange32, &AudioChange, sizeof( MCI_AUDIO_CHANGE ) );
1904
1905 prAudioChange16 = ( PVOID ) MAKEULONG( LOUSHORT(prAudioChange32),
1906 (HIUSHORT(prAudioChange32) << 3) + 7);
1907
1908 }
1909
1910 else
1911 {
1912 prAudioChange16 = ( PVOID ) MAKEULONG( LOUSHORT(prAudioChange32),
1913 (HIUSHORT(prAudioChange32) << 3) + 7);
1914 }
1915
1916 AudioControl.pbRequestInfo = prAudioChange16;
1917
1918 prTrackInfo32 = &rTrackInfo;
1919
1920 /* Check to see if pointer crosses 64k boundary */
1921
1922 l64kCheck = LOUSHORT(prTrackInfo32) ;
1923
1924 /* If the address crosses a 64k boundary--allocate the memory instead */
1925
1926 if ( l64kCheck > 65500 )
1927 {
1928 rc = DosAllocSharedMem((PVOID)&prTrackInfo32,
1929 NULL,
1930 sizeof( MCI_TRACK_INFO ),
1931 PAG_COMMIT | OBJ_GIVEABLE |
1932 PAG_READ | PAG_WRITE);
1933
1934 lError = MCI_Error(rc);
1935 if ( lError )
1936 {
1937 return ( lError );
1938 }
1939
1940
1941 fAllocatedTrackMemory = TRUE;
1942 /* Copy the data into the allocated buffer */
1943
1944 memmove(prTrackInfo32, &rTrackInfo, sizeof( MCI_TRACK_INFO ) );
1945
1946 prTrackInfo16 = ( PVOID ) MAKEULONG ( LOUSHORT(prTrackInfo32),
1947 (HIUSHORT(prTrackInfo32) << 3) + 7);
1948
1949 }
1950
1951 else
1952 {
1953 prTrackInfo16 = ( PVOID ) MAKEULONG ( LOUSHORT(prTrackInfo32),
1954 (HIUSHORT(prTrackInfo32) << 3) + 7);
1955 } /* stack variable is safe to use */
1956
1957
1958 AudioChange.pvDevInfo = prTrackInfo16;
1959
1960 /*-----------------------------------------------------------------*
1961 * Informat the AUDIODD which connectors (i.e. speakers, line etc.)
1962 * will be enabled.
1963 *-----------------------------------------------------------------*/
1964
1965
1966 Set_IO_Ports( &AudioChange, pInstance, ulFlags );
1967
1968 /*-----------------------------------------------------------------*
1969 * Make the IOCtl call
1970 *-----------------------------------------------------------------*/
1971
1972 AudioControl.usIOCtlRequest = AUDIO_CHANGE;
1973 AudioControl.ulPosition = 0L;
1974 AudioControl.sReturnCode = 0;
1975
1976 ulDataLen = sizeof(MCI_AUDIO_CONTROL);
1977
1978 AudioChange.pvModeInfo = 0;
1979
1980//-----------------------------------------------------------------------------
1981#ifdef INCL_MM_OS2
1982 rc = DosDevIOCtl(pInstance->hFile,
1983 AUDIO_IOCTL_CAT,
1984 AUDIO_CONTROL,
1985 0,
1986 0L,
1987 &ulParmLengthInOut,
1988 &AudioControl,
1989 (ULONG) sizeof(MCI_AUDIO_CONTROL),
1990 &ulDataLen);
1991#endif
1992//-----------------------------------------------------------------------------
1993
1994//-----------------------------------------------------------------------------
1995#ifdef INCL_MM_WPOS
1996 //WPOS - this code should not be executed for Workplace OS.
1997#endif
1998//-----------------------------------------------------------------------------
1999
2000 lError = MCI_Error(rc);
2001
2002 pInstance->lBalanceDelay = pInstance->lVolumeDelay = 0;
2003// 15552--need to allocate memory
2004#endif
2005
2006 } /* we are using the older/less functional AUDIODD interface */
2007
2008// 15552--need to allocate memory
2009#ifndef INCL_MM_WPOS
2010
2011 if ( fAllocatedTrackMemory )
2012 {
2013 DosFreeMem(prTrackInfo32);
2014
2015 }
2016
2017 if ( fAllocatedChangeMemory )
2018 {
2019 DosFreeMem(prAudioChange32);
2020
2021 }
2022
2023// 15552--need to allocate memory
2024#endif
2025 return(lError);
2026
2027
2028} /* ModifyAudioAttributes */
2029
2030
2031
2032
2033/************************** START OF SPECIFICATIONS ************************
2034* *
2035* SUBROUTINE NAME: CloseDevice *
2036* *
2037* DESCRIPTIVE NAME: Opens the audio device. *
2038* *
2039* FUNCTION: Returns if a particular port is currently active. *
2040* *
2041* NOTES: This function will close the audio device. *
2042* *
2043* INPUT: PVSD_INSTANCE *
2044* *
2045*************************** END OF SPECIFICATIONS **************************/
2046LONG CloseDevice ( PVSD_INSTANCE pInstance )
2047
2048{
2049
2050#ifdef PERFORMANCE_TRACE
2051// console_printf("Closing device\n");
2052#endif
2053
2054//-----------------------------------------------------------------------------
2055#ifdef INCL_MM_OS2
2056 return ( DosClose( pInstance->hFile ) );
2057#endif
2058//-----------------------------------------------------------------------------
2059
2060//-----------------------------------------------------------------------------
2061#ifdef INCL_MM_WPOS
2062// return ( DD_Close( (mach_port_t) pInstance->hFile, 0 ) );
2063 return ( DD_Close( (port_t) pInstance->hFile, 0 ) );
2064#endif
2065//-----------------------------------------------------------------------------
2066} /* CloseDevice */
2067
2068/************************** START OF SPECIFICATIONS ************************
2069* *
2070* SUBROUTINE NAME: InitMixer *
2071* *
2072* DESCRIPTIVE NAME: Ensures that wave/midi input lines are correctly *
2073* enabled *
2074* *
2075* Input Output *
2076* ------------------------------------- *
2077* | | *
2078* Wave Output - | |- *
2079* Synth Output- | Mixer Device |- *
2080* /\ - | |-Wave Input *
2081* | | | /\ *
2082* | - | | | *
2083* | | | | *
2084* | ------------------------------------ | *
2085* Enable for playback | *
2086* Enable for Record *
2087*************************** END OF SPECIFICATIONS **************************/
2088LONG InitMixer ( PVSD_INSTANCE pInstance )
2089
2090{
2091 LINECONNECTIONS mixinfo;
2092// 15552
2093 BOOL fSetConnRequired = TRUE;
2094 ULONG rc = MCIERR_SUCCESS;
2095// 15552
2096 extern ULONG ulInputDevice;
2097 extern ULONG ulOutputDevice;
2098 extern HMTX hmtxProcessSemVSD;
2099
2100 mixinfo.ulLength = sizeof ( LINECONNECTIONS );
2101
2102
2103 /* Have we connected the default wave in/wave out lines? */
2104
2105 if ( !pInstance->lOutput )
2106 {
2107 /*-------------------------------------
2108 * MIDI uses a different mixer line that
2109 * PCM so ensure the correct mixer line
2110 * is created.
2111 *-------------------------------------*/
2112
2113 if ( pInstance->sMode == DATATYPE_MIDI)
2114 {
2115 /* MIDI volume, bass, treble etc. will go to the synth input */
2116
2117 mixinfo.ulLine = pInstance->ulLine;
2118
2119 /* Connect MIDI output to output device (i.e. speakers etc.) */
2120
2121 mixinfo.ulConnection = pInstance->ulOutputDev;
2122 }
2123 else
2124 {
2125
2126// 15552
2127
2128 DosRequestMutexSem ( hmtxProcessSemVSD, SEM_INDEFINITE_WAIT);
2129// 15552
2130 /*-------------------------------------
2131 * If we are in record mode, then enable
2132 * the correct record mixer lines
2133 *-------------------------------------*/
2134
2135// if ( pInstance->ulOperation == MCIDRV_INPUT )
2136 if ( pInstance->ulOperation == OPERATION_RECORD )
2137 {
2138 mixinfo.ulLine = pInstance->ulInputDev;
2139 mixinfo.ulConnection =
2140 pInstance->ulLine = SINK_WAVE;
2141 // determine if the instance connection matches with
2142 // the global connection.
2143
2144 if ( pInstance->ulInputDev == ulInputDevice )
2145 {
2146 fSetConnRequired = FALSE;
2147 }
2148 }
2149
2150 /*-------------------------------------
2151 * else we are in playback mode, so enable
2152 * the wave output to speaker/etc.
2153 *-------------------------------------*/
2154 else
2155 {
2156 mixinfo.ulLine =
2157 pInstance->ulLine = SOURCE_WAVE;
2158 mixinfo.ulConnection = pInstance->ulOutputDev;
2159
2160 // determine if the instance connection matches with
2161 // the global connection.
2162
2163 if ( OutputConnectionMatch(pInstance->ulOutputDev, TRUE) )
2164 {
2165 fSetConnRequired = FALSE;
2166 }
2167 } /* else we are in playback mode */
2168
2169 } /* not MIDI--so must be PCM */
2170
2171 pInstance->lOutput = TRUE;
2172
2173 if ( fSetConnRequired )
2174 {
2175 /*-------------------------------
2176 * Enable the desired mixer line
2177 *-------------------------------*/
2178 rc = ( mixSetConnections ( pInstance->hMix, &mixinfo ) );
2179 }
2180
2181// 15552
2182 DosReleaseMutexSem (hmtxProcessSemVSD);
2183 return ( rc );
2184// 15552
2185 } /* we haven't enabled a default mixer line */
2186 else
2187 {
2188 return ( MCIERR_SUCCESS );
2189 }
2190} /* CloseDevice */
2191
2192
2193
2194/************************ START OF SPECIFICATIONS **************************
2195*
2196* SUBROUTINE NAME: DetermineSubType
2197*
2198* FUNCTION: Determine the sub type of the data format based on the data type,
2199* sampling rate , number of channels, and bits per sample.
2200*
2201* INPUT: ulFormat - data type
2202* ulBitsPerSample - number of bits per sample
2203* ulChannelCount - number of channels
2204* ulSampleRate - sampling rate
2205*
2206* SUCCESS: Returned SubType
2207*
2208* FAILURE: VSD error code (-1)
2209*
2210* C CALLS: None
2211*
2212* INTERNAL CALLS:
2213*
2214*************************** END OF SPECIFICATIONS *************************/
2215
2216ULONG DetermineSubType( ULONG ulFormat,
2217 ULONG ulBitsPerSample,
2218 ULONG ulChannelCount,
2219 ULONG ulSampleRate )
2220
2221{
2222
2223 ULONG ulSubType = 0;
2224
2225 if (ulFormat == DATATYPE_MIDI)
2226 {
2227 ulSubType = SUBTYPE_NONE;
2228 }
2229 else if (ulBitsPerSample == 8)
2230 {
2231 // LAD--this is PPC specific code and is going to cause a problem
2232 // on Intel, the Device driver supplies this information (as it should)
2233 // on PPC, there is a mapping. When future drivers are available,
2234 // this will cause a problem.
2235 // Net: PPC DD interface should be enhanced to return this info.
2236
2237 if ( ulFormat == DATATYPE_MULAW ||
2238 ulFormat == DATATYPE_RIFF_MULAW ||
2239 ulFormat == DATATYPE_ALAW ||
2240 ulFormat == DATATYPE_RIFF_ALAW)
2241 {
2242 if (ulChannelCount == 1)
2243 { // 8-bit mono
2244 if (ulSampleRate <= HZ_8000)
2245 {
2246 ulSubType = MULAW_8B8KM;
2247 }
2248 else if (ulSampleRate <= HZ_11025)
2249 {
2250 ulSubType = MULAW_8B11KM;
2251 }
2252 else if (ulSampleRate <= HZ_22050)
2253 {
2254 ulSubType = MULAW_8B22KM;
2255 }
2256 else
2257 {
2258 ulSubType = MULAW_8B44KM;
2259 }
2260 }
2261 else // 8bit, stereo
2262 {
2263 if (ulSampleRate <= HZ_8000)
2264 {
2265 ulSubType = MULAW_8B8KS;
2266 }
2267 else if (ulSampleRate <= HZ_11025)
2268 {
2269 ulSubType = MULAW_8B11KS;
2270 }
2271 else if (ulSampleRate <= HZ_22050)
2272 {
2273 ulSubType = MULAW_8B22KS;
2274 }
2275 else
2276 {
2277 ulSubType = MULAW_8B44KS;
2278 }
2279 }
2280
2281 } // if mulaw
2282
2283
2284 else // must be PCM
2285 {
2286
2287 if (ulChannelCount == 1)
2288 { // 8-bit mono
2289 if (ulSampleRate <= HZ_8000)
2290 {
2291 ulSubType = WAVE_FORMAT_8M08;
2292 }
2293 else if (ulSampleRate <= HZ_11025)
2294 {
2295 ulSubType = WAVE_FORMAT_1M08;
2296 }
2297 else if (ulSampleRate <= HZ_22050)
2298 {
2299 ulSubType = WAVE_FORMAT_2M08;
2300 }
2301 else
2302 {
2303 ulSubType = WAVE_FORMAT_4M08;
2304 }
2305 }
2306 else // 8bit, stereo
2307 {
2308 if (ulSampleRate <= HZ_8000)
2309 {
2310 ulSubType = WAVE_FORMAT_8S08;
2311 }
2312 else if (ulSampleRate <= HZ_11025)
2313 {
2314 ulSubType = WAVE_FORMAT_1S08;
2315 }
2316 else if (ulSampleRate <= HZ_22050)
2317 {
2318 ulSubType = WAVE_FORMAT_2S08;
2319 }
2320 else
2321 {
2322 ulSubType = WAVE_FORMAT_4S08;
2323 }
2324 }
2325 } // else--it is PCM
2326 }
2327 else
2328 {
2329 if (ulChannelCount == 1)
2330 { // 16-bit mono
2331 if (ulSampleRate <= HZ_8000)
2332 {
2333 ulSubType = WAVE_FORMAT_8M16;
2334 }
2335 else if (ulSampleRate <= HZ_11025)
2336 {
2337 ulSubType = WAVE_FORMAT_1M16;
2338 }
2339 else if (ulSampleRate <= HZ_22050)
2340 {
2341 ulSubType = WAVE_FORMAT_2M16;
2342 }
2343 else
2344 {
2345 ulSubType = WAVE_FORMAT_4M16;
2346 }
2347 }
2348 else // 16bit, stereo
2349 {
2350 if (ulSampleRate <= HZ_8000)
2351 {
2352 ulSubType = WAVE_FORMAT_8S16;
2353 }
2354 else if (ulSampleRate <= HZ_11025)
2355 {
2356 ulSubType = WAVE_FORMAT_1S16;
2357 }
2358 else if (ulSampleRate <= HZ_22050)
2359 {
2360 ulSubType = WAVE_FORMAT_2S16;
2361 }
2362 else
2363 {
2364 ulSubType = WAVE_FORMAT_4S16;
2365 }
2366 }
2367 }
2368 return ulSubType;
2369}
2370
2371
2372 // lad--capabilty addition
2373/************************** START OF SPECIFICATIONS ************************
2374* *
2375* SUBROUTINE NAME: DetermineLineCaps *
2376* *
2377* DESCRIPTIVE NAME: Determines the capabilities (i.e. volume/treble/bass *
2378* etc. which a line supports). *
2379* *
2380* Input Output *
2381* ------------------------------------- *
2382* | | *
2383* Wave Output - | |- *
2384* Synth Output- | Mixer Device |- *
2385* /\ - | |-Wave Input *
2386* | | | /\ *
2387* | - | | | *
2388* | | | | *
2389* | ------------------------------------ | *
2390* Volume/Treble/Bass support flags | *
2391* Volume/Treble etc. flags*
2392*************************** END OF SPECIFICATIONS **************************/
2393void DetermineLineCaps( PVSD_INSTANCE pInstance )
2394
2395{
2396 ULONG ulLoop;
2397 MIXERLINEINFO mixerInfo;
2398 ULONG lError;
2399 PDRIVER_LINECAPS pdriverLineCaps;
2400
2401// 15552p--optimize for global variables.
2402
2403 // See if we have already queried the capabilities for
2404 // the given device.
2405
2406 FindDeviceCaps( pInstance, &pdriverLineCaps );
2407
2408 // if the device has not been added to memory OR
2409 // we have not obtained the global capabilities of the
2410 // device yet
2411
2412 if ( !pdriverLineCaps )
2413 {
2414 // No: we haven't seen this device before. Allocate
2415 // memory to store its capabilities.
2416
2417 lError = AddDeviceCaps( pInstance, &pdriverLineCaps );
2418
2419 if ( !lError )
2420 {
2421 pdriverLineCaps->lineCaps[ 0 ].ulLine = SOURCE_SYNTHESIZER ;
2422 pdriverLineCaps->lineCaps[ 1 ].ulLine = SOURCE_LINE ;
2423 pdriverLineCaps->lineCaps[ 2 ].ulLine = SOURCE_INTERNAL_AUDIO;
2424 pdriverLineCaps->lineCaps[ 3 ].ulLine = SOURCE_MICROPHONE ;
2425 pdriverLineCaps->lineCaps[ 4 ].ulLine = SOURCE_WAVE ;
2426 pdriverLineCaps->lineCaps[ 5 ].ulLine = SOURCE_PC_SPEAKER ;
2427 pdriverLineCaps->lineCaps[ 6 ].ulLine = SINK_LINE_OUT ;
2428 pdriverLineCaps->lineCaps[ 7 ].ulLine = SINK_SPEAKER ;
2429 pdriverLineCaps->lineCaps[ 8 ].ulLine = SINK_HEADPHONES ;
2430 pdriverLineCaps->lineCaps[ 9 ].ulLine = SINK_NULL ;
2431 pdriverLineCaps->lineCaps[10 ].ulLine = SINK_ALL ;
2432 pdriverLineCaps->lineCaps[11 ].ulLine = SINK_WAVE ;
2433 pdriverLineCaps->lineCaps[12 ].ulLine = SINK_MIDI ;
2434 pdriverLineCaps->lineCaps[13 ].ulLine = SOURCE_MIDI ;
2435
2436
2437
2438 for ( ulLoop = 0; ulLoop < NUM_SOURCES + NUM_SINKS; ulLoop++ )
2439 {
2440 // get the capabilities for each line
2441 mixerInfo.ulLine = pdriverLineCaps->lineCaps[ulLoop].ulLine;
2442 lError = mixGetLineInfo( pInstance->hMix, &mixerInfo );
2443 if ( !lError )
2444 {
2445 // 15552p--optimize for global variables.
2446 pdriverLineCaps->lineCaps[ulLoop].ulSupport = mixerInfo.ulSupport ;
2447 // 15552p--optimize for global variables.
2448 }
2449
2450 }
2451 // ensure that global variable for device caps is set.
2452
2453 pdriverLineCaps->fFlags = TRUE;
2454 } // able to allocate memory for global capabilities.
2455
2456 } // if we haven't determine line caps for the device.
2457
2458 // 15552--optimize for global variables.
2459} /* DetermineLineCaps */
2460
2461
2462/************************** START OF SPECIFICATIONS ************************
2463* *
2464* SUBROUTINE NAME: LineSupport *
2465* *
2466* DESCRIPTIVE NAME: Returns if a line supports a given audio attributes *
2467* (such as volume/treble/bass etc.) *
2468* *
2469* Input Output *
2470* ------------------------------------- *
2471* | | *
2472* Wave Output - | |- *
2473* Synth Output- | Mixer Device |- *
2474* /\ - | |-Wave Input *
2475* | | | /\ *
2476* | - | | | *
2477* | | | | *
2478* | ------------------------------------ | *
2479* Volume/Treble/Bass support flags | *
2480* Volume/Treble etc. flags*
2481*************************** END OF SPECIFICATIONS **************************/
2482BOOL LineSupport( PVSD_INSTANCE pInstance,
2483 PMIXERCONTROL pMixControl)
2484
2485{
2486 ULONG ulLoop = 0;
2487 BOOL fAnswer = FALSE;
2488 PDRIVER_LINECAPS pdriverLineCaps;
2489
2490 FindDeviceCaps( pInstance, &pdriverLineCaps );
2491
2492
2493 while ( ulLoop < NUM_SOURCES + NUM_SINKS )
2494 {
2495
2496 // get the capabilities for each line
2497// if ( driverLineCaps.lineCaps[ulLoop].ulLine == pMixControl->ulLine)
2498 if ( pdriverLineCaps->lineCaps[ulLoop].ulLine & pMixControl->ulLine)
2499 {
2500 // does the line support this audio control?????
2501 if ( pdriverLineCaps->lineCaps[ulLoop].ulSupport & pMixControl->ulControl)
2502 {
2503 fAnswer = TRUE;
2504 }
2505 break;
2506 }
2507 // advance to next line
2508 ulLoop++;
2509 }
2510 return ( fAnswer );
2511
2512} /* LineCaps */
2513
2514
2515#ifdef INCL_MM_WPOS
2516
2517
2518/************************** START OF SPECIFICATIONS ************************
2519* *
2520* SUBROUTINE NAME: RemoveDevicePorts *
2521* *
2522* DESCRIPTIVE NAME: Removes linked list of global capabilities. Only *
2523* called when last process is terminating. *
2524* *
2525*************************** END OF SPECIFICATIONS **************************/
2526void RemoveDevicePorts( void )
2527
2528{
2529
2530 extern HHUGEHEAP hhpHeapVSD;
2531 PDRIVER_PORT pTemp;
2532
2533 // allocate the memory
2534 pTemp = pDriverPort;
2535
2536 while ( pDriverPort )
2537 {
2538 pTemp = pDriverPort->pNext;
2539 HhpFreeMem(hhpHeapVSD, ( PVOID) pDriverPort );
2540
2541 // advance to next routine
2542
2543 pDriverPort = pTemp;
2544 }
2545
2546 return;
2547
2548} // RemoveDevicePorts
2549
2550
2551/************************** START OF SPECIFICATIONS ************************
2552* *
2553* SUBROUTINE NAME: FindDevicePort *
2554* *
2555* DESCRIPTIVE NAME: Returns if the capabilities of a given device are *
2556* stored in global memory. *
2557* *
2558*************************** END OF SPECIFICATIONS **************************/
2559BOOL FindDevicePort( PVSD_INSTANCE pInstance,
2560 port_t *pAudioDrvPort,
2561 port_t *prns_port)
2562
2563{
2564 extern HMTX hmtxProcessSemVSD;
2565 extern HHUGEHEAP hhpHeapVSD;
2566
2567 PDRIVER_PORT pTemp = pDriverPort;
2568 BOOL fFound = FALSE;
2569
2570 // search through our list of global capabilities and find
2571 // the requested device.
2572 while (pTemp )
2573 {
2574 if ( !strcmp( pTemp->szDeviceName,
2575 pInstance->szDeviceName ) )
2576 {
2577 // copy the port associated with this driver
2578 // into our instance
2579 if (pAudioDrvPort)
2580 {
2581 *pAudioDrvPort = pTemp->AudioDrvPort;
2582 *prns_port = pTemp->rns_port;
2583 }
2584 fFound = TRUE;
2585 break;
2586
2587 }
2588 pTemp = pTemp->pNext;
2589
2590 } /* endwhile */
2591
2592 return ( fFound );
2593
2594} // FindDevicePort
2595
2596
2597/************************** START OF SPECIFICATIONS ************************
2598* *
2599* SUBROUTINE NAME: AddDevicePort *
2600* *
2601* DESCRIPTIVE NAME: Adds the capabililities of a given device to global *
2602* memory for use by other instances/process *
2603*
2604* Prevents each process from having to query the same *
2605* info.
2606* *
2607*************************** END OF SPECIFICATIONS **************************/
2608ULONG AddDevicePort( PVSD_INSTANCE pInstance,
2609 port_t AudioDrvPort,
2610 port_t rns_port)
2611
2612{
2613
2614 extern HMTX hmtxProcessSemVSD;
2615 extern HHUGEHEAP hhpHeapVSD;
2616 ULONG rc;
2617 PDRIVER_PORT pTemp;
2618
2619 // allocate the memory
2620 pTemp = HhpAllocMem( hhpHeapVSD, sizeof ( DRIVER_PORT ) );
2621
2622
2623 if ( !pTemp )
2624 {
2625 return ( MCIERR_OUT_OF_MEMORY );
2626 }
2627
2628 rc = DosRequestMutexSem ( hmtxProcessSemVSD, SEM_INDEFINITE_WAIT);
2629 strcpy( pTemp->szDeviceName, pInstance->szDeviceName );
2630
2631 pTemp->AudioDrvPort = AudioDrvPort;
2632
2633 pTemp->rns_port = rns_port;
2634 pTemp->pNext = pDriverPort;
2635
2636 // only update root pointer IF we allocated memory
2637 pDriverPort = pTemp;
2638
2639 DosReleaseMutexSem (hmtxProcessSemVSD);
2640
2641 return ( MCIERR_SUCCESS );
2642
2643} // AddDevicePort
2644
2645
2646#endif // #ifdef INCL_MM_WPOS
2647
2648
2649
2650/************************ START OF SPECIFICATIONS **************************
2651*
2652* SUBROUTINE NAME: VSDEscape
2653*
2654* FUNCTION: Sends a raw buffer to the device driver.
2655*
2656* INPUT: pInstance - pointer to VSD instance
2657*
2658* SUCCESS : VSDERR_SUCCESS
2659*
2660* FAILURE : VSD error code.
2661*
2662* OS/2 CALLS: DosDevIOCtl()
2663*
2664* C CALLS: None.
2665*
2666* INTERNAL CALLS: VSDError()
2667*
2668*************************** END OF SPECIFICATIONS *************************/
2669
2670#ifdef ESCAPE
2671LONG VSDEscape( PVSD_INSTANCE pInstance,
2672 PVSD_ESCAPE_PARMS pRequest )
2673
2674{
2675 kern_return_t rc;
2676
2677 rc = DD_SetInfo( (port_t) pInstance->hFile,
2678 ADF_MCI_ESCAPE,
2679 0,
2680 0,
2681 (dd_data_ptr_t) pRequest,
2682 (mach_msg_type_number_t) sizeof(VSD_ESCAPE_PARMS));
2683
2684} /* VSDDevUnits */
2685#endif
2686
Note: See TracBrowser for help on using the repository browser.