1 // ****************************************************************************
5 // Implementation file for the CEchoGals driver class (mixer functions).
6 // Set editor tabs to 3 for your viewing pleasure.
8 // ----------------------------------------------------------------------------
10 // This file is part of Echo Digital Audio's generic driver library.
11 // Copyright Echo Digital Audio Corporation (c) 1998 - 2005
12 // All rights reserved
15 // This library is free software; you can redistribute it and/or
16 // modify it under the terms of the GNU Lesser General Public
17 // License as published by the Free Software Foundation; either
18 // version 2.1 of the License, or (at your option) any later version.
20 // This library is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 // Lesser General Public License for more details.
25 // You should have received a copy of the GNU Lesser General Public
26 // License along with this library; if not, write to the Free Software
27 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 // ****************************************************************************
31 #include "CEchoGals.h"
33 #undef ECHO_DEBUGPRINTF
34 #define ECHO_DEBUGPRINTF(x)
36 /****************************************************************************
38 CEchoGals mixer client management
40 ****************************************************************************/
42 //===========================================================================
44 // Open the mixer - create a mixer client structure for this client and
45 // return the cookie. The cookie uniquely identifies this client to the
48 // Valid cookies are non-zero. If you get a zero cookie, the open failed
51 // Clients can change mixer controls without calling OpenMixer first; it just
52 // means that they can't track control changes made by other clients.
54 //===========================================================================
56 ECHOSTATUS
CEchoGals::OpenMixer(NUINT
&Cookie
)
58 ECHO_MIXER_CLIENT
*pTemp
;
61 return ECHOSTATUS_MIXER_DISABLED
;
64 // If the cookie is non-zero, then use the specified value
68 pTemp
= m_pMixerClients
;
71 if (Cookie
== pTemp
->Cookie
)
73 ECHO_DEBUGPRINTF(("CEchoGals::OpenMixer - cookie 0x%lx already in use\n",
75 return ECHOSTATUS_BAD_COOKIE
;
88 m_pOsSupport
->OsGetSystemTime(&ullTime
);
89 Cookie
= (NUINT
) ullTime
;
94 // Look through the existing mixer client list to ensure that this
97 pTemp
= m_pMixerClients
;
100 if (Cookie
== pTemp
->Cookie
)
103 // Oops, someone is already using this cookie. Increment
104 // the new cookie and try again.
107 pTemp
= m_pMixerClients
;
110 pTemp
= pTemp
->pNext
;
117 // Allocate the mixer client structure
119 ECHO_MIXER_CLIENT
*pClient
= NULL
;
122 Status
= OsAllocateNonPaged(sizeof(ECHO_MIXER_CLIENT
),(void **) &pClient
);
131 // Store the new cookie and the new mixer client
133 pClient
->Cookie
= Cookie
;
134 pClient
->pNext
= m_pMixerClients
;
135 m_pMixerClients
= pClient
;
137 return ECHOSTATUS_OK
;
142 //===========================================================================
144 // Find a mixer client that matches a cookie
146 //===========================================================================
148 ECHO_MIXER_CLIENT
*CEchoGals::GetMixerClient(NUINT Cookie
)
150 ECHO_MIXER_CLIENT
*pTemp
;
152 pTemp
= m_pMixerClients
;
153 while (NULL
!= pTemp
)
155 if (Cookie
== pTemp
->Cookie
)
158 pTemp
= pTemp
->pNext
;
166 //===========================================================================
168 // Close the mixer - free the mixer client structure
170 //===========================================================================
172 ECHOSTATUS
CEchoGals::CloseMixer(NUINT Cookie
)
175 // Search the linked list and remove the client that matches the cookie
177 ECHO_MIXER_CLIENT
*pTemp
;
179 pTemp
= m_pMixerClients
;
181 return ECHOSTATUS_BAD_COOKIE
;
186 if (pTemp
->Cookie
== Cookie
)
188 m_pMixerClients
= pTemp
->pNext
;
189 OsFreeNonPaged(pTemp
);
191 return ECHOSTATUS_OK
;
195 // Not the head of the list; search the list
197 while (NULL
!= pTemp
->pNext
)
199 if (Cookie
== pTemp
->pNext
->Cookie
)
201 ECHO_MIXER_CLIENT
*pDeadClient
;
203 pDeadClient
= pTemp
->pNext
;
204 pTemp
->pNext
= pDeadClient
->pNext
;
205 OsFreeNonPaged(pDeadClient
);
207 return ECHOSTATUS_OK
;
210 pTemp
= pTemp
->pNext
;
216 return ECHOSTATUS_BAD_COOKIE
;
221 //===========================================================================
223 // IsMixerOpen - returns true if at least one client has the mixer open
225 //===========================================================================
227 BOOL
CEchoGals::IsMixerOpen()
229 if (NULL
== m_pMixerClients
)
237 //===========================================================================
239 // This function is called when a mixer control changes; add the change
240 // to the queue for each client.
242 // Here's what the wCh1 and wCh2 parameters represent, based on the wType
247 // ECHO_BUS_OUT Output bus Ignored
248 // ECHO_BUS_IN Input bus Ignored
249 // ECHO_PIPE_OUT Output pipe Output bus
250 // ECHO_MONITOR Input bus Output bus
252 // ECHO_PIPE_IN is not used right now.
254 //===========================================================================
256 ECHOSTATUS
CEchoGals::MixerControlChanged
258 WORD wType
, // One of the ECHO_CHANNEL_TYPES
259 WORD wParameter
, // One of the MXN_* values
260 WORD wCh1
, // Depends on the wType value
261 WORD wCh2
// Also depends on wType value
264 ECHO_MIXER_CLIENT
*pClient
= m_pMixerClients
;
265 PMIXER_NOTIFY pNotify
;
267 if (m_fMixerDisabled
)
268 return ECHOSTATUS_MIXER_DISABLED
;
271 // Go through all the clients and store this control change
273 while (NULL
!= pClient
)
276 // Search the circular buffer for this client and see if
277 // this control change is already stored
279 DWORD dwIndex
,dwCount
;
282 dwCount
= pClient
->dwCount
;
283 dwIndex
= pClient
->dwTail
;
287 pNotify
= pClient
->Notifies
+ dwIndex
;
288 if ( (pNotify
->wType
== wType
) &&
289 (pNotify
->wParameter
== wParameter
) &&
290 (pNotify
->u
.wPipeOut
== wCh1
) && // can use any union member her
291 (pNotify
->wBusOut
== wCh2
))
294 // Found this notify already in the circular buffer
300 dwIndex
&= MAX_MIXER_NOTIFIES
- 1;
305 // If the notify was not found, add this notify to the circular buffer if
306 // there is enough room.
308 if ( (FALSE
== fFound
) &&
309 (pClient
->dwCount
!= MAX_MIXER_NOTIFIES
))
311 pNotify
= pClient
->Notifies
+ pClient
->dwHead
;
313 pNotify
->wType
= wType
;
314 pNotify
->wParameter
= wParameter
;
316 if (ECHO_BUS_OUT
== wType
)
318 pNotify
->u
.wPipeOut
= ECHO_CHANNEL_UNUSED
;
319 pNotify
->wBusOut
= wCh1
;
323 pNotify
->u
.wPipeOut
= wCh1
; // can use any union member here also
324 pNotify
->wBusOut
= wCh2
;
327 pClient
->dwCount
+= 1;
328 pClient
->dwHead
= (pClient
->dwHead
+ 1) & (MAX_MIXER_NOTIFIES
- 1);
331 pClient
= pClient
->pNext
;
334 return ECHOSTATUS_OK
;
336 } // MixerControlChanged
339 //===========================================================================
341 // This method is called when a client wants to know what controls have
344 //===========================================================================
346 ECHOSTATUS
CEchoGals::GetControlChanges
348 PMIXER_MULTI_NOTIFY pNotifies
,
355 ECHO_MIXER_CLIENT
*pClient
= GetMixerClient(MixerCookie
);
359 pNotifies
->dwCount
= 0;
360 return ECHOSTATUS_BAD_COOKIE
;
364 // Copy mixer notifies
366 PMIXER_NOTIFY pDest
,pSrc
;
367 DWORD dwNumClientNotifies
,dwNumReturned
;
369 dwNumClientNotifies
= pNotifies
->dwCount
;
370 pDest
= pNotifies
->Notifies
;
372 while ( (dwNumClientNotifies
> 0) && (pClient
->dwCount
> 0))
374 pSrc
= pClient
->Notifies
+ pClient
->dwTail
;
376 OsCopyMemory(pDest
,pSrc
,sizeof(MIXER_NOTIFY
));
380 pClient
->dwTail
= (pClient
->dwTail
+ 1) & (MAX_MIXER_NOTIFIES
- 1);
381 pClient
->dwCount
-= 1;
383 dwNumClientNotifies
--;
388 pNotifies
->dwCount
= dwNumReturned
;
390 return ECHOSTATUS_OK
;
392 } // GetControlChanges
397 /****************************************************************************
399 CEchoGals mixer control
401 ****************************************************************************/
403 //===========================================================================
405 // Process mixer function - service a single mixer function
407 //===========================================================================
409 ECHOSTATUS
CEchoGals::ProcessMixerFunction
411 PMIXER_FUNCTION pMixerFunction
,
415 ECHOSTATUS Status
= ECHOSTATUS_OK
;
417 if (m_fMixerDisabled
)
418 return ECHOSTATUS_MIXER_DISABLED
;
420 switch ( pMixerFunction
->iFunction
)
423 Status
= GetCapabilities( &pMixerFunction
->Data
.Capabilities
);
424 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
425 "MXF_GET_CAPS Status %ld\n", Status
) );
429 Status
= GetAudioLineLevel( pMixerFunction
);
431 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
432 "MXF_GET_LEVEL Status %ld\n", Status) );
437 Status
= SetAudioLineLevel( pMixerFunction
);
438 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
439 "MXF_SET_LEVEL Status %ld\n", Status
) );
442 case MXF_GET_NOMINAL
:
443 Status
= GetAudioNominal( pMixerFunction
);
445 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
446 "MXF_GET_NOMINAL Status %ld\n", Status) );
450 case MXF_SET_NOMINAL
:
451 Status
= SetAudioNominal( pMixerFunction
);
452 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
453 "MXF_SET_NOMINAL Status %ld\n", Status
) );
456 case MXF_GET_MONITOR
:
457 Status
= GetAudioMonitor( pMixerFunction
->Channel
.wChannel
,
458 pMixerFunction
->Data
.Monitor
.wBusOut
,
459 pMixerFunction
->Data
.Monitor
.Data
.iLevel
);
461 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
462 "MXF_GET_MONITOR Status %ld\n", Status) );
466 case MXF_SET_MONITOR
:
467 Status
= SetAudioMonitor( pMixerFunction
->Channel
.wChannel
,
468 pMixerFunction
->Data
.Monitor
.wBusOut
,
469 pMixerFunction
->Data
.Monitor
.Data
.iLevel
);
470 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
471 "MXF_SET_MONITOR Status %ld\n", Status
) );
474 case MXF_GET_CLOCK_DETECT
:
475 Status
= GetInputClockDetect( pMixerFunction
->Data
.dwClockDetectBits
);
478 case MXF_GET_INPUT_CLOCK
:
479 Status
= GetInputClock( pMixerFunction
->Data
.wClock
);
480 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
481 "MXF_GET_INPUT_CLOCK Status %ld\n", Status
) );
484 case MXF_SET_INPUT_CLOCK
:
485 Status
= SetInputClock( pMixerFunction
->Data
.wClock
);
486 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
487 "MXF_SET_INPUT_CLOCK Status %ld\n", Status
) );
491 case MXF_GET_OUTPUT_CLOCK
:
492 Status
= GetOutputClock( pMixerFunction
->Data
.wClock
);
493 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
494 "MXF_GET_OUTPUT_CLOCK Status %ld\n", Status
) );
497 case MXF_SET_OUTPUT_CLOCK
:
498 Status
= SetOutputClock( pMixerFunction
->Data
.wClock
);
499 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
500 "MXF_SET_OUTPUT_CLOCK Status %ld\n", Status
) );
504 case MXF_GET_METERS
:
506 if (NULL
!= GetDspCommObject())
508 Status
= GetDspCommObject()->
509 GetAudioMeters( &pMixerFunction
->Data
.Meters
);
513 Status
= ECHOSTATUS_DSP_DEAD
;
516 //ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
517 // "MXF_GET_METERS Status %ld\n", Status) );
520 case MXF_GET_METERS_ON
:
521 Status
= GetMetersOn( pMixerFunction
->Data
.bMetersOn
);
522 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
523 "MXF_SET_METERS Status %ld\n", Status
) );
526 case MXF_SET_METERS_ON
:
527 Status
= SetMetersOn( pMixerFunction
->Data
.bMetersOn
);
528 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
529 "MXF_SET_METERS_ON Status %ld\n", Status
) );
532 case MXF_GET_PROF_SPDIF
:
533 if ( ECHOSTATUS_DSP_DEAD
== IsProfessionalSpdif() )
535 Status
= ECHOSTATUS_DSP_DEAD
;
539 pMixerFunction
->Data
.bProfSpdif
= IsProfessionalSpdif();
541 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
542 "MXF_GET_PROF_SPDIF Pro S/PDIF: 0x%x Status %ld\n",
543 pMixerFunction
->Data
.bProfSpdif
,
547 case MXF_SET_PROF_SPDIF
:
548 SetProfessionalSpdif( pMixerFunction
->Data
.bProfSpdif
);
549 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
550 "MXF_SET_PROF_SPDIF Pro S/PDIF: 0x%x Status %ld\n",
551 pMixerFunction
->Data
.bProfSpdif
,
556 Status
= GetAudioMute(pMixerFunction
);
558 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
559 "MXF_GET_MUTE Status %ld\n", Status) );
564 Status
= SetAudioMute(pMixerFunction
);
565 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
566 "MXF_SET_MUTE Status %ld\n", Status
) );
569 case MXF_GET_MONITOR_MUTE
:
571 GetAudioMonitorMute( pMixerFunction
->Channel
.wChannel
,
572 pMixerFunction
->Data
.Monitor
.wBusOut
,
573 pMixerFunction
->Data
.Monitor
.Data
.bMuteOn
);
575 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
576 "MXF_GET_MONITOR_MUTE Status %ld\n", Status) );
580 case MXF_SET_MONITOR_MUTE
:
582 SetAudioMonitorMute( pMixerFunction
->Channel
.wChannel
,
583 pMixerFunction
->Data
.Monitor
.wBusOut
,
584 pMixerFunction
->Data
.Monitor
.Data
.bMuteOn
);
585 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
586 "MXF_SET_MONITOR_MUTE Status %ld\n", Status
) );
589 case MXF_GET_MONITOR_PAN
:
591 GetAudioMonitorPan( pMixerFunction
->Channel
.wChannel
,
592 pMixerFunction
->Data
.Monitor
.wBusOut
,
593 pMixerFunction
->Data
.Monitor
.Data
.iPan
);
596 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
597 "MXF_GET_MONITOR_PAN Status %ld\n", Status) );
601 case MXF_SET_MONITOR_PAN
:
603 SetAudioMonitorPan( pMixerFunction
->Channel
.wChannel
,
604 pMixerFunction
->Data
.Monitor
.wBusOut
,
605 pMixerFunction
->Data
.Monitor
.Data
.iPan
);
606 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
607 "MXF_SET_MONITOR_PAN Status %ld\n", Status
) );
611 pMixerFunction
->Data
.wFlags
= GetFlags();
612 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
613 "MXF_GET_FLAGS 0x%x Status %ld\n",
614 pMixerFunction
->Data
.wFlags
,
618 SetFlags( pMixerFunction
->Data
.wFlags
);
619 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
620 "MXF_SET_FLAGS 0x%x Status %ld\n",
621 pMixerFunction
->Data
.wFlags
,
624 case MXF_CLEAR_FLAGS
:
625 ClearFlags( pMixerFunction
->Data
.wFlags
);
626 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
627 "MXF_CLEAR_FLAGS 0x%x Status %ld\n",
628 pMixerFunction
->Data
.wFlags
,
632 case MXF_GET_SAMPLERATE_LOCK
:
633 GetAudioLockedSampleRate( pMixerFunction
->Data
.dwLockedSampleRate
);
634 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
635 "MXF_GET_SAMPLERATE_LOCK 0x%lx Status %ld\n",
636 pMixerFunction
->Data
.dwLockedSampleRate
,
640 case MXF_SET_SAMPLERATE_LOCK
:
641 SetAudioLockedSampleRate( pMixerFunction
->Data
.dwLockedSampleRate
);
642 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
643 "MXF_SET_SAMPLERATE_LOCK 0x%lx Status %ld\n",
644 pMixerFunction
->Data
.dwLockedSampleRate
,
648 case MXF_GET_SAMPLERATE
:
650 GetAudioSampleRate( &pMixerFunction
->Data
.dwSampleRate
);
652 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
653 "MXF_GET_SAMPLERATE 0x%lx Status %ld\n",
654 pMixerFunction
->Data
.dwSampleRate
,
660 case MXF_GET_MIDI_IN_ACTIVITY
:
661 pMixerFunction
->Data
.bMidiActive
= m_MidiIn
.IsActive();
663 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
664 "MXF_GET_MIDI_IN_ACTIVITY %s "
666 ( pMixerFunction
->Data
.bMidiActive
)
667 ? "ACTIVE" : "INACTIVE",
672 case MXF_GET_MIDI_OUT_ACTIVITY
:
673 pMixerFunction
->Data
.bMidiActive
=
674 GetDspCommObject()->IsMidiOutActive();
676 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
677 "MXF_GET_MIDI_OUT_ACTIVITY %s "
679 ( pMixerFunction
->Data
.bMidiActive
)
680 ? "ACTIVE" : "INACTIVE",
684 #endif // MIDI_SUPPORT
687 case MXF_GET_DIGITAL_MODE
:
688 Status
= ECHOSTATUS_OK
;
689 pMixerFunction
->Data
.iDigMode
= GetDigitalMode();
690 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
691 "MXF_GET_DIGITAL_MODE %s "
693 ( DIGITAL_MODE_SPDIF_RCA
==
694 pMixerFunction
->Data
.iDigMode
)
696 : ( DIGITAL_MODE_SPDIF_OPTICAL
==
697 pMixerFunction
->Data
.iDigMode
)
698 ? "S/PDIF Optical" : "ADAT",
703 case MXF_SET_DIGITAL_MODE
:
704 Status
= SetDigitalMode( (BYTE
) pMixerFunction
->Data
.iDigMode
);
705 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
706 "MXF_SET_DIGITAL_MODE %s "
708 ( DIGITAL_MODE_SPDIF_RCA
==
709 pMixerFunction
->Data
.iDigMode
)
711 : ( DIGITAL_MODE_SPDIF_OPTICAL
==
712 pMixerFunction
->Data
.iDigMode
)
713 ? "S/PDIF Optical" : "ADAT",
719 Status
= GetAudioPan( pMixerFunction
);
720 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
721 "MXF_GET_PAN Status %ld\n", Status
) );
725 Status
= SetAudioPan( pMixerFunction
);
726 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
727 "MXF_SET_PAN Status %ld\n", Status
) );
730 #ifdef DIGITAL_INPUT_AUTO_MUTE_SUPPORT
732 case MXF_GET_DIG_IN_AUTO_MUTE
:
733 Status
= GetDigitalInAutoMute( pMixerFunction
);
734 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
735 "MXF_GET_DIG_IN_AUTO_MUTE Status %ld\n", Status
) );
739 case MXF_SET_DIG_IN_AUTO_MUTE
:
740 Status
= SetDigitalInAutoMute( pMixerFunction
);
741 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
742 "MXF_SET_DIG_IN_AUTO_MUTE Status %ld\n", Status
) );
745 #endif // DIGITAL_INPUT_AUTO_MUTE_SUPPORT
747 case MXF_GET_AUDIO_LATENCY
:
748 GetAudioLatency( &(pMixerFunction
->Data
.Latency
) );
751 #ifdef PHANTOM_POWER_CONTROL
753 case MXF_GET_PHANTOM_POWER
:
754 GetPhantomPower( &(pMixerFunction
->Data
.fPhantomPower
) );
757 case MXF_SET_PHANTOM_POWER
:
758 SetPhantomPower( pMixerFunction
->Data
.fPhantomPower
);
765 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerFunction: "
766 "Function %ld not supported\n",
767 pMixerFunction
->iFunction
) );
768 return ECHOSTATUS_NOT_SUPPORTED
;
771 pMixerFunction
->RtnStatus
= Status
;
772 iRtnDataSz
= sizeof( MIXER_FUNCTION
);
776 } // ECHOSTATUS CEchoGals::ProcessMixerFunction
781 //===========================================================================
783 // Process multiple mixer functions
785 //===========================================================================
787 ECHOSTATUS
CEchoGals::ProcessMixerMultiFunction
789 PMIXER_MULTI_FUNCTION pMixerFunctions
, // Request from mixer
790 INT32
& iRtnDataSz
// # bytes returned (if any)
793 ECHOSTATUS Status
= ECHOSTATUS_NOT_SUPPORTED
;
794 PMIXER_FUNCTION pMixerFunction
;
795 INT32 iRtn
, nCard
, i
;
797 if (m_fMixerDisabled
)
798 return ECHOSTATUS_MIXER_DISABLED
;
800 iRtnDataSz
= sizeof( MIXER_MULTI_FUNCTION
) - sizeof( MIXER_FUNCTION
);
801 pMixerFunction
= &pMixerFunctions
->MixerFunction
[ 0 ];
802 nCard
= pMixerFunction
->Channel
.wCardId
;
803 for ( i
= 0; i
< pMixerFunctions
->iCount
; i
++ )
805 pMixerFunction
= &pMixerFunctions
->MixerFunction
[ i
];
806 if ( nCard
!= pMixerFunction
->Channel
.wCardId
)
808 ECHO_DEBUGPRINTF( ("CEchoGals::ProcessMixerMultiFunction: "
809 "All functions MUST be for the same card "
812 pMixerFunction
->Channel
.wCardId
) );
813 return ECHOSTATUS_NOT_SUPPORTED
;
816 Status
= ProcessMixerFunction(pMixerFunction
,iRtn
);
822 } // ECHOSTATUS CEchoGals::ProcessMixerMultiFunction
827 //===========================================================================
829 // Typically, if you are writing a console, you will be polling the driver
830 // to get the current peak and VU meters, clock detect bits, and
831 // control changes. GetPolledStuff will fill out an ECHO_POLLED_STUFF
832 // structure with all of those things.
834 //===========================================================================
836 ECHOSTATUS
CEchoGals::GetPolledStuff
838 ECHO_POLLED_STUFF
*pPolledStuff
,
842 ECHO_MIXER_CLIENT
*pClient
;
843 CDspCommObject
*pDCO
= GetDspCommObject();
845 if (m_fMixerDisabled
)
846 return ECHOSTATUS_MIXER_DISABLED
;
849 return ECHOSTATUS_DSP_DEAD
;
852 // Fill out the non-client-specific portions of the struct
854 pDCO
->GetAudioMeters(&(pPolledStuff
->Meters
));
855 GetInputClockDetect(pPolledStuff
->dwClockDetectBits
);
858 // If there is a matching client, fill out the number
861 pClient
= GetMixerClient(MixerCookie
);
863 pPolledStuff
->dwNumPendingNotifies
= 0;
865 pPolledStuff
->dwNumPendingNotifies
= pClient
->dwCount
;
867 return ECHOSTATUS_OK
;
872 //===========================================================================
874 // Get the pan setting for an output pipe (virtual outputs only)
876 //===========================================================================
878 ECHOSTATUS
CEchoGals::GetAudioPan
887 if ( (pMF
->Channel
.dwType
!= ECHO_PIPE_OUT
) ||
889 return ECHOSTATUS_INVALID_CHANNEL
;
891 wPipe
= pMF
->Channel
.wChannel
;
892 wBus
= pMF
->Data
.PipeOut
.wBusOut
;
893 Status
= m_PipeOutCtrl
.GetPan(wPipe
,
895 pMF
->Data
.PipeOut
.Data
.iPan
);
899 } // ECHOSTATUS CEchoGals::GetAudioPan
902 //===========================================================================
904 // Set the pan for an output pipe (virtual outputs only)
906 //===========================================================================
908 ECHOSTATUS
CEchoGals::SetAudioPan
917 if ( (pMF
->Channel
.dwType
!= ECHO_PIPE_OUT
) ||
919 return ECHOSTATUS_INVALID_CHANNEL
;
921 wPipe
= pMF
->Channel
.wChannel
;
922 wBus
= pMF
->Data
.PipeOut
.wBusOut
;
923 Status
= m_PipeOutCtrl
.SetPan(wPipe
,
925 pMF
->Data
.PipeOut
.Data
.iPan
);
929 } // ECHOSTATUS CEchoGals::SetAudioPan
934 /****************************************************************************
936 CEchoGals clock control
938 The input clock is the sync source - is the audio for this card running
939 off of the internal clock, synced to word clock, etc.
941 Output clock is only supported on Layla20 - Layla20 can transmit either
944 ****************************************************************************/
946 //===========================================================================
948 // Get input and output clocks - just return the stored value
950 //===========================================================================
952 ECHOSTATUS
CEchoGals::GetInputClock(WORD
&wClock
)
954 if ( NULL
== GetDspCommObject() )
955 return ECHOSTATUS_DSP_DEAD
;
957 wClock
= GetDspCommObject()->GetInputClock();
959 return ECHOSTATUS_OK
;
963 ECHOSTATUS
CEchoGals::GetOutputClock(WORD
&wClock
)
965 if ( NULL
== GetDspCommObject() )
966 return ECHOSTATUS_DSP_DEAD
;
968 wClock
= GetDspCommObject()->GetOutputClock();
970 return ECHOSTATUS_OK
;
974 //===========================================================================
976 // Set input and output clocks - pass it down to the comm page and
977 // store the control change.
979 //===========================================================================
981 ECHOSTATUS
CEchoGals::SetInputClock(WORD wClock
)
985 if ( NULL
== GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
986 return ECHOSTATUS_DSP_DEAD
;
988 ECHO_DEBUGPRINTF( ("CEchoGals::SetInputClock: ") );
990 Status
= GetDspCommObject()->SetInputClock( wClock
);
992 if (ECHOSTATUS_OK
== Status
)
994 MixerControlChanged( ECHO_NO_CHANNEL_TYPE
,
1002 ECHOSTATUS
CEchoGals::SetOutputClock(WORD wClock
)
1006 if ( NULL
== GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
1007 return ECHOSTATUS_DSP_DEAD
;
1009 ECHO_DEBUGPRINTF( ("CEchoGals::SetOutputClock: ") );
1011 Status
= GetDspCommObject()->SetOutputClock( wClock
);
1013 if (ECHOSTATUS_OK
== Status
)
1015 MixerControlChanged( ECHO_NO_CHANNEL_TYPE
,
1023 //===========================================================================
1025 // Get the currently detected clock bits - default method. Overridden by
1026 // derived card classes.
1028 //===========================================================================
1030 ECHOSTATUS
CEchoGals::GetInputClockDetect(DWORD
&dwClockDetectBits
)
1032 dwClockDetectBits
= ECHO_CLOCK_INTERNAL
;
1034 return ECHOSTATUS_OK
;
1038 //===========================================================================
1040 // Set the locked sample rate
1042 //===========================================================================
1044 ECHOSTATUS
CEchoGals::SetAudioLockedSampleRate
1051 Status
= QueryAudioSampleRate( dwSampleRate
);
1052 if ( ECHOSTATUS_OK
!= Status
)
1055 if (0 != (ECHOGALS_FLAG_SAMPLE_RATE_LOCKED
& GetFlags()))
1057 GetDspCommObject()->SetSampleRate( dwSampleRate
);
1058 m_dwSampleRate
= dwSampleRate
;
1061 m_dwLockedSampleRate
= dwSampleRate
;
1063 return ECHOSTATUS_OK
;
1065 } // ECHOSTATUS CEchoGals::SetAudioLockedSampleRate
1068 //===========================================================================
1070 // Get the locked sample rate
1072 //===========================================================================
1074 ECHOSTATUS
CEchoGals::GetAudioLockedSampleRate
1079 dwSampleRate
= m_dwLockedSampleRate
;
1081 return ECHOSTATUS_OK
;
1083 } // ECHOSTATUS CEchoGals::GetAudioLockedSampleRate
1087 #ifdef DIGITAL_INPUT_AUTO_MUTE_SUPPORT
1089 //===========================================================================
1091 // Get the digital input auto mute flag from the comm page
1093 //===========================================================================
1095 ECHOSTATUS
CEchoGals::GetDigitalInAutoMute(PMIXER_FUNCTION pMixerFunction
)
1099 if (0 == (m_wFlags
& ECHOGALS_ROFLAG_DIGITAL_IN_AUTOMUTE
))
1101 pMixerFunction
->Data
.fDigitalInAutoMute
= FALSE
;
1102 return ECHOSTATUS_NOT_SUPPORTED
;
1105 GetDspCommObject()->GetDigitalInputAutoMute( fAutoMute
);
1106 pMixerFunction
->Data
.fDigitalInAutoMute
= fAutoMute
;
1108 return ECHOSTATUS_OK
;
1110 } // GetDigitalInAutoMute
1113 //===========================================================================
1115 // Set the digital input auto mute flag
1117 //===========================================================================
1119 ECHOSTATUS
CEchoGals::SetDigitalInAutoMute(PMIXER_FUNCTION pMixerFunction
)
1123 if (0 == (m_wFlags
& ECHOGALS_ROFLAG_DIGITAL_IN_AUTOMUTE
))
1124 return ECHOSTATUS_NOT_SUPPORTED
;
1126 fAutoMute
= pMixerFunction
->Data
.fDigitalInAutoMute
;
1127 GetDspCommObject()->SetDigitalInputAutoMute( fAutoMute
);
1129 return ECHOSTATUS_OK
;
1131 } // SetDigitalInAutoMute
1133 #endif // DIGITAL_INPUT_AUTO_MUTE_SUPPORT
1136 //===========================================================================
1138 // Get the gain for an output bus, input bus, or output pipe.
1140 // Gain levels are in units of dB * 256.
1142 //===========================================================================
1144 ECHOSTATUS
CEchoGals::GetAudioLineLevel
1153 switch (pMF
->Channel
.dwType
)
1157 wBus
= pMF
->Channel
.wChannel
;
1159 if (wBus
< GetNumBussesOut())
1161 pMF
->Data
.iLevel
= m_BusOutLineLevels
[wBus
].GetGain();
1162 Status
= ECHOSTATUS_OK
;
1166 Status
= ECHOSTATUS_INVALID_CHANNEL
;
1173 wBus
= pMF
->Channel
.wChannel
;
1174 if (wBus
< GetNumBussesIn())
1176 pMF
->Data
.iLevel
= m_BusInLineLevels
[wBus
].GetGain();
1177 Status
= ECHOSTATUS_OK
;
1181 Status
= ECHOSTATUS_INVALID_CHANNEL
;
1185 case ECHO_PIPE_OUT
:
1187 wPipe
= pMF
->Channel
.wChannel
;
1188 wBus
= pMF
->Data
.PipeOut
.wBusOut
;
1189 Status
= m_PipeOutCtrl
.GetGain( wPipe
,
1191 pMF
->Data
.PipeOut
.Data
.iLevel
);
1195 Status
= ECHOSTATUS_INVALID_PARAM
;
1201 } // ECHOSTATUS CEchoGals::GetAudioLineLevel
1204 //===========================================================================
1206 // Utility function to check that a setting is within the correct range.
1208 //===========================================================================
1210 ECHOSTATUS
CheckSetting(INT32 iValue
,INT32 iMin
,INT32 iMax
)
1212 if ( (iValue
> iMax
) || (iValue
< iMin
))
1213 return ECHOSTATUS_INVALID_PARAM
;
1215 return ECHOSTATUS_OK
;
1220 //===========================================================================
1222 // Set the gain for an output bus, input bus, or output pipe.
1224 // Gain levels are in units of dB * 256.
1226 //===========================================================================
1228 ECHOSTATUS
CEchoGals::SetAudioLineLevel
1238 switch (pMF
->Channel
.dwType
)
1242 wBus
= pMF
->Channel
.wChannel
;
1243 iLevel
= pMF
->Data
.iLevel
;
1245 Status
= CheckSetting(iLevel
,ECHOGAIN_MINOUT
,ECHOGAIN_MAXOUT
);
1246 if (ECHOSTATUS_OK
!= Status
)
1249 Status
= m_BusOutLineLevels
[wBus
].SetGain(iLevel
);
1254 wBus
= pMF
->Channel
.wChannel
;
1255 iLevel
= pMF
->Data
.iLevel
;
1257 Status
= CheckSetting(iLevel
,ECHOGAIN_MININP
,ECHOGAIN_MAXINP
);
1258 if (ECHOSTATUS_OK
!= Status
)
1261 Status
= m_BusInLineLevels
[wBus
].SetGain(iLevel
);
1264 case ECHO_PIPE_OUT
:
1266 wPipe
= pMF
->Channel
.wChannel
;
1267 wBus
= pMF
->Data
.PipeOut
.wBusOut
;
1268 iLevel
= pMF
->Data
.PipeOut
.Data
.iLevel
;
1270 Status
= CheckSetting(iLevel
,ECHOGAIN_MINOUT
,ECHOGAIN_MAXOUT
);
1271 if (ECHOSTATUS_OK
!= Status
)
1274 Status
= m_PipeOutCtrl
.SetGain( wPipe
,
1280 Status
= ECHOSTATUS_INVALID_PARAM
;
1286 } // ECHOSTATUS CEchoGals::SetAudioLineLevel
1289 //===========================================================================
1291 // Get the nominal level for an output or input bus. The nominal level is
1292 // also referred to as the +4/-10 switch.
1294 //===========================================================================
1296 ECHOSTATUS
CEchoGals::GetAudioNominal
1303 CDspCommObject
* pDspCommObj
= GetDspCommObject();
1306 if ( NULL
== pDspCommObj
|| pDspCommObj
->IsBoardBad() )
1307 return ECHOSTATUS_DSP_DEAD
;
1309 switch (pMF
->Channel
.dwType
)
1312 wCh
= pMF
->Channel
.wChannel
;
1316 wCh
= pMF
->Channel
.wChannel
+ GetNumBussesOut();
1320 return ECHOSTATUS_INVALID_CHANNEL
;
1323 Status
= pDspCommObj
->GetNominalLevel( wCh
, &byNominal
);
1325 if ( ECHOSTATUS_OK
!= Status
)
1328 pMF
->Data
.iNominal
= ( byNominal
) ? -10 : 4;
1330 return ECHOSTATUS_OK
;
1331 } // ECHOSTATUS CEchoGals::GetAudioNominal
1334 //===========================================================================
1336 // Set the nominal level for an output or input bus. The nominal level is
1337 // also referred to as the +4/-10 switch.
1339 //===========================================================================
1341 ECHOSTATUS
CEchoGals::SetAudioNominal
1350 if ( NULL
== GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
1351 return ECHOSTATUS_DSP_DEAD
;
1353 switch (pMF
->Channel
.dwType
)
1356 wCh
= pMF
->Channel
.wChannel
;
1360 wCh
= pMF
->Channel
.wChannel
+ GetNumBussesOut();
1364 return ECHOSTATUS_INVALID_CHANNEL
;
1367 iNominal
= pMF
->Data
.iNominal
;
1369 if ((iNominal
!= -10) && (iNominal
!= 4))
1370 return ECHOSTATUS_INVALID_PARAM
;
1373 GetDspCommObject()->SetNominalLevel( wCh
,
1374 ( iNominal
== -10 ) );
1376 if ( ECHOSTATUS_OK
!= Status
)
1379 Status
= MixerControlChanged( (WORD
) pMF
->Channel
.dwType
,
1381 pMF
->Channel
.wChannel
);
1384 } // ECHOSTATUS CEchoGals::SetAudioNominal
1387 //===========================================================================
1389 // Set the mute for an output bus, input bus, or output pipe.
1391 //===========================================================================
1393 ECHOSTATUS
CEchoGals::SetAudioMute
1403 switch (pMF
->Channel
.dwType
)
1407 wBus
= pMF
->Channel
.wChannel
;
1408 bMute
= pMF
->Data
.bMuteOn
;
1409 Status
= m_BusOutLineLevels
[wBus
].SetMute(bMute
);
1414 wBus
= pMF
->Channel
.wChannel
;
1415 bMute
= pMF
->Data
.bMuteOn
;
1416 Status
= m_BusInLineLevels
[wBus
].SetMute(bMute
);
1419 case ECHO_PIPE_OUT
:
1421 wPipe
= pMF
->Channel
.wChannel
;
1422 wBus
= pMF
->Data
.PipeOut
.wBusOut
;
1423 bMute
= pMF
->Data
.PipeOut
.Data
.bMuteOn
;
1424 Status
= m_PipeOutCtrl
.SetMute( wPipe
,
1430 Status
= ECHOSTATUS_INVALID_PARAM
;
1435 } // ECHOSTATUS CEchoGals::SetAudioMute
1438 //===========================================================================
1440 // Get the mute for an output bus, input bus, or output pipe.
1442 //===========================================================================
1444 ECHOSTATUS
CEchoGals::GetAudioMute
1453 switch (pMF
->Channel
.dwType
)
1457 wBus
= pMF
->Channel
.wChannel
;
1459 if (wBus
< GetNumBussesOut())
1461 pMF
->Data
.bMuteOn
= m_BusOutLineLevels
[wBus
].IsMuteOn();
1462 Status
= ECHOSTATUS_OK
;
1466 Status
= ECHOSTATUS_INVALID_CHANNEL
;
1473 wBus
= pMF
->Channel
.wChannel
;
1475 if (wBus
< GetNumBussesIn())
1477 pMF
->Data
.bMuteOn
= m_BusInLineLevels
[wBus
].IsMuteOn();
1478 Status
= ECHOSTATUS_OK
;
1482 Status
= ECHOSTATUS_INVALID_CHANNEL
;
1486 case ECHO_PIPE_OUT
:
1488 wPipe
= pMF
->Channel
.wChannel
;
1489 wBus
= pMF
->Data
.PipeOut
.wBusOut
;
1490 Status
= m_PipeOutCtrl
.GetMute( wPipe
,
1492 pMF
->Data
.PipeOut
.Data
.bMuteOn
);
1496 Status
= ECHOSTATUS_INVALID_PARAM
;
1502 } // ECHOSTATUS CEchoGals::GetAudioMute
1505 //===========================================================================
1507 // Get the monitor gain for a single input bus mixed to a single output bus.
1509 //===========================================================================
1511 ECHOSTATUS
CEchoGals::GetAudioMonitor
1518 if ( wBusIn
>= GetNumBussesIn() ||
1519 wBusOut
>= GetNumBussesOut() )
1521 return ECHOSTATUS_INVALID_INDEX
;
1525 // Get the monitor value
1527 m_MonitorCtrl
.GetGain(wBusIn
,wBusOut
,iGain
);
1529 return ECHOSTATUS_OK
;
1531 } // ECHOSTATUS CEchoGals::GetAudioMonitor
1534 //===========================================================================
1536 // Set the monitor gain for a single input bus mixed to a single output bus.
1538 //===========================================================================
1540 ECHOSTATUS
CEchoGals::SetAudioMonitor
1549 if ( wBusIn
>= GetNumBussesIn() ||
1550 wBusOut
>= GetNumBussesOut() )
1552 return ECHOSTATUS_INVALID_INDEX
;
1555 Status
= CheckSetting(iGain
,ECHOGAIN_MINOUT
,ECHOGAIN_MAXOUT
);
1556 if (ECHOSTATUS_OK
== Status
)
1559 // Set the monitor gain
1561 m_MonitorCtrl
.SetGain(wBusIn
,wBusOut
,iGain
);
1566 } // ECHOSTATUS CEchoGals::SetAudioMonitor
1569 //===========================================================================
1571 // Helper functions for doing log conversions on pan values
1573 // The parameter iNum is a fixed point 32 bit number in 16.16 format;
1574 // that is, 16 bits of integer and 16 bits of decimal
1575 // To convert a float number to fixed point, simply multiply by 2^16 and round
1577 // Valid range for iNum is from +1.0 (0x10000) to 0.
1579 //===========================================================================
1581 #define FIXED_BASE 16 // 16 bits of fraction
1582 #define FIXED_ONE_HALF ((INT32) 0x00008000) // 0.5 in 16.16 format
1583 #define COEFF_A2 ((INT32) 0xffffa9ac) // -.3372223
1584 #define COEFF_A1 ((INT32) 0x0000ff8a) // .9981958
1585 #define COEFF_A0 ((INT32) 0xffff5661) // -.6626105
1587 #define DB_CONVERT 0x60546 // 6.02... in 16.16
1589 // Note use of double precision here to prevent overflow
1590 static INT32
FixedMult( INT32 iNum1
, INT32 iNum2
)
1594 llNum
= (LONGLONG
) iNum1
* (LONGLONG
) iNum2
;
1596 return (INT32
) (llNum
>> FIXED_BASE
);
1597 } // INT32 FixedMult( INT32 iNum1, INT32 iNum2 )
1600 static INT32
log2( INT32 iNum
)
1605 // log2 is undefined for zero, so return -infinity (or close enough)
1607 return ECHOGAIN_MUTED
;
1609 // Step 1 - Normalize and save the number of shifts
1610 // Keep shifting iNum up until iNum > 0.5
1612 while ( iNum
< FIXED_ONE_HALF
)
1618 // Step 2 - Calculate LOG2 by polynomial approximation. 8 bit accuracy.
1620 // LOG2(x) = 4.0* (-.3372223 x*x + .9981958 x - .6626105)
1622 // where 0.5 <= x < 1.0
1625 // Compute polynomial sum
1626 iTemp
= FixedMult( iNum
, iNum
); // iTemp now has iNum squared
1627 iTemp
= FixedMult( iTemp
, COEFF_A2
);
1628 iTemp
+= FixedMult( iNum
, COEFF_A1
);
1634 // Account for the normalize shifts
1635 iTemp
-= ( iNumShifts
<< FIXED_BASE
);
1638 } // INT32 log2( INT32 iNum )
1642 // Convert pan value to Db X 256
1643 // Pan value is 0 - MAX_MIXER_PAN
1645 INT32
PanToDb( INT32 iPan
)
1647 if ( iPan
>= ( MAX_MIXER_PAN
- 1 ) )
1650 return( ECHOGAIN_MUTED
);
1652 // Convert pan to 16.16
1654 iPan
= ( iPan
<< 16 ) / MAX_MIXER_PAN
;
1658 iPan
= log2( iPan
);
1660 // To convert to decibels*256, just multiply by the conversion factor
1662 iPan
= FixedMult( iPan
<< 8, DB_CONVERT
);
1664 // To round, add one half and then mask off the fractional bits
1666 iPan
= ( iPan
+ FIXED_ONE_HALF
) >> FIXED_BASE
;
1668 } // INT32 PanToDb( INT32 iPan )
1671 //===========================================================================
1673 // Set the monitor pan
1675 // For this to work effectively, both the input and output channels must
1676 // both either be odd or even. Thus even channel numbers are for the
1677 // left channel and odd channel numbers are for the right channel.
1678 // Pan values will be computed for both channels.
1680 // iPan ranges from 0 (hard left) to MAX_MIXER_PAN (hard right)
1682 //===========================================================================
1684 ECHOSTATUS
CEchoGals::SetAudioMonitorPan
1688 INT32 iPan
// New pan
1693 if ( wBusIn
>= GetNumBussesIn() ||
1694 wBusOut
>= GetNumBussesOut() )
1696 return ECHOSTATUS_INVALID_INDEX
;
1699 Status
= CheckSetting(iPan
,0,MAX_MIXER_PAN
);
1700 if (ECHOSTATUS_OK
== Status
)
1705 m_MonitorCtrl
.SetPan(wBusIn
,wBusOut
,iPan
);
1710 } // ECHOSTATUS CEchoGals::SetAudioMonitorPan
1713 //===========================================================================
1715 // Get the monitor pan
1717 //===========================================================================
1719 ECHOSTATUS
CEchoGals::GetAudioMonitorPan
1723 INT32
& iPan
// Returns current pan (0 - MAX_MIXER_PAN)
1726 if ( wBusIn
>= GetNumBussesIn() ||
1727 wBusOut
>= GetNumBussesOut() )
1729 return ECHOSTATUS_INVALID_INDEX
;
1735 m_MonitorCtrl
.GetPan(wBusIn
,wBusOut
,iPan
);
1737 return ECHOSTATUS_OK
;
1739 } // ECHOSTATUS CEchoGals::GetAudioMonitorPan
1742 //===========================================================================
1744 // Set the monitor mute
1746 //===========================================================================
1748 ECHOSTATUS
CEchoGals::SetAudioMonitorMute
1752 BOOL bMute
// New state
1755 if ( wBusIn
>= GetNumBussesIn() ||
1756 wBusOut
>= GetNumBussesOut() )
1758 return ECHOSTATUS_INVALID_INDEX
;
1764 m_MonitorCtrl
.SetMute(wBusIn
,wBusOut
,bMute
);
1766 return ECHOSTATUS_OK
;
1768 } // ECHOSTATUS CEchoGals::SetAudioMonitorMute
1771 //===========================================================================
1773 // Get the monitor mute
1775 //===========================================================================
1777 ECHOSTATUS
CEchoGals::GetAudioMonitorMute
1781 BOOL
&bMute
// Returns current state
1784 if ( wBusIn
>= GetNumBussesIn() ||
1785 wBusOut
>= GetNumBussesOut() )
1787 return ECHOSTATUS_INVALID_INDEX
;
1793 m_MonitorCtrl
.GetMute(wBusIn
,wBusOut
,bMute
);
1795 return ECHOSTATUS_OK
;
1797 } // ECHOSTATUS CEchoGals::GetAudioMonitorMute
1800 //===========================================================================
1802 // Set the S/PDIF output format to professional or consumer
1804 //===========================================================================
1806 void CEchoGals::SetProfessionalSpdif( BOOL bNewStatus
)
1808 ECHO_DEBUGPRINTF(("CEchoGals::SetProfessionalSpdif %d\n",bNewStatus
));
1810 if ( NULL
!= GetDspCommObject() )
1812 GetDspCommObject()->SetProfessionalSpdif( bNewStatus
);
1813 MixerControlChanged( ECHO_NO_CHANNEL_TYPE
,
1816 } // void CEchoGals::SetProfessionalSpdif( BOOL bNewStatus )
1819 //===========================================================================
1823 // See ECHOGALS_FLAG_??? definitions in EchoGalsXface.h
1825 //===========================================================================
1827 ECHOSTATUS
CEchoGals::SetFlags
1833 // Mask off the read-only flags so they don't change
1835 wFlags
&= ECHOGALS_FLAG_WRITABLE_MASK
;
1838 // Set the flags & mark the flags as changed
1842 MixerControlChanged( ECHO_NO_CHANNEL_TYPE
,
1845 return ECHOSTATUS_OK
;
1847 } // ECHOSTATUS CEchoGals::SetFlags
1850 //===========================================================================
1852 // Clear driver flags
1854 // See ECHOGALS_FLAG_??? definitions in EchoGalsXface.h
1856 //===========================================================================
1858 ECHOSTATUS
CEchoGals::ClearFlags
1864 // Mask off the read-only flags so they don't change
1866 wFlags
&= ECHOGALS_FLAG_WRITABLE_MASK
;
1869 // Clear the flags & mark the flags as changed
1871 m_wFlags
&= ~wFlags
;
1873 MixerControlChanged( ECHO_NO_CHANNEL_TYPE
,
1876 return ECHOSTATUS_OK
;
1878 } // ECHOSTATUS CEchoGals::ClearFlags
1881 //===========================================================================
1883 // Set the digital mode - currently for Gina24, Layla24, and Mona
1885 //===========================================================================
1887 ECHOSTATUS
CEchoGals::SetDigitalMode
1893 BYTE byPreviousDigitalMode
;
1895 if ( NULL
== GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
1896 return ECHOSTATUS_DSP_DEAD
;
1898 if ( 0 == GetDspCommObject()->GetDigitalModes() )
1899 return ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED
;
1901 if ( TRUE
== GetDspCommObject()->IsTransportActive() )
1903 ECHO_DEBUGPRINTF( ( "CEchoGals::SetDigitalMode() Cannot set the digital "
1904 "mode while transport is running\n"));
1905 return ECHOSTATUS_BUSY
;
1907 byPreviousDigitalMode
= GetDspCommObject()->GetDigitalMode();
1908 Status
= GetDspCommObject()->SetDigitalMode( byDigitalMode
);
1909 MixerControlChanged( ECHO_NO_CHANNEL_TYPE
,
1911 MixerControlChanged( ECHO_NO_CHANNEL_TYPE
,
1915 // If we successfully changed the digital mode from or to ADAT, then
1916 // make sure all output, input and monitor levels are updated by the
1919 if ( ECHOSTATUS_OK
== Status
&&
1920 byPreviousDigitalMode
!= byDigitalMode
&&
1921 ( DIGITAL_MODE_ADAT
== byPreviousDigitalMode
||
1922 DIGITAL_MODE_ADAT
== byDigitalMode
) )
1924 WORD i
, j
,wBus
,wPipe
;
1926 for ( i
= 0; i
< GetNumBussesIn(); i
++ )
1928 for ( j
= 0; j
< GetNumBussesOut(); j
+= 2 )
1930 m_MonitorCtrl
.SetGain(i
,j
,ECHOGAIN_UPDATE
,FALSE
);
1934 for ( wBus
= 0; wBus
< GetNumBussesOut(); wBus
++)
1936 for ( wPipe
= 0; wPipe
< GetNumPipesOut(); wPipe
++)
1938 m_PipeOutCtrl
.SetGain(wPipe
,wBus
,ECHOGAIN_UPDATE
,FALSE
);
1942 for ( i
= 0; i
< GetNumBussesOut(); i
++ )
1944 m_BusOutLineLevels
[ i
].SetGain(ECHOGAIN_UPDATE
,FALSE
);
1947 for ( i
= 0; i
< GetNumBussesIn(); i
++ )
1949 m_BusInLineLevels
[ i
].SetGain( ECHOGAIN_UPDATE
);
1953 // Now set them all at once, since all the
1954 // fImmediate parameters were set to FALSE. Do the output
1955 // bus _and_ the output pipe in case this is a vmixer card.
1957 m_BusOutLineLevels
[0].SetGain(ECHOGAIN_UPDATE
,TRUE
);
1958 m_PipeOutCtrl
.SetGain(0,0,ECHOGAIN_UPDATE
,TRUE
);
1962 // If the card has just been put in ADAT mode, it is possible
1963 // that the locked sample rate is greater than 48KHz, which is not allowed
1964 // in ADAT mode. If this happens, change the locked rate to 48.
1966 if ( (DIGITAL_MODE_ADAT
== byDigitalMode
) &&
1967 (m_wFlags
& ECHOGALS_FLAG_SAMPLE_RATE_LOCKED
) &&
1968 (m_dwLockedSampleRate
> 48000) )
1970 m_dwLockedSampleRate
= 48000;
1975 } // ECHOSTATUS CEchoGals::SetDigitalMode( ... )
1980 The output bus gain controls aren't actually implemented in the hardware;
1981 insted they are virtual controls created by the generic code.
1983 The signal sent to an output bus is a mix of the monitors and output pipes
1984 routed to that bus; the output bus gain is therefore implemented by tweaking
1985 each appropriate monitor and output pipe gain.
1990 //===========================================================================
1992 // Adjust all the monitor levels for a particular output bus
1994 // For efficiency, fImmediate is set to FALSE in the call
1995 // to SetGain; all the monitor and pipe out gains are
1996 // sent to the DSP at once by AdjustPipesOutForBusOut.
1998 //===========================================================================
2000 ECHOSTATUS
CEchoGals::AdjustMonitorsForBusOut(WORD wBusOut
)
2005 // Poke the monitors
2007 for (wBusIn
= 0; wBusIn
< GetNumBussesIn(); wBusIn
++)
2009 m_MonitorCtrl
.SetGain(wBusIn
,wBusOut
,ECHOGAIN_UPDATE
,FALSE
);
2012 return ECHOSTATUS_OK
;
2014 } // AdjustMonitorsForBusOut
2017 //===========================================================================
2019 // Adjust all the pipe out levels for a particular output bus
2021 // For efficiency, fImmediate is set to FALSE in the call
2022 // to SetGain; all the monitor and pipe out gains are
2023 // sent to the DSP at once by AdjustPipesOutForBusOut.
2025 //===========================================================================
2027 ECHOSTATUS
CEchoGals::AdjustPipesOutForBusOut(WORD wBusOut
,INT32 iBusOutGain
)
2029 ECHO_DEBUGPRINTF(("CEchoGals::AdjustPipesOutForBusOut wBusOut %d iBusOutGain %ld\n",
2034 // Round down to the nearest even bus
2038 m_PipeOutCtrl
.SetGain(wBusOut
,wBusOut
,ECHOGAIN_UPDATE
,FALSE
);
2040 m_PipeOutCtrl
.SetGain(wBusOut
,wBusOut
,ECHOGAIN_UPDATE
,TRUE
);
2042 return ECHOSTATUS_OK
;
2044 } // AdjustPipesOutForBusOut
2048 //===========================================================================
2050 // GetAudioLatency - returns the latency for a single pipe
2052 //===========================================================================
2054 void CEchoGals::GetAudioLatency(ECHO_AUDIO_LATENCY
*pLatency
)
2058 if (FALSE
== pLatency
->wIsInput
)
2060 if (pLatency
->wPipe
>= GetFirstDigitalBusOut())
2061 dwLatency
= m_wDigitalOutputLatency
;
2063 dwLatency
= m_wAnalogOutputLatency
;
2067 if (pLatency
->wPipe
>= GetFirstDigitalBusIn())
2068 dwLatency
= m_wDigitalInputLatency
;
2070 dwLatency
= m_wAnalogInputLatency
;
2073 pLatency
->dwLatency
= dwLatency
;
2075 } // GetAudioLatency