Commit 052c7215 authored by aymeric's avatar aymeric
Browse files

Fix directsound & MME capture volume level & mute.

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@596 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
parent 98354289
......@@ -62,6 +62,11 @@ static void winsndcard_set_level(MSSndCard *card, MSSndCardMixerElem e, int perc
MIXERLINE Line;
UINT uLineIndex;
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_UNSIGNED mcdu = {0};
MMRESULT mr = MMSYSERR_NOERROR;
DWORD dwVolume = ((0xFFFF) * percent) / 100;
......@@ -76,11 +81,6 @@ static void winsndcard_set_level(MSSndCard *card, MSSndCardMixerElem e, int perc
case MS_SND_CARD_PLAYBACK:
case MS_SND_CARD_MASTER:
{
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_UNSIGNED mcdu = {0};
mr = mixerGetID( (HMIXEROBJ)d->out_devid, &uMixerID, MIXER_OBJECTF_WAVEOUT );
if ( mr != MMSYSERR_NOERROR )
{
......@@ -168,6 +168,43 @@ static void winsndcard_set_level(MSSndCard *card, MSSndCardMixerElem e, int perc
/* ms_message("Source Line: %d\n", MixerLine.dwSource); */
/* ms_message("ComponentType: %d\n", MixerLine.dwComponentType); */
mlc.cbStruct = sizeof(MIXERLINECONTROLS);
mlc.dwLineID = MixerLine.dwLineID;
mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mlc.cControls = 1;
mlc.pamxctrl = &mc;
mlc.cbmxctrl = sizeof(MIXERCONTROL);
mr = mixerGetLineControls((HMIXEROBJ)dwMixerHandle,
&mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (mr == MMSYSERR_NOERROR)
{
mcdu.dwValue = 65535*percent/100; /* the volume is a number between 0 and 65535 */
mcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mcd.hwndOwner = 0;
mcd.dwControlID = mc.dwControlID;
mcd.paDetails = &mcdu;
mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mcd.cChannels = 1;
mr = mixerSetControlDetails((HMIXEROBJ)dwMixerHandle,
&mcd, MIXER_SETCONTROLDETAILSF_VALUE);
if (mr == MMSYSERR_NOERROR)
{
return;
}
ms_error("winsndcard_set_level: mixerSetControlDetails failed. (0x%x)", mr);
ms_warning("winsndcard_set_level: control the SRC_MICROPHONE instead");
}
else
{
ms_error("winsndcard_set_level: mixerGetLineControls failed. (0x%x)", mr);
ms_warning("winsndcard_set_level: control the SRC_MICROPHONE instead");
}
/* In case capture doesn't work: use the SRC_MICROPHONE volume */
for (uLineIndex = 0; uLineIndex < MixerLine.cConnections; uLineIndex++)
{
memset( &Line, 0, sizeof(MIXERLINE) );
......@@ -260,6 +297,11 @@ static int winsndcard_get_level(MSSndCard *card, MSSndCardMixerElem e){
MIXERLINE Line;
UINT uLineIndex;
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_UNSIGNED mcdu = {0};
MMRESULT mr = MMSYSERR_NOERROR;
int percent;
......@@ -267,11 +309,6 @@ static int winsndcard_get_level(MSSndCard *card, MSSndCardMixerElem e){
case MS_SND_CARD_MASTER:
case MS_SND_CARD_PLAYBACK:
{
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_UNSIGNED mcdu = {0};
mr = mixerGetID( (HMIXEROBJ)d->out_devid, &uMixerID, MIXER_OBJECTF_WAVEOUT );
if ( mr != MMSYSERR_NOERROR )
{
......@@ -360,6 +397,39 @@ static int winsndcard_get_level(MSSndCard *card, MSSndCardMixerElem e){
return -1;
}
mlc.cbStruct = sizeof(MIXERLINECONTROLS);
mlc.dwLineID = MixerLine.dwLineID;
mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mlc.cControls = 1;
mlc.pamxctrl = &mc;
mlc.cbmxctrl = sizeof(MIXERCONTROL);
mr = mixerGetLineControls((HMIXEROBJ)dwMixerHandle,
&mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (mr == MMSYSERR_NOERROR)
{
mcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mcd.hwndOwner = 0;
mcd.dwControlID = mc.dwControlID;
mcd.paDetails = &mcdu;
mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mcd.cChannels = 1;
mr = mixerGetControlDetails((HMIXEROBJ)dwMixerHandle, &mcd,
MIXER_SETCONTROLDETAILSF_VALUE);
percent = (mcdu.dwValue *100) / (mc.Bounds.dwMaximum);
if (mr == MMSYSERR_NOERROR)
{
return percent;
}
ms_error("winsndcard_get_level: mixerGetControlDetails failed. (0x%x)", mr);
ms_warning("winsndcard_get_level: control the SRC_MICROPHONE instead");
}
else
{
ms_error("winsndcard_get_level: mixerGetLineControls failed. (0x%x)", mr);
ms_warning("winsndcard_get_level: control the SRC_MICROPHONE instead");
}
/* ms_message("Name: %s\n", MixerLine.szName); */
/* ms_message("Source Line: %d\n", MixerLine.dwSource); */
/* ms_message("ComponentType: %d\n", MixerLine.dwComponentType); */
......@@ -466,11 +536,18 @@ static int winsndcard_set_control(MSSndCard *card, MSSndCardControlElem e, int v
MIXERLINE Line;
UINT uLineIndex;
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_BOOLEAN bMute;
MMRESULT mr = MMSYSERR_NOERROR;
switch(e){
case MS_SND_CARD_CAPTURE_MUTE:
bMute.fValue = (val>0);
mr = mixerGetID( (HMIXEROBJ)d->in_devid, &uMixerID, MIXER_OBJECTF_WAVEIN );
if ( mr != MMSYSERR_NOERROR )
{
......@@ -582,11 +659,6 @@ static int winsndcard_set_control(MSSndCard *card, MSSndCardControlElem e, int v
case MS_SND_CARD_MASTER_MUTE:
case MS_SND_CARD_PLAYBACK_MUTE:
{
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_BOOLEAN bMute;
bMute.fValue = (val>0);
mr = mixerGetID( (HMIXEROBJ)d->out_devid, &uMixerID, MIXER_OBJECTF_WAVEOUT );
......
......@@ -146,6 +146,11 @@ static void winsnddscard_set_level(MSSndCard *card, MSSndCardMixerElem e, int pe
MIXERLINE Line;
UINT uLineIndex;
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_UNSIGNED mcdu = {0};
MMRESULT mr = MMSYSERR_NOERROR;
DWORD dwVolume = ((0xFFFF) * percent) / 100;
......@@ -163,10 +168,6 @@ static void winsnddscard_set_level(MSSndCard *card, MSSndCardMixerElem e, int pe
case MS_SND_CARD_PLAYBACK:
case MS_SND_CARD_MASTER:
{
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_UNSIGNED mcdu = {0};
mr = mixerGetID( (HMIXEROBJ)waveout_devid, &uMixerID, MIXER_OBJECTF_WAVEOUT );
if ( mr != MMSYSERR_NOERROR )
......@@ -208,6 +209,11 @@ static void winsnddscard_set_level(MSSndCard *card, MSSndCardMixerElem e, int pe
mr = mixerGetLineControls((HMIXEROBJ)dwMixerHandle,
&mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (mr != MMSYSERR_NOERROR)
{
ms_error("winsndcard_set_level: mixerGetLineControls failed. (0x%x)", mr);
return;
}
mcdu.dwValue = 65535*percent/100; /* the volume is a number between 0 and 65535 */
......@@ -234,7 +240,7 @@ static void winsnddscard_set_level(MSSndCard *card, MSSndCardMixerElem e, int pe
ms_error("winsndcard_set_level: mixerGetID failed. (0x%x)", mr);
return;
}
mr = mixerOpen( (LPHMIXER)&dwMixerHandle, uMixerID, 0L, 0L, 0L );
mr = mixerOpen( (LPHMIXER)&dwMixerHandle, uMixerID, 0L, 0L, 0L );
if ( mr != MMSYSERR_NOERROR )
{
mixerClose( (HMIXER)dwMixerHandle );
......@@ -251,10 +257,48 @@ static void winsnddscard_set_level(MSSndCard *card, MSSndCardMixerElem e, int pe
ms_error("winsndcard_set_level: mixerGetLineInfo failed. (0x%x)", mr);
return;
}
/* ms_message("Name: %s\n", MixerLine.szName); */
/* ms_message("Source Line: %d\n", MixerLine.dwSource); */
/* ms_message("ComponentType: %d\n", MixerLine.dwComponentType); */
mlc.cbStruct = sizeof(MIXERLINECONTROLS);
mlc.dwLineID = MixerLine.dwLineID;
mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mlc.cControls = 1;
mlc.pamxctrl = &mc;
mlc.cbmxctrl = sizeof(MIXERCONTROL);
mr = mixerGetLineControls((HMIXEROBJ)dwMixerHandle,
&mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (mr == MMSYSERR_NOERROR)
{
mcdu.dwValue = 65535*percent/100; /* the volume is a number between 0 and 65535 */
mcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mcd.hwndOwner = 0;
mcd.dwControlID = mc.dwControlID;
mcd.paDetails = &mcdu;
mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mcd.cChannels = 1;
mr = mixerSetControlDetails((HMIXEROBJ)dwMixerHandle,
&mcd, MIXER_SETCONTROLDETAILSF_VALUE);
if (mr == MMSYSERR_NOERROR)
{
return;
}
ms_error("winsndcard_set_level: mixerSetControlDetails failed. (0x%x)", mr);
ms_warning("winsndcard_set_level: control the SRC_MICROPHONE instead");
}
else
{
ms_error("winsndcard_set_level: mixerGetLineControls failed. (0x%x)", mr);
ms_warning("winsndcard_set_level: control the SRC_MICROPHONE instead");
}
/* In case capture doesn't work: use the SRC_MICROPHONE volume */
for (uLineIndex = 0; uLineIndex < MixerLine.cConnections; uLineIndex++)
{
memset( &Line, 0, sizeof(MIXERLINE) );
......@@ -294,36 +338,48 @@ static void winsnddscard_set_level(MSSndCard *card, MSSndCardMixerElem e, int pe
if (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE == Line.dwComponentType)
{
LPMIXERCONTROL pmxctrl = (LPMIXERCONTROL)malloc(sizeof(MIXERCONTROL));
MIXERLINECONTROLS mxlctrl = {sizeof(mxlctrl), Line.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME, 1, sizeof(MIXERCONTROL), pmxctrl};
if(!mixerGetLineControls((HMIXEROBJ)dwMixerHandle, &mxlctrl,
MIXER_GETLINECONTROLSF_ONEBYTYPE)){
DWORD cChannels = Line.cChannels;
LPMIXERCONTROLDETAILS_UNSIGNED pUnsigned;
MIXERCONTROLDETAILS mxcd;
if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl->fdwControl)
cChannels = 1;
pUnsigned =
(LPMIXERCONTROLDETAILS_UNSIGNED)
malloc(cChannels * sizeof(MIXERCONTROLDETAILS_UNSIGNED));
MIXERLINECONTROLS mxlctrl = {sizeof(mxlctrl), Line.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME, 1, sizeof(MIXERCONTROL), pmxctrl};
mr = mixerGetLineControls((HMIXEROBJ)dwMixerHandle, &mxlctrl, MIXER_GETLINECONTROLSF_ONEBYTYPE);
if(!mr){
DWORD cChannels = Line.cChannels;
LPMIXERCONTROLDETAILS_UNSIGNED pUnsigned;
MIXERCONTROLDETAILS mxcd;
if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl->fdwControl)
cChannels = 1;
pUnsigned =
(LPMIXERCONTROLDETAILS_UNSIGNED)
malloc(cChannels * sizeof(MIXERCONTROLDETAILS_UNSIGNED));
mxcd.cbStruct = sizeof(mxcd);
mxcd.dwControlID = pmxctrl->dwControlID;
mxcd.cChannels = cChannels;
mxcd.hwndOwner = (HWND)0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = (LPVOID) pUnsigned;
mxcd.cbStruct = sizeof(mxcd);
mxcd.dwControlID = pmxctrl->dwControlID;
mxcd.cChannels = cChannels;
mxcd.hwndOwner = (HWND)0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = (LPVOID) pUnsigned;
mixerGetControlDetails((HMIXEROBJ)dwMixerHandle, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
mr = mixerGetControlDetails((HMIXEROBJ)dwMixerHandle, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
if(!mr){
pUnsigned[0].dwValue = pUnsigned[cChannels - 1].dwValue
= pmxctrl->Bounds.dwMaximum*percent/100;
mixerSetControlDetails((HMIXEROBJ)dwMixerHandle, &mxcd,
mr = mixerSetControlDetails((HMIXEROBJ)dwMixerHandle, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
free(pmxctrl);
free(pUnsigned);
if(mr){
ms_error("winsndcard_set_level: mixerSetControlDetails failed. (0x%x)", mr);
}
}
else
{
ms_error("winsndcard_set_level: mixerGetControlDetails failed. (0x%x)", mr);
}
free(pmxctrl);
free(pUnsigned);
}
else
free(pmxctrl);
{
ms_error("winsndcard_set_level: mixerGetLineControls failed. (0x%x)", mr);
free(pmxctrl);
}
}
}
mixerClose( (HMIXER)dwMixerHandle );
......@@ -349,6 +405,11 @@ static int winsnddscard_get_level(MSSndCard *card, MSSndCardMixerElem e){
MIXERLINE Line;
UINT uLineIndex;
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_UNSIGNED mcdu = {0};
MMRESULT mr = MMSYSERR_NOERROR;
int percent;
......@@ -359,11 +420,6 @@ static int winsnddscard_get_level(MSSndCard *card, MSSndCardMixerElem e){
case MS_SND_CARD_MASTER:
case MS_SND_CARD_PLAYBACK:
{
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_UNSIGNED mcdu = {0};
mr = mixerGetID( (HMIXEROBJ)waveout_devid, &uMixerID, MIXER_OBJECTF_WAVEOUT );
if ( mr != MMSYSERR_NOERROR )
{
......@@ -456,6 +512,39 @@ static int winsnddscard_get_level(MSSndCard *card, MSSndCardMixerElem e){
/* ms_message("Source Line: %d\n", MixerLine.dwSource); */
/* ms_message("ComponentType: %d\n", MixerLine.dwComponentType); */
mlc.cbStruct = sizeof(MIXERLINECONTROLS);
mlc.dwLineID = MixerLine.dwLineID;
mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mlc.cControls = 1;
mlc.pamxctrl = &mc;
mlc.cbmxctrl = sizeof(MIXERCONTROL);
mr = mixerGetLineControls((HMIXEROBJ)dwMixerHandle,
&mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (mr == MMSYSERR_NOERROR)
{
mcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mcd.hwndOwner = 0;
mcd.dwControlID = mc.dwControlID;
mcd.paDetails = &mcdu;
mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mcd.cChannels = 1;
mr = mixerGetControlDetails((HMIXEROBJ)dwMixerHandle, &mcd,
MIXER_SETCONTROLDETAILSF_VALUE);
percent = (mcdu.dwValue *100) / (mc.Bounds.dwMaximum);
if (mr == MMSYSERR_NOERROR)
{
return percent;
}
ms_error("winsndcard_get_level: mixerGetControlDetails failed. (0x%x)", mr);
ms_warning("winsndcard_get_level: control the SRC_MICROPHONE instead");
}
else
{
ms_error("winsndcard_get_level: mixerGetLineControls failed. (0x%x)", mr);
ms_warning("winsndcard_get_level: control the SRC_MICROPHONE instead");
}
for (uLineIndex = 0; uLineIndex < MixerLine.cConnections; uLineIndex++)
{
memset( &Line, 0, sizeof(MIXERLINE) );
......@@ -492,7 +581,7 @@ static int winsnddscard_get_level(MSSndCard *card, MSSndCardMixerElem e){
/* ms_message("LineID: %d\n", MixerLine.dwLineID); */
/* ms_message("ComponentType: %d\n", MixerLine.dwComponentType); */
if (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE == Line.dwComponentType)
if (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE == Line.dwComponentType)
{
LPMIXERCONTROL pmxctrl = (LPMIXERCONTROL)malloc(sizeof(MIXERCONTROL));
MIXERLINECONTROLS mxlctrl = {sizeof(mxlctrl), Line.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME, 1, sizeof(MIXERCONTROL), pmxctrl};
......@@ -560,6 +649,11 @@ static int winsnddscard_set_control(MSSndCard *card, MSSndCardControlElem e, int
MIXERLINE Line;
UINT uLineIndex;
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_BOOLEAN bMute;
MMRESULT mr = MMSYSERR_NOERROR;
GetWaveIdFromDSoundGUID(d->in_guid, &wavein_devid);
......@@ -567,6 +661,7 @@ static int winsnddscard_set_control(MSSndCard *card, MSSndCardControlElem e, int
switch(e){
case MS_SND_CARD_CAPTURE_MUTE:
bMute.fValue = (val>0);
mr = mixerGetID( (HMIXEROBJ)wavein_devid, &uMixerID, MIXER_OBJECTF_WAVEIN );
if ( mr != MMSYSERR_NOERROR )
......@@ -595,6 +690,39 @@ static int winsnddscard_set_control(MSSndCard *card, MSSndCardControlElem e, int
/* ms_message("Source Line: %d\n", MixerLine.dwSource); */
/* ms_message("ComponentType: %d\n", MixerLine.dwComponentType); */
mlc.cbStruct = sizeof(MIXERLINECONTROLS);
mlc.dwLineID = MixerLine.dwLineID;
mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE; //MIXERCONTROL_CONTROLTYPE_VOLUME;
mlc.cControls = 1;
mlc.pamxctrl = &mc;
mlc.cbmxctrl = sizeof(MIXERCONTROL);
mr = mixerGetLineControls((HMIXEROBJ)dwMixerHandle,
&mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (mr == MMSYSERR_NOERROR)
{
mcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mcd.hwndOwner = 0;
mcd.dwControlID = mc.dwControlID;
mcd.paDetails = &bMute;
mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
mcd.cChannels = 1;
mr = mixerSetControlDetails((HMIXEROBJ)dwMixerHandle,
&mcd, MIXER_SETCONTROLDETAILSF_VALUE);
if (mr == MMSYSERR_NOERROR)
{
return 0;
}
ms_error("winsndcard_set_control: mixerSetControlDetails failed. (0x%x)", mr);
ms_warning("winsndcard_get_level: control the SRC_MICROPHONE instead");
}
else
{
ms_error("winsndcard_set_control: mixerGetLineControls failed. (0x%x)", mr);
ms_warning("winsndcard_get_level: control the SRC_MICROPHONE instead");
}
for (uLineIndex = 0; uLineIndex < MixerLine.cConnections; uLineIndex++)
{
memset( &Line, 0, sizeof(MIXERLINE) );
......@@ -631,7 +759,7 @@ static int winsnddscard_set_control(MSSndCard *card, MSSndCardControlElem e, int
/* ms_message("LineID: %d\n", MixerLine.dwLineID); */
/* ms_message("ComponentType: %d\n", MixerLine.dwComponentType); */
if (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE == Line.dwComponentType)
if (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE == Line.dwComponentType)
{
/* unmute */
/* Find a mute control, if any, of the microphone line */
......@@ -679,11 +807,6 @@ static int winsnddscard_set_control(MSSndCard *card, MSSndCardControlElem e, int
case MS_SND_CARD_MASTER_MUTE:
case MS_SND_CARD_PLAYBACK_MUTE:
{
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
MIXERCONTROLDETAILS mcd = {0};
MIXERCONTROLDETAILS_BOOLEAN bMute;
bMute.fValue = (val>0);
mr = mixerGetID( (HMIXEROBJ)waveout_devid, &uMixerID, MIXER_OBJECTF_WAVEOUT );
......@@ -775,7 +898,7 @@ MSSndCardDesc winsndds_card_desc={
winsnddscard_set_level,
winsnddscard_get_level,
winsnddscard_set_source,
NULL,
winsnddscard_set_control,
NULL,
ms_winsndds_read_new,
ms_winsndds_write_new,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment