Tom's Guide | Tom's Hardware | Tom's Games
![]() |
![]() |
![]() |
Well, my last problem got solved so quickly (thanks Jeff!) that I've decided to try again :). This problem will probably be a little tougher, though.
I'm using an EDIROL UA-1A in a custom app in order to record some audio. The UA-1A accepts analog stereo input and transfers this along through the USB port. Edirol's drivers don't include volume control, and the custom program I'm using treats all the UA-1A audio as waveform audio with no problems.
I'm using the code that Jeff helped me with and am having problem accessing my USB audio device with mixerGetLineControls. I only even get to that problem, however, after I force-feed a device line to my functions, as I'm first having problems with enumeration. Guessing that if whatever is screwing up enumeration is screwing up everything else, here's the enumeration code:
bool CVolumeInXXX::EnumerateInputLines( PINPUTLINEPROC pUserCallback, DWORD dwUserValue )
{
if ( !pUserCallback )
return false;
MMRESULT mmResult;
HWAVEIN hwaveIn;
WAVEFORMATEX WaveFmt;
SetDeviceType( &WaveFmt );
mmResult = waveInOpen( &hwaveIn, WAVE_MAPPER, &WaveFmt, 0L, 0L, CALLBACK_NULL );
if ( mmResult != MMSYSERR_NOERROR )
{
TRACE(".InputXxxVolume: FAILURE: Could not open WaveIn Mapper. mmResult=%d\n", mmResult );
return false;
}
UINT uMixerID;
DWORD dwMixerHandle;
mmResult = mixerGetID( (HMIXEROBJ)hwaveIn, &uMixerID, MIXER_OBJECTF_HWAVEIN );
waveInClose( hwaveIn );
if ( mmResult != MMSYSERR_NOERROR )
{
TRACE(".InputXxxVolume: FAILURE: WaveIn Mapper in Mixer is not available. mmResult=%d\n", mmResult );
return false;
}
mmResult = mixerOpen( (LPHMIXER)&dwMixerHandle, uMixerID, 0L, 0L, 0L );
if ( mmResult != MMSYSERR_NOERROR )
{
mixerClose( (HMIXER)dwMixerHandle );
TRACE(".InputXxxVolume: FAILURE: Could not open Mixer. mmResult=%d\n", mmResult );
return false;
}
MIXERLINE MixerLine;
memset( &MixerLine, 0, sizeof(MIXERLINE) );
MixerLine.cbStruct = sizeof(MIXERLINE);
MixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
mmResult = mixerGetLineInfo( (HMIXEROBJ)dwMixerHandle, &MixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE );
if ( mmResult != MMSYSERR_NOERROR )
{
mixerClose( (HMIXER)dwMixerHandle );
TRACE(".InputXxxVolume: FAILURE: Could not get WaveIn Destionation Line for the requested source while enumerating. mmResult=%d\n", mmResult );
return false;
}
MIXERLINE Line;
for ( UINT uLineIndex = 0; uLineIndex dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE )
if ( pLineInfo->dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_DIGITAL )
{
*((UINT*)dwUserValue) = uLineIndex;
return false;
}
return true;
}
which now works thanks to Jeff :).My first guess was that I was simply selecting the wrong component type for USB audio, but I've gone through EVERY component type that I can find and none work. When I forcefeed a line number to my functions, line "0" works for a couple of mixerGetLineControl calls but craps out after that.
I've done a lot of searching and many people seem to have the same problem with USB audio. I'm guessing it's common; maybe that's why Edirol didn't include any volume control w/their product :).
Regardless, any help or information on the problem in general that anyone can provide would be met with incredible, incredible gratitude.
Roch

No need to butter me up ;). Well, it's been quite a while, and certainly before USB came along, but I'll share what I can. I take it you want to control the wave in and wave out volume levels in your app, so that ideally you wish to control the lines when dwComponentType is MIXERLINE_COMPONENTTYPE_DST_WAVEIN and MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT.
Bear with me, as I do not know what you've done so far, but have you called waveOutGetDevCaps with indeces from zero to (waveOutGetNumDevs -1)? The returned szPname field of WAVEOUTCAPS should identify your driver by name, and the dwSupport bit field should hopefully AND to true with WAVECAPS_VOLUME (whether volume changes are supported).
I seem to recall that mixerGetLineControl can be picky about certain parameters. When you said it always fails it rang a bell (I'm not senile yet!). It sounds like that function is returning an error for the *_WAVEOUT and *_WAVEIN component types, but I'm unclear what you mean when you say setting the line ID to zero does work sometimes. Are you also calling with MIXER_GETLINEINFOF_LINEID?
Unfortunately, this forum eats code when it encounters a less-than character, so I think some of your for loop and other code was lost in the post (very nice formatting, though). If you replace them with ampersand+"lt"+semicolon (HTML equivalent), and make sure there is a trailing space, it should post better. If you could post more about some specific failures, I might be able to help better. Feel free to write away (as I usually do ;).

Hi Jeff,
I've taken your advice and have started from scratch, hopefully only temporarily, with the following code:
WAVEOUTCAPS woc;
MMRESULT mmResult = waveOutGetDevCaps((UINT)WAVE_MAPPER,&woc,sizeof(woc));if (mmResult == MMSYSERR_NOERROR)
{
TRACE("Driver name %s\n", woc.szPname);
if (woc.dwSupport & WAVECAPS_VOLUME)
TRACE("Volume Control Supported\n");
else
TRACE("No Volume Control\n");
}
else
TRACE("Error %d\n", mmResult);
HWAVEIN hwaveIn;
WAVEFORMATEX WaveFmt;
SetDeviceType( &WaveFmt );
mmResult = waveInOpen( &hwaveIn, WAVE_MAPPER, &WaveFmt, 0L, 0L, CALLBACK_NULL );
if ( mmResult != MMSYSERR_NOERROR )
TRACE("FAILURE: Could not open WaveIn Mapper. mmResult=%d\n", mmResult );
UINT uMixerID;
DWORD dwMixerHandle;
mmResult = mixerGetID( (HMIXEROBJ)hwaveIn, &uMixerID, MIXER_OBJECTF_HWAVEIN );
waveInClose( hwaveIn );
if ( mmResult != MMSYSERR_NOERROR )
TRACE(".InputXxxVolume: FAILURE: WaveIn Mapper in Mixer is not available. mmResult=%d\n", mmResult );
mmResult = mixerOpen( (LPHMIXER)&dwMixerHandle, uMixerID, 0L, 0L, 0L );
if ( mmResult != MMSYSERR_NOERROR )
{
mixerClose( (HMIXER)dwMixerHandle );
TRACE("FAILURE: Could not open Mixer. mmResult=%d\n", mmResult );
}
MIXERLINE MixerLine;
memset( &MixerLine, 0, sizeof(MIXERLINE) );
MixerLine.cbStruct = sizeof(MIXERLINE);
MixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
mmResult = mixerGetLineInfo( (HMIXEROBJ)dwMixerHandle, &MixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE );
if ( mmResult != MMSYSERR_NOERROR )
{
mixerClose( (HMIXER)dwMixerHandle );
TRACE("FAILURE: Could not get WaveIn Destionation Line for the requested source while enumerating. mmResult=%d\n", mmResult );
}
else
{
TRACE("Name: %s\n", MixerLine.szName);
TRACE("Source Line: %d\n", MixerLine.dwSource);
TRACE("ComponentType: %d\n", MixerLine.dwComponentType);
}
TRACE("MixerLine.cConnections: %d\n", MixerLine.cConnections);
MIXERLINE Line;
for ( UINT uLineIndex = 0; uLineIndex < MixerLine.cConnections; uLineIndex++ )
{
memset( &Line, 0, sizeof(MIXERLINE) );
Line.cbStruct = sizeof(MIXERLINE);
Line.dwDestination = MixerLine.dwDestination;
Line.dwSource = uLineIndex;
mmResult = mixerGetLineInfo( (HMIXEROBJ)dwMixerHandle, &Line, MIXER_GETLINEINFOF_LINEID);
//mmResult = mixerGetLineInfo( (HMIXEROBJ)dwMixerHandle, &Line, MIXER_GETLINEINFOF_SOURCE);
if ( mmResult != MMSYSERR_NOERROR )
{
mixerClose( (HMIXER)dwMixerHandle );
TRACE("FAILURE: Could not get the interated Source Line while enumerating. mmResult=%d\n", mmResult );
}
else
{
TRACE("Name: %s\n", MixerLine.szName);
TRACE("Source Line: %d\n", MixerLine.dwSource);
TRACE("LineID: %d\n", MixerLine.dwLineID);
TRACE("ComponentType: %d\n", MixerLine.dwComponentType);
}
}
mixerClose( (HMIXER)dwMixerHandle );And my debugger said:
Driver name Microsoft Sound Mapper
Volume Control Supported
Name: Wave In
Source Line: -1
ComponentType: 7
MixerLine.cConnections: 1
Name: Wave In
Source Line: -1
LineID: -65535
ComponentType: 7I have no problem using the USB audio when I don't need volume control, and even checking to see if volume control returns positive results. When I try to index the source line, though, which is what is happening during enumeration, I get -1. Yeah. That's not right. The -65535 line ID also sets off some alarms; gee, just call it "programmer's intuition."
While Windows apparently has no problems opening the USB Audio device, mixerGetLineInfo is really crapping out when it comes to getting information like the source line and line id's. Without these, I think what's happening is that down the road the mixerSetControlDetails function can't, well, set any control details like volume. Thus, USB volume control is non-existant.
Could this potentially be a problem with the device itself? The software that came with the Edirol UA-1A doesn't have volume control, so I'm wondering if it just doesn't return the necessary info for volume control to take place. If that's not the case, then any help with these software bugs would be incredibly appreciated!
Cheers,

This will take a fair bit of back-and-forth communicating, so I will send you an email about this. Besides, it will make viewing code much easier for both of us :) I'm sure this will be worked out, yet I hope this does not discourage anyone else from joining in.
Jeff J

![]() |
![]() |
![]() |

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.
| Ads by Google |