/* * Sample MIXER Wine Driver for Linux * * Copyright 1997 Marcus Meissner */ #include #include #include #include #include "wintypes.h" #include "user.h" #include "driver.h" #include "multimedia.h" #include "debug.h" #define MIXER_DEV "/dev/mixer" /************************************************************************** * MIX_GetDevCaps [internal] */ static DWORD MIX_GetDevCaps(WORD wDevID, LPMIXERCAPS16 lpCaps, DWORD dwSize) { #ifdef HAVE_OSS int mixer,mask; TRACE(mmaux, "(%04X, %p, %lu);\n", wDevID, lpCaps, dwSize); if (lpCaps == NULL) return MMSYSERR_INVALPARAM; if ((mixer = open(MIXER_DEV, O_RDWR)) < 0) { WARN(mmaux, "mixer device not available !\n"); return MMSYSERR_NOTENABLED; } lpCaps->wMid = 0xAA; lpCaps->wPid = 0x55; lpCaps->vDriverVersion = 0x0100; strcpy(lpCaps->szPname, "WINE Generic Mixer"); if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &mask) == -1) { close(mixer); perror("ioctl mixer SOUND_MIXER_DEVMASK"); return MMSYSERR_NOTENABLED; } /* FIXME: can the Linux Mixer differ between multiple mixertargets? */ lpCaps->cDestinations = 1; lpCaps->fdwSupport = 0; /* No bits defined yet */ close(mixer); return MMSYSERR_NOERROR; #else return MMSYSERR_NOTENABLED; #endif } #ifdef HAVE_OSS static char *sdlabels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS; static char *sdnames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; static void MIX_GetLineInfoFromIndex(LPMIXERLINE16 lpml, int devmask, DWORD idx) { strcpy(lpml->szShortName, sdlabels[idx]); strcpy(lpml->szName, sdnames[idx]); lpml->dwLineID = idx; lpml->dwDestination = 0; /* index for speakers */ lpml->cConnections = 1; lpml->cControls = 1; switch (idx) { case SOUND_MIXER_SYNTH: lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER; lpml->fdwLine |= MIXERLINE_LINEF_SOURCE; break; case SOUND_MIXER_CD: lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC; lpml->fdwLine |= MIXERLINE_LINEF_SOURCE; break; case SOUND_MIXER_LINE: lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE; lpml->fdwLine |= MIXERLINE_LINEF_SOURCE; break; case SOUND_MIXER_MIC: lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE; lpml->fdwLine |= MIXERLINE_LINEF_SOURCE; break; case SOUND_MIXER_PCM: lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT; lpml->fdwLine |= MIXERLINE_LINEF_SOURCE; break; default: ERR(mmaux, "Index %ld not handled.\n", idx); break; } } #endif /************************************************************************** * MIX_GetLineInfo [internal] */ static DWORD MIX_GetLineInfo(WORD wDevID, LPMIXERLINE16 lpml, DWORD fdwInfo) { #ifdef HAVE_OSS int mixer, i, j, devmask, recsrc, recmask; DWORD ret = MMSYSERR_NOERROR; TRACE(mmaux, "(%04X, %p, %lu);\n", wDevID, lpml, fdwInfo); if (lpml == NULL || lpml->cbStruct != sizeof(*lpml)) return MMSYSERR_INVALPARAM; if ((mixer = open(MIXER_DEV, O_RDWR)) < 0) return MMSYSERR_NOTENABLED; if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { close(mixer); perror("ioctl mixer SOUND_MIXER_DEVMASK"); return MMSYSERR_NOTENABLED; } if (ioctl(mixer, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) { close(mixer); perror("ioctl mixer SOUND_MIXER_RECSRC"); return MMSYSERR_NOTENABLED; } if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &recmask) == -1) { close(mixer); perror("ioctl mixer SOUND_MIXER_RECMASK"); return MMSYSERR_NOTENABLED; } /* FIXME: set all the variables correctly... the lines below * are very wrong... */ lpml->fdwLine = MIXERLINE_LINEF_ACTIVE; lpml->cChannels = 2; switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) { case MIXER_GETLINEINFOF_DESTINATION: /* FIXME: Linux doesn't seem to support multiple outputs? * So we have only one outputtype, Speaker. */ lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; /* we have all connections found in the devmask */ lpml->cConnections = 0; for (j=0;j<31;j++) if (devmask & (1<cConnections++; break; case MIXER_GETLINEINFOF_SOURCE: for (i = j = 0; j < 31; j++) { if (devmask & (1 << j)) { if (lpml->dwSource == i) break; i++; } } MIX_GetLineInfoFromIndex(lpml, devmask, i); break; case MIXER_GETLINEINFOF_LINEID: MIX_GetLineInfoFromIndex(lpml, devmask, lpml->dwLineID); break; case MIXER_GETLINEINFOF_COMPONENTTYPE: TRACE(mmaux, "Getting component type (%08lx)\n", lpml->dwComponentType); switch (lpml->dwComponentType) { case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS: i = -1; break; case MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER: i = SOUND_MIXER_SYNTH; break; case MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC: i = SOUND_MIXER_CD; break; case MIXERLINE_COMPONENTTYPE_SRC_LINE: i = SOUND_MIXER_LINE; break; case MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE: i = SOUND_MIXER_MIC; break; case MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT: i = SOUND_MIXER_PCM; break; default: FIXME(mmaux, "Unhandled component type (%08lx)\n", lpml->dwComponentType); return MMSYSERR_INVALPARAM; } if (i != -1 && (devmask & (1 << i))) { strcpy(lpml->szShortName, sdlabels[i]); strcpy(lpml->szName, sdnames[i]); lpml->dwLineID = i; lpml->fdwLine = MIXERLINE_LINEF_SOURCE; } else { lpml->cConnections = 0; for (j=0;j<31;j++) if (devmask & (1<cConnections++; lpml->dwLineID = 32; } break; case MIXER_GETLINEINFOF_TARGETTYPE: FIXME(mmaux, "_TARGETTYPE not implemented yet.\n"); break; } lpml->Target.dwType = MIXERLINE_TARGETTYPE_AUX; close(mixer); return ret; #else return MMSYSERR_NOTENABLED; #endif } /************************************************************************** * MIX_GetLineInfo [internal] */ static DWORD MIX_Open(WORD wDevID, LPMIXEROPENDESC lpmod, DWORD flags) { #ifdef HAVE_OSS TRACE(mmaux, "(%04X, %p, %lu);\n", wDevID,lpmod,flags); if (lpmod == NULL) return MMSYSERR_INVALPARAM; /* hmm. We don't keep the mixer device open. So just pretend it works */ return MMSYSERR_NOERROR; #else return MMSYSERR_NOTENABLED; #endif } /************************************************************************** * mixMessage [sample driver] */ DWORD WINAPI mixMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { TRACE(mmaux, "(%04X, %04X, %08lX, %08lX, %08lX);\n", wDevID, wMsg, dwUser, dwParam1, dwParam2); switch(wMsg) { case MXDM_GETDEVCAPS: return MIX_GetDevCaps(wDevID, (LPMIXERCAPS16)dwParam1, dwParam2); case MXDM_GETLINEINFO: return MIX_GetLineInfo(wDevID, (LPMIXERLINE16)dwParam1, dwParam2); case MXDM_GETNUMDEVS: TRACE(mmaux, "return 1;\n"); return 1; case MXDM_OPEN: return MIX_Open(wDevID, (LPMIXEROPENDESC)dwParam1, dwParam2); case MXDM_CLOSE: return MMSYSERR_NOERROR; default: WARN(mmaux, "unknown message %d!\n", wMsg); } return MMSYSERR_NOTSUPPORTED; }