wineoss multiple mixers patch
Robert Reif
reif at earthlink.net
Sun Aug 22 07:59:37 CDT 2004
Adds support for multiple mixers.
Gets mixer name from OSS.
More tracing.
-------------- next part --------------
Index: dlls/winmm/wineoss/mixer.c
===================================================================
RCS file: /home/wine/wine/dlls/winmm/wineoss/mixer.c,v
retrieving revision 1.25
diff -u -r1.25 mixer.c
--- dlls/winmm/wineoss/mixer.c 22 Aug 2004 02:02:27 -0000 1.25
+++ dlls/winmm/wineoss/mixer.c 22 Aug 2004 12:55:20 -0000
@@ -83,7 +83,8 @@
struct mixer
{
- const char* name;
+ char* name;
+ char* dev_name;
int volume[SOUND_MIXER_NRDEVICES];
int devMask;
int stereoMask;
@@ -131,7 +132,6 @@
static char str[64];
#define IOCTL_TO_STR(x) case x: return #x;
switch (command) {
- IOCTL_TO_STR(SOUND_MIXER_NRDEVICES);
IOCTL_TO_STR(SOUND_MIXER_VOLUME);
IOCTL_TO_STR(SOUND_MIXER_BASS);
IOCTL_TO_STR(SOUND_MIXER_TREBLE);
@@ -157,8 +157,6 @@
IOCTL_TO_STR(SOUND_MIXER_VIDEO);
IOCTL_TO_STR(SOUND_MIXER_RADIO);
IOCTL_TO_STR(SOUND_MIXER_MONITOR);
- IOCTL_TO_STR(SOUND_ONOFF_MIN);
- IOCTL_TO_STR(SOUND_ONOFF_MAX);
}
#undef IOCTL_TO_STR
sprintf(str, "UNKNOWN(%08x)", command);
@@ -207,23 +205,72 @@
return str;
}
+static const char * getComponentType(DWORD dwComponentType)
+{
+ static char str[64];
+#define TYPE_TO_STR(x) case x: return #x;
+ switch (dwComponentType) {
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_UNDEFINED);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_DIGITAL);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_LINE);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_MONITOR);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_HEADPHONES);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_TELEPHONE);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_WAVEIN);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_VOICEIN);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_DIGITAL);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_LINE);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY);
+ TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_ANALOG);
+ }
+#undef TYPE_TO_STR
+ sprintf(str, "UNKNOWN(%08lx)", dwComponentType);
+ return str;
+}
+
+static const char * getTargetType(DWORD dwType)
+{
+ static char str[64];
+#define TYPE_TO_STR(x) case x: return #x;
+ switch (dwType) {
+ TYPE_TO_STR(MIXERLINE_TARGETTYPE_UNDEFINED);
+ TYPE_TO_STR(MIXERLINE_TARGETTYPE_WAVEOUT);
+ TYPE_TO_STR(MIXERLINE_TARGETTYPE_WAVEIN);
+ TYPE_TO_STR(MIXERLINE_TARGETTYPE_MIDIOUT);
+ TYPE_TO_STR(MIXERLINE_TARGETTYPE_MIDIIN);
+ TYPE_TO_STR(MIXERLINE_TARGETTYPE_AUX);
+ }
+#undef TYPE_TO_STR
+ sprintf(str, "UNKNOWN(%08lx)", dwType);
+ return str;
+}
+
/**************************************************************************
* MIX_FillLineControls [internal]
*/
static void MIX_FillLineControls(struct mixer* mix, int c, DWORD lineID,
- DWORD dwType)
+ DWORD dwControlType)
{
struct mixerCtrl* mc = &mix->ctrl[c];
int j;
- TRACE("(%p, %d, %08lx, %s)\n", mix, c, lineID, getControlType(dwType));
+ TRACE("(%p, %d, %08lx, %s)\n", mix, c, lineID,
+ getControlType(dwControlType));
mc->dwLineID = lineID;
mc->ctrl.cbStruct = sizeof(MIXERCONTROLA);
mc->ctrl.dwControlID = c + 1;
- mc->ctrl.dwControlType = dwType;
+ mc->ctrl.dwControlType = dwControlType;
- switch (dwType)
+ switch (dwControlType)
{
case MIXERCONTROL_CONTROLTYPE_VOLUME:
mc->ctrl.fdwControl = 0;
@@ -266,9 +313,9 @@
break;
default:
- FIXME("Internal error: unknown type: %08lx\n", dwType);
+ FIXME("Internal error: unknown type: %08lx\n", dwControlType);
}
- TRACE("ctrl[%2d]: typ=%08lx lin=%08lx\n", c + 1, dwType, lineID);
+ TRACE("ctrl[%2d]: typ=%08lx lin=%08lx\n", c + 1, dwControlType, lineID);
}
/******************************************************************
@@ -280,7 +327,7 @@
{
TRACE("(%04x)\n", wDevID);
- if (wDevID >= MIX_NumMixers || MIX_Mixers[wDevID].name == NULL)
+ if (wDevID >= MIX_NumMixers || MIX_Mixers[wDevID].dev_name == NULL)
return NULL;
return &MIX_Mixers[wDevID];
@@ -302,7 +349,7 @@
* EPP if (lpMod == NULL) return MMSYSERR_INVALPARAM;
* anyway, it seems that WINMM/MMSYSTEM doesn't always open the mixer
* device before sending messages to it... it seems to be linked to all
- * the equivalent of mixer identification
+ * the equivalent of mixer identification
* (with a reference to a wave, midi.. handle
*/
if (!(mix = MIX_Get(wDevID))) {
@@ -310,10 +357,10 @@
return MMSYSERR_BADDEVICEID;
}
- if ((mixer = open(mix->name, O_RDWR)) < 0)
+ if ((mixer = open(mix->dev_name, O_RDWR)) < 0)
{
ERR("open(%s, O_RDWR) failed (%s)\n",
- mix->name, strerror(errno));
+ mix->dev_name, strerror(errno));
if (errno == ENODEV || errno == ENXIO)
{
@@ -327,7 +374,7 @@
if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &mix->devMask) == -1)
{
ERR("ioctl(%s, SOUND_MIXER_DEVMASK) failed (%s)\n",
- mix->name, strerror(errno));
+ mix->dev_name, strerror(errno));
ret = MMSYSERR_ERROR;
goto error;
}
@@ -343,7 +390,7 @@
if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &mix->stereoMask) == -1)
{
ERR("ioctl(%s, SOUND_MIXER_STEREODEVS) failed (%s)\n",
- mix->name, strerror(errno));
+ mix->dev_name, strerror(errno));
ret = MMSYSERR_ERROR;
goto error;
}
@@ -352,7 +399,7 @@
if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &mix->recMask) == -1)
{
ERR("ioctl(%s, SOUND_MIXER_RECMASK) failed (%s)\n",
- mix->name, strerror(errno));
+ mix->dev_name, strerror(errno));
ret = MMSYSERR_ERROR;
goto error;
}
@@ -367,7 +414,7 @@
if (ioctl(mixer, SOUND_MIXER_READ_CAPS, &caps) == -1)
{
ERR("ioctl(%s, SOUND_MIXER_READ_CAPS) failed (%s)\n",
- mix->name, strerror(errno));
+ mix->dev_name, strerror(errno));
ret = MMSYSERR_ERROR;
goto error;
}
@@ -443,7 +490,7 @@
TRACE("(%p, %s, %p\n", mix, getIoctlCommand(chn), val);
- if ((mixer = open(mix->name, O_RDWR)) < 0) {
+ if ((mixer = open(mix->dev_name, O_RDWR)) < 0) {
/* FIXME: ENXIO => no mixer installed */
WARN("mixer device not available !\n");
} else {
@@ -452,7 +499,7 @@
ret = TRUE;
} else {
ERR("ioctl(%s, MIXER_READ(%s)) failed (%s)\n",
- mix->name, getIoctlCommand(chn), strerror(errno));
+ mix->dev_name, getIoctlCommand(chn), strerror(errno));
}
close(mixer);
}
@@ -469,7 +516,7 @@
TRACE("(%p, %s, %x)\n", mix, getIoctlCommand(chn), val);
- if ((mixer = open(mix->name, O_RDWR)) < 0) {
+ if ((mixer = open(mix->dev_name, O_RDWR)) < 0) {
/* FIXME: ENXIO => no mixer installed */
WARN("mixer device not available !\n");
} else {
@@ -478,7 +525,7 @@
ret = TRUE;
} else {
ERR("ioctl(%s, MIXER_WRITE(%s)) failed (%s)\n",
- mix->name, getIoctlCommand(chn), strerror(errno));
+ mix->dev_name, getIoctlCommand(chn), strerror(errno));
}
close(mixer);
}
@@ -497,12 +544,12 @@
TRACE("(%p, %p)\n", mix, mask);
- if ((mixer = open(mix->name, O_RDWR)) >= 0) {
+ if ((mixer = open(mix->dev_name, O_RDWR)) >= 0) {
if (ioctl(mixer, SOUND_MIXER_READ_RECSRC, &mask) >= 0) {
ret = TRUE;
} else {
ERR("ioctl(%s, SOUND_MIXER_READ_RECSRC) failed (%s)\n",
- mix->name, strerror(errno));
+ mix->dev_name, strerror(errno));
}
close(mixer);
}
@@ -521,12 +568,12 @@
TRACE("(%p, %08x)\n", mix, mask);
- if ((mixer = open(mix->name, O_RDWR)) >= 0) {
+ if ((mixer = open(mix->dev_name, O_RDWR)) >= 0) {
if (ioctl(mixer, SOUND_MIXER_WRITE_RECSRC, &mask) >= 0) {
ret = TRUE;
} else {
ERR("ioctl(%s, SOUND_MIXER_WRITE_RECSRC) failed (%s)\n",
- mix->name, strerror(errno));
+ mix->dev_name, strerror(errno));
}
close(mixer);
}
@@ -556,7 +603,10 @@
capsA.wMid = WINE_MIXER_MANUF_ID;
capsA.wPid = WINE_MIXER_PRODUCT_ID;
capsA.vDriverVersion = WINE_MIXER_VERSION;
- strcpy(capsA.szPname, WINE_MIXER_NAME);
+ if (mix->name)
+ strcpy(capsA.szPname, mix->name);
+ else
+ strcpy(capsA.szPname, WINE_MIXER_NAME);
capsA.cDestinations = 2; /* speakers & record */
capsA.fdwSupport = 0; /* No bits defined yet */
@@ -689,7 +739,7 @@
TRACE("(%08lx)\n",lineID);
return ((HIWORD(lineID) < SOUND_MIXER_NRDEVICES && LOWORD(lineID) < 2) ||
- (HIWORD(lineID) == LINEID_DST &&
+ (HIWORD(lineID) == LINEID_DST &&
LOWORD(lineID) < SOUND_MIXER_NRDEVICES));
}
@@ -705,8 +755,14 @@
TRACE("(%04X, %p, %lu);\n", wDevID, lpMl, fdwInfo);
- if (lpMl == NULL || lpMl->cbStruct != sizeof(*lpMl)) {
- WARN("invalid parameter\n");
+ if (lpMl == NULL) {
+ WARN("invalid parameter: lpMl = NULL\n");
+ return MMSYSERR_INVALPARAM;
+ }
+
+ if (lpMl->cbStruct != sizeof(*lpMl)) {
+ WARN("invalid parameter: lpMl->cbStruct = %ld != %d\n",
+ lpMl->cbStruct, sizeof(*lpMl));
return MMSYSERR_INVALPARAM;
}
@@ -726,7 +782,8 @@
case MIXER_GETLINEINFOF_DESTINATION:
TRACE("MIXER_GETLINEINFOF_DESTINATION (%08lx)\n", lpMl->dwDestination);
if (lpMl->dwDestination >= 2) {
- WARN("invalid parameter\n");
+ WARN("invalid parameter: lpMl->dwDestination = %ld >= 2\n",
+ lpMl->dwDestination);
return MMSYSERR_INVALPARAM;
}
ret = MIX_GetLineInfoDst(mix, lpMl, lpMl->dwDestination);
@@ -780,8 +837,8 @@
}
break;
case MIXER_GETLINEINFOF_COMPONENTTYPE:
- TRACE("MIXER_GETLINEINFOF_COMPONENTTYPE (%08lx)\n",
- lpMl->dwComponentType);
+ TRACE("MIXER_GETLINEINFOF_COMPONENTTYPE (%s)\n",
+ getComponentType(lpMl->dwComponentType));
switch (lpMl->dwComponentType)
{
case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS:
@@ -809,12 +866,27 @@
ret = MIX_GetLineInfoSrc(mix, lpMl, SOUND_MIXER_IMIX, 1);
break;
default:
- FIXME("Unhandled component type (%08lx)\n", lpMl->dwComponentType);
+ FIXME("Unhandled component type (%s)\n",
+ getComponentType(lpMl->dwComponentType));
return MMSYSERR_INVALPARAM;
}
break;
case MIXER_GETLINEINFOF_TARGETTYPE:
FIXME("MIXER_GETLINEINFOF_TARGETTYPE not implemented yet.\n");
+ TRACE("MIXER_GETLINEINFOF_TARGETTYPE (%s)\n",
+ getTargetType(lpMl->Target.dwType));
+ switch (lpMl->Target.dwType) {
+ case MIXERLINE_TARGETTYPE_UNDEFINED:
+ case MIXERLINE_TARGETTYPE_WAVEOUT:
+ case MIXERLINE_TARGETTYPE_WAVEIN:
+ case MIXERLINE_TARGETTYPE_MIDIOUT:
+ case MIXERLINE_TARGETTYPE_MIDIIN:
+ case MIXERLINE_TARGETTYPE_AUX:
+ default:
+ FIXME("Unhandled target type (%s)\n",
+ getTargetType(lpMl->Target.dwType));
+ return MMSYSERR_INVALPARAM;
+ }
break;
default:
WARN("Unknown flag (%08lx)\n", fdwInfo & MIXER_GETLINEINFOF_QUERYMASK);
@@ -826,7 +898,10 @@
lpMl->Target.wMid = WINE_MIXER_MANUF_ID;
lpMl->Target.wPid = WINE_MIXER_PRODUCT_ID;
lpMl->Target.vDriverVersion = WINE_MIXER_VERSION;
- strcpy(lpMl->Target.szPname, WINE_MIXER_NAME);
+ if (mix->name)
+ strcpy(lpMl->Target.szPname, mix->name);
+ else
+ strcpy(lpMl->Target.szPname, WINE_MIXER_NAME);
return ret;
}
@@ -858,9 +933,15 @@
return MMSYSERR_INVALPARAM;
}
- if (lpMlc->cbStruct < sizeof(*lpMlc) ||
- lpMlc->cbmxctrl < sizeof(MIXERCONTROLA)) {
- WARN("invalid parameter: lpMlc\n");
+ if (lpMlc->cbStruct < sizeof(*lpMlc)) {
+ WARN("invalid parameter: lpMlc->cbStruct = %ld < %d\n",
+ lpMlc->cbStruct, sizeof(*lpMlc));
+ return MMSYSERR_INVALPARAM;
+ }
+
+ if (lpMlc->cbmxctrl < sizeof(MIXERCONTROLA)) {
+ WARN("invalid parameter: lpMlc->cbmxctrl = %ld < %d\n",
+ lpMlc->cbmxctrl, sizeof(MIXERCONTROLA));
return MMSYSERR_INVALPARAM;
}
@@ -986,7 +1067,7 @@
LPMIXERCONTROLDETAILS_UNSIGNED mcdu;
int val;
- if (lpmcd->cbDetails !=
+ if (lpmcd->cbDetails !=
sizeof(MIXERCONTROLDETAILS_UNSIGNED)) {
WARN("invalid parameter: cbDetails != %d\n",
sizeof(MIXERCONTROLDETAILS_UNSIGNED));
@@ -1009,16 +1090,17 @@
switch (lpmcd->cChannels)
{
case 1:
- TRACE("mono\n");
/* mono... so R = L */
mcdu->dwValue = (LOBYTE(LOWORD(val)) * 65536L) / 100;
+ TRACE("Reading RL = %ld\n", mcdu->dwValue);
break;
case 2:
- TRACE("stereo\n");
/* stereo, left is paDetails[0] */
mcdu->dwValue = (LOBYTE(LOWORD(val)) * 65536L) / 100;
+ TRACE("Reading L = %ld\n", mcdu->dwValue);
mcdu++;
mcdu->dwValue = (HIBYTE(LOWORD(val)) * 65536L) / 100;
+ TRACE("Reading R = %ld\n", mcdu->dwValue);
break;
default:
WARN("Unsupported cChannels (%ld)\n", lpmcd->cChannels);
@@ -1032,7 +1114,7 @@
{
LPMIXERCONTROLDETAILS_BOOLEAN mcdb;
- if (lpmcd->cbDetails !=
+ if (lpmcd->cbDetails !=
sizeof(MIXERCONTROLDETAILS_BOOLEAN)) {
WARN("invalid parameter: cbDetails != %d\n",
sizeof(MIXERCONTROLDETAILS_BOOLEAN));
@@ -1054,7 +1136,7 @@
{
unsigned mask;
- if (lpmcd->cbDetails !=
+ if (lpmcd->cbDetails !=
sizeof(MIXERCONTROLDETAILS_BOOLEAN)) {
WARN("invalid parameter: cbDetails != %d\n",
sizeof(MIXERCONTROLDETAILS_BOOLEAN));
@@ -1185,7 +1267,7 @@
{
LPMIXERCONTROLDETAILS_UNSIGNED mcdu;
- if (lpmcd->cbDetails !=
+ if (lpmcd->cbDetails !=
sizeof(MIXERCONTROLDETAILS_UNSIGNED)) {
WARN("invalid parameter: cbDetails != %d\n",
sizeof(MIXERCONTROLDETAILS_UNSIGNED));
@@ -1237,7 +1319,7 @@
{
LPMIXERCONTROLDETAILS_BOOLEAN mcdb;
- if (lpmcd->cbDetails !=
+ if (lpmcd->cbDetails !=
sizeof(MIXERCONTROLDETAILS_BOOLEAN)) {
WARN("invalid parameter: cbDetails != %d\n",
sizeof(MIXERCONTROLDETAILS_BOOLEAN));
@@ -1281,7 +1363,7 @@
unsigned mask;
int i, j;
- if (lpmcd->cbDetails !=
+ if (lpmcd->cbDetails !=
sizeof(MIXERCONTROLDETAILS_BOOLEAN)) {
WARN("invalid parameter: cbDetails != %d\n",
sizeof(MIXERCONTROLDETAILS_BOOLEAN));
@@ -1333,27 +1415,69 @@
*/
static DWORD MIX_Init(void)
{
- int mixer;
+ int i, mixer;
TRACE("()\n");
-#define MIXER_DEV "/dev/mixer"
- if ((mixer = open(MIXER_DEV, O_RDWR)) < 0)
- {
- if (errno == ENODEV || errno == ENXIO)
- {
- /* no driver present */
- WARN("no driver\n");
- return MMSYSERR_NODRIVER;
- }
- MIX_NumMixers = 0;
- return MMSYSERR_ERROR;
+ MIX_NumMixers = 0;
+
+ for (i = 0; i < MAX_MIXERDRV; i++) {
+ char name[32];
+
+ if (i == 0)
+ sprintf(name, "/dev/mixer");
+ else
+ sprintf(name, "/dev/mixer%d", i);
+
+ if ((mixer = open(name, O_RDWR)) >= 0) {
+#ifdef SOUND_MIXER_INFO
+ mixer_info info;
+ if (ioctl(mixer, SOUND_MIXER_INFO, &info) >= 0) {
+ MIX_Mixers[i].name = HeapAlloc(GetProcessHeap(),0,strlen(info.name) + 1);
+ strncpy(MIX_Mixers[i].name, info.name, sizeof(info.name));
+ } else {
+ /* FreeBSD up to at least 5.2 provides this ioctl, but does not
+ * implement it properly, and there are probably similar issues
+ * on other platforms, so we warn but try to go ahead.
+ */
+ WARN("%s: cannot read SOUND_MIXER_INFO!\n", name);
+ }
+#endif
+ close(mixer);
+
+ MIX_NumMixers++;
+ MIX_Mixers[i].dev_name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
+ strcpy(MIX_Mixers[i].dev_name, name);
+ MIX_Open(i, NULL, 0); /* FIXME */
+ } else {
+ WARN("couldn't open %s\n", name);
+ }
}
- close(mixer);
- MIX_NumMixers = 1;
- MIX_Mixers[0].name = MIXER_DEV;
- MIX_Open(0, NULL, 0); /* FIXME */
-#undef MIXER_DEV
+
+ if (MIX_NumMixers == 0) {
+ WARN("no driver\n");
+ return MMSYSERR_NODRIVER;
+ }
+
+ return MMSYSERR_NOERROR;
+}
+
+/**************************************************************************
+ * MIX_Exit [internal]
+ */
+static DWORD MIX_Exit(void)
+{
+ int i;
+
+ TRACE("()\n");
+
+ for (i = 0; i < MIX_NumMixers; i++) {
+ if (MIX_Mixers[i].name)
+ HeapFree(GetProcessHeap(),0,MIX_Mixers[i].name);
+ if (MIX_Mixers[i].dev_name)
+ HeapFree(GetProcessHeap(),0,MIX_Mixers[i].dev_name);
+ }
+
return MMSYSERR_NOERROR;
}
@@ -1384,6 +1508,7 @@
case DRVM_INIT:
return MIX_Init();
case DRVM_EXIT:
+ return MIX_Exit();
case DRVM_ENABLE:
case DRVM_DISABLE:
/* FIXME: Pretend this is supported */
More information about the wine-patches
mailing list