Volume control for QAudioInput windows backend.

Change-Id: I1245a38c68254fc48373a856dc44e8ad8142636e
Reviewed-by: Ling Hu <ling.hu@nokia.com>
This commit is contained in:
Lev Zelenskiy
2012-07-25 13:23:57 +10:00
committed by Qt by Nokia
parent 64dbf9d968
commit 403eee4d87
2 changed files with 115 additions and 0 deletions

View File

@@ -72,11 +72,16 @@ QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device)
resuming = false; resuming = false;
finished = false; finished = false;
waveBlockOffset = 0; waveBlockOffset = 0;
mixerID = 0;
memset(&mixerLineControls, 0, sizeof(mixerLineControls));
initMixer();
} }
QAudioInputPrivate::~QAudioInputPrivate() QAudioInputPrivate::~QAudioInputPrivate()
{ {
stop(); stop();
closeMixer();
} }
void QT_WIN_CALLBACK QAudioInputPrivate::waveInProc( HWAVEIN hWaveIn, UINT uMsg, void QT_WIN_CALLBACK QAudioInputPrivate::waveInProc( HWAVEIN hWaveIn, UINT uMsg,
@@ -163,6 +168,71 @@ QAudio::State QAudioInputPrivate::state() const
return deviceState; return deviceState;
} }
#ifndef DRVM_MAPPER_CONSOLEVOICECOM_GET
#ifndef DRVM_MAPPER
#define DRVM_MAPPER 0x2000
#endif
#ifndef DRVM_MAPPER_STATUS
#define DRVM_MAPPER_STATUS (DRVM_MAPPER+0)
#endif
#define DRVM_USER 0x4000
#define DRVM_MAPPER_RECONFIGURE (DRVM_MAPPER+1)
#define DRVM_MAPPER_PREFERRED_GET (DRVM_MAPPER+21)
#define DRVM_MAPPER_CONSOLEVOICECOM_GET (DRVM_MAPPER+23)
#endif
void QAudioInputPrivate::setVolume(qreal volume)
{
for (DWORD i = 0; i < mixerLineControls.cControls; i++) {
MIXERCONTROLDETAILS controlDetails;
controlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
controlDetails.dwControlID = mixerLineControls.pamxctrl[i].dwControlID;
controlDetails.cChannels = 1;
if ((mixerLineControls.pamxctrl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_FADER) ||
(mixerLineControls.pamxctrl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)) {
MIXERCONTROLDETAILS_UNSIGNED controlDetailsUnsigned;
controlDetailsUnsigned.dwValue = qBound(DWORD(0), DWORD(65535.0 * volume + 0.5), DWORD(65535));
controlDetails.cMultipleItems = 0;
controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
controlDetails.paDetails = &controlDetailsUnsigned;
mixerSetControlDetails((HMIXEROBJ)mixerID, &controlDetails, MIXER_SETCONTROLDETAILSF_VALUE);
}
}
}
qreal QAudioInputPrivate::volume() const
{
DWORD volume = 0;
for (DWORD i = 0; i < mixerLineControls.cControls; i++) {
if ((mixerLineControls.pamxctrl[i].dwControlType != MIXERCONTROL_CONTROLTYPE_FADER) &&
(mixerLineControls.pamxctrl[i].dwControlType != MIXERCONTROL_CONTROLTYPE_VOLUME)) {
continue;
}
MIXERCONTROLDETAILS controlDetails;
controlDetails.cbStruct = sizeof(controlDetails);
controlDetails.dwControlID = mixerLineControls.pamxctrl[i].dwControlID;
controlDetails.cChannels = 1;
controlDetails.cMultipleItems = 0;
controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
MIXERCONTROLDETAILS_UNSIGNED detailsUnsigned;
controlDetails.paDetails = &detailsUnsigned;
memset(controlDetails.paDetails, 0, controlDetails.cbDetails);
MMRESULT result = mixerGetControlDetails((HMIXEROBJ)mixerID, &controlDetails, MIXER_GETCONTROLDETAILSF_VALUE);
if (result != MMSYSERR_NOERROR)
continue;
if (controlDetails.cbDetails < sizeof(MIXERCONTROLDETAILS_UNSIGNED))
continue;
volume = detailsUnsigned.dwValue;
break;
}
return volume / 65535.0;
}
void QAudioInputPrivate::setFormat(const QAudioFormat& fmt) void QAudioInputPrivate::setFormat(const QAudioFormat& fmt)
{ {
if (deviceState == QAudio::StoppedState) if (deviceState == QAudio::StoppedState)
@@ -351,6 +421,44 @@ void QAudioInputPrivate::close()
} }
} }
void QAudioInputPrivate::initMixer()
{
QDataStream ds(&m_device, QIODevice::ReadOnly);
quint32 inputDevice;
ds >> inputDevice;
if (int(inputDevice) < 0)
return;
// Get the Mixer ID from the Sound Device ID
if (mixerGetID((HMIXEROBJ)inputDevice, &mixerID, MIXER_OBJECTF_WAVEIN) != MMSYSERR_NOERROR)
return;
// Get the Destination (Recording) Line Infomation
MIXERLINE mixerLine;
mixerLine.cbStruct = sizeof(MIXERLINE);
mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
if (mixerGetLineInfo((HMIXEROBJ)mixerID, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR)
return;
// Set all the Destination (Recording) Line Controls
if (mixerLine.cControls > 0) {
mixerLineControls.cbStruct = sizeof(MIXERLINECONTROLS);
mixerLineControls.dwLineID = mixerLine.dwLineID;
mixerLineControls.cControls = mixerLine.cControls;
mixerLineControls.cbmxctrl = sizeof(MIXERCONTROL);
mixerLineControls.pamxctrl = new MIXERCONTROL[mixerLineControls.cControls];
if (mixerGetLineControls((HMIXEROBJ)mixerID, &mixerLineControls, MIXER_GETLINECONTROLSF_ALL) != MMSYSERR_NOERROR)
closeMixer();
}
}
void QAudioInputPrivate::closeMixer()
{
delete[] mixerLineControls.pamxctrl;
memset(&mixerLineControls, 0, sizeof(mixerLineControls));
}
int QAudioInputPrivate::bytesReady() const int QAudioInputPrivate::bytesReady() const
{ {
if(period_size == 0 || buffer_size == 0) if(period_size == 0 || buffer_size == 0)

View File

@@ -114,6 +114,8 @@ public:
qint64 elapsedUSecs() const; qint64 elapsedUSecs() const;
QAudio::Error error() const; QAudio::Error error() const;
QAudio::State state() const; QAudio::State state() const;
void setVolume(qreal volume);
qreal volume() const;
QIODevice* audioSource; QIODevice* audioSource;
QAudioFormat settings; QAudioFormat settings;
@@ -150,6 +152,11 @@ private:
bool open(); bool open();
void close(); void close();
void initMixer();
void closeMixer();
UINT mixerID;
MIXERLINECONTROLS mixerLineControls;
private slots: private slots:
void feedback(); void feedback();
bool deviceReady(); bool deviceReady();