- got rid of all the internal MM tweaks to load builtin MCI

drivers. They are all seen as drivers, loaded as DLLs and standard
  module loadorder is used to know which type to use (builtin vs
  native).
- first full working implementation of mmThread??? functions (to
  support gracefully native MCI drivers).
- support of mmShowMMCPLPropertySheet.
- fix of some heap validate bugs (thanks to Ulrich for reporting them).
This commit is contained in:
Eric Pouech 1999-05-02 10:21:49 +00:00 committed by Alexandre Julliard
parent 4f6d7f38dc
commit 281c927317
24 changed files with 1149 additions and 743 deletions

View file

@ -15,6 +15,7 @@ services.
1. Lowlevel layers
Following lowlevel layers are implemented:
1.1 (Waveform) Audio
The API consists of the waveIn*/waveOut* functions found in
@ -29,18 +30,18 @@ services.
The implementation contains all features commonly used, but has several
problems. For instance:
Writes and reads are not done asynchronously as they are supposed to
be done. This breaks some programs (soundrec.exe from the Windows applets),
but doesn't worry other programs. Some callbacks are probably done
incorrectly (there are reports of some broken multimedia applications,
but I haven't found one yet.)
Writes are not done asynchronously as they are supposed to be done.
This breaks some programs (soundrec.exe from the Windows applets),
but doesn't worry other programs.
TODO:
- add asynchronous writes and reads (must use threads)
- check the callback functions
- add asynchronous writes (must use threads)
- verify all functions for correctness
- add drivers for other soundsystems (Sun Audio, remote audio systems
(using X extensions, ...), ALSA
- WaveHdr must be sent though mmsystem.c to get the linear address
set correctly. An application calling directly (wod|wid)Message
will fail
1.2 Mixer
@ -77,9 +78,10 @@ services.
use existing instrument definition (from playmidi or kmid)
with a .winerc option
- have a look at OPL/3 ?
- a hack is used in mmsystem.c (setting reserved to the 32 bit linear
address of the block whatever the call is made from 16 or 32 bits
code...). this should be made in midi.c I think
- MidiHdr must be sent though mmsystem.c to get the linear address
set correctly. An application calling directly (wod|wid)Message
will fail
- implement asynchronous playback of MidiHdr
1.4 Timers
@ -92,7 +94,7 @@ services.
and 'Pinball! SpaceCadet' at least start up.
TODO:
- Implemented asynchronous timers (using a thread probably)
- Implemented asynchronous timers (using the service thread)
1.5 MMIO
@ -139,19 +141,18 @@ services.
The implementation is not complete.
There is a first shot at using native (MS provided) MCI
drivers. For this to work, there are two .winerc options to be
used:
- key 'mci' in [option] section
MCI drivers are seen as regular WINE modules, and can be loaded
(with a correct loadorder between builtin, native, elfdll, so), as
any other DLL. Please note, that MCI drivers module names must
bear the .drv extension to be correctly understood.
The list of available MCI drivers is obtained as follows:
1/ key 'mci' in [option] section from .winerc (or wineconf)
mci=CDAUDIO:SEQUENCER
gives the list of MCI drivers (names, in uppercase only) to
be used in WINE. This list, when defined, supercedes the mci
be used in WINE.
2/ This list, when defined, supercedes the mci
key in c:\windows\system.ini
- key 'mciExternal' in [option] section
mciExternal=CDAUDIO
gives the list of MCI drivers to be loaded from Windows
installation. Since, drivers are DLLs, drivers are searched
(and loaded) as DLLs are.
TODO:
- support windows MCI drivers (should be possible for they usually
@ -164,6 +165,7 @@ services.
- implement other stuff as yet unknown
- in mciString(), make use of hiword from mciSendMessage
return value to convert value into string...
- move mci drivers as regular DLLs (loading in wine, elfglue...)
WINE implements several MCI midlevel drivers:
@ -193,7 +195,12 @@ services.
It uses the lowlevel audio API (although not abstracted correctly).
FIXME: The MCI_STATUS command is broken.
TODO: - check for correctness
TODO:
- check for correctness
- better use of asynchronous playback from low level
Native MCIWAVE has been working but is currently blocked by
scheduling issues.
2.3 MIDI/SEQUENCER
@ -205,6 +212,9 @@ services.
- implement it correctly
- finish asynchronous commands
Native MCIMIDI has been working but is currently blocked by
scheduling issues.
2.4 MCIANIM
The implementation consists of stubs and is in multimedia/mcianim.c.
@ -213,6 +223,14 @@ services.
- implement it, probably using xanim or something similair. Could
also be implemented by using the Windows MCI video drivers.
2.5 MCIAVI
The implementation consists of stubs and is in multimedia/mciavi.c.
TODO:
- implement it, probably using xanim or something similair. Could
also be implemented by using the Windows MCI video drivers.
3 High-level layers
The rest (basically the MMSYSTEM and WINMM DLLs entry points.
The rest (basically the MMSYSTEM and WINMM DLLs entry points).

View file

@ -1,5 +1,6 @@
name mmsystem
type win16
init MMSYSTEM_LibMain
#1 pascal MMSYSTEM_WEP(word word word ptr) MMSYSTEM_WEP
2 pascal SNDPLAYSOUND(ptr word) sndPlaySoundA
@ -147,7 +148,7 @@ type win16
1123 pascal mmThreadIsCurrent(word) mmThreadIsCurrent16
1124 pascal mmThreadIsValid(word) mmThreadIsValid16
1125 pascal mmThreadGetTask(word) mmThreadGetTask16
1150 pascal mmShowMMCPLPropertySheet(word word word word word word word) mmShowMMCPLPropertySheet16
1150 pascal mmShowMMCPLPropertySheet(word str str str) mmShowMMCPLPropertySheet16
1210 pascal mmioOpen(str ptr long) mmioOpen16
1211 pascal mmioClose(word word) mmioClose16
@ -175,4 +176,4 @@ type win16
#2006 stub WINMMSL_THUNKDATA16
# this is a wine only exported function. Is there another way to do it ?
2047 pascal WINE_mmThreadingEntryPoint(long) WINE_mmThreadingEntryPoint
2047 pascal WINE_mmThreadEntryPoint(long) WINE_mmThreadEntryPoint

View file

@ -2,9 +2,10 @@
/*****************************************************************************
* Copyright 1998, Luiz Otavio L. Zorzella
* 1999, Eric Pouech
*
* File: multimedia.h
* Purpose: multimedia declarations
* Purpose: multimedia declarations (internal to multimedia DLLs)
*
*****************************************************************************
*/
@ -44,7 +45,7 @@
#endif
typedef struct {
HDRVR16 hDrv;
HDRVR hDrv;
DRIVERPROC16 driverProc;
MCI_OPEN_DRIVER_PARMS16 modp;
MCI_OPEN_PARMS16 mop;
@ -62,41 +63,50 @@ extern WINE_MCIDRIVER mciDrv[MAXMCIDRIVERS];
typedef struct {
DWORD dwSignature; /* 00 "BSIL" when ok, 0xDEADDEAD when being deleted */
DWORD dwCounter; /* 04 */
DWORD dwCounter; /* 04 > 1 when in mmThread functions */
HANDLE hThread; /* 08 hThread */
DWORD dwThreadId; /* 0C */
FARPROC16 fpThread; /* 10 segmented address of thread proc */
DWORD dwThreadPmt; /* 14 parameter to be called upon thread creation */
DWORD dwUnknown3; /* 18 increment interlocked ? */
DWORD hEvent; /* 1C event */
DWORD dwUnknown5; /* 20 */
DWORD dwStatus; /* 24 0, 10, 20, 30 */
DWORD dwThreadID; /* 0C */
FARPROC16 fpThread; /* 10 address of thread proc (segptr or lin depending on dwFlags) */
DWORD dwThreadPmt; /* 14 parameter to be passed upon thread creation to fpThread */
DWORD dwSignalCount; /* 18 counter used for signaling */
HANDLE hEvent; /* 1C event */
HANDLE hVxD; /* 20 return from OpenVxDHandle */
DWORD dwStatus; /* 24 0x00, 0x10, 0x20, 0x30 */
DWORD dwFlags; /* 28 dwFlags upon creation */
HANDLE16 hTask; /* 2C handle to created task */
} WINE_MMTHREAD;
#define MCI_GetDrv(wDevID) (&mciDrv[MCI_DevIDToIndex(wDevID)])
#define MCI_GetOpenDrv(wDevID) (&(MCI_GetDrv(wDevID)->mop))
typedef enum {
MCI_MAP_NOMEM, /* ko, memory problem */
MCI_MAP_MSGERROR, /* ko, unknown message */
MCI_MAP_OK, /* ok, no memory allocated. to be sent to 16 bit proc. */
MCI_MAP_OKMEM, /* ok, some memory allocated, need to call MCI_UnMapMsg32ATo16. to be sent to 16 bit proc. */
MCI_MAP_PASS /* ok, no memory allocated. to be sent to 32 bit proc */
} MCI_MapType;
/* function prototypes */
extern BOOL MULTIMEDIA_Init(void);
#define MCI_GetDrv(wDevID) (&mciDrv[MCI_DevIDToIndex(wDevID)])
#define MCI_GetOpenDrv(wDevID) (&(MCI_GetDrv(wDevID)->mop))
extern int MCI_DevIDToIndex(UINT16 wDevID);
extern UINT16 MCI_FirstDevID(void);
extern UINT16 MCI_NextDevID(UINT16 wDevID);
extern BOOL MCI_DevIDValid(UINT16 wDevID);
extern int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam);
extern int MCI_UnMapMsg16To32A(WORD uDevTyp, WORD wMsg, DWORD lParam);
extern MCI_MapType MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam);
extern MCI_MapType MCI_UnMapMsg16To32A(WORD uDevTyp, WORD wMsg, DWORD lParam);
extern DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms);
extern DWORD MCI_Close(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms);
extern DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSA lpParms);
typedef LONG (*MCIPROC16)(DWORD, HDRVR16, WORD, DWORD, DWORD);
typedef LONG (*MCIPROC)(DWORD, HDRVR16, DWORD, DWORD, DWORD);
typedef LONG (*MCIPROC)(DWORD, HDRVR, DWORD, DWORD, DWORD);
extern WORD MCI_GetDevTypeFromString(LPCSTR str);
extern LPCSTR MCI_GetStringFromDevType(WORD type);
extern WORD MCI_GetDevType(LPCSTR str);
extern DWORD MCI_WriteString(LPSTR lpDstStr, DWORD dstSize, LPCSTR lpSrcStr);
extern const char* MCI_CommandToString(UINT16 wMsg);
@ -106,28 +116,34 @@ extern LPSTR lpmciInstallNames;
extern UINT16 WINAPI MCI_DefYieldProc(UINT16 wDevID, DWORD data);
typedef struct {
WORD uDevType;
char* lpstrName;
MCIPROC lpfnProc;
} MCI_WineDesc;
extern MCI_WineDesc MCI_InternalDescriptors[];
extern LRESULT MCI_CleanUp(LRESULT dwRet, UINT wMsg, DWORD dwParam2, BOOL bIs32);
extern DWORD MCI_SendCommand(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2);
extern DWORD MCI_SendCommandFrom32(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2);
extern DWORD MCI_SendCommandFrom16(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2);
extern DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2, UINT size);
LONG MCIWAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
LONG MCIWAVE_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2);
LONG MCIMIDI_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
LONG MCIMIDI_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2);
LONG MCICDAUDIO_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
LONG MCICDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2);
LONG MCIANIM_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
LONG MCIANIM_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2);
LONG MCIAVI_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
LONG MCIAVI_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2);
HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt);
void WINAPI mmTaskBlock16(HINSTANCE16 hInst);
LRESULT WINAPI mmTaskSignal16(HTASK16 ht);
void WINAPI mmTaskYield16(void);
void WINAPI WINE_mmThreadEntryPoint(DWORD _pmt);
LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE lpHndl, DWORD dwPmt, DWORD dwFlags);
void WINAPI mmThreadSignal16(HANDLE16 hndl);
void WINAPI mmThreadBlock16(HANDLE16 hndl);
HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl);
BOOL16 WINAPI mmThreadIsValid16(HANDLE16 hndl);
BOOL16 WINAPI mmThreadIsCurrent16(HANDLE16 hndl);
#endif /* __WINE_MULTIMEDIA_H */

View file

@ -17,7 +17,6 @@
#include "main.h"
#include "menu.h"
#include "message.h"
#include "multimedia.h"
#include "dialog.h"
#include "drive.h"
#include "queue.h"
@ -239,9 +238,6 @@ BOOL WINAPI MAIN_UserInit(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserve
/* Initialize cursor/icons */
CURSORICON_Init();
/* Initialize multimedia */
if (!MULTIMEDIA_Init()) return FALSE;
/* Initialize message spying */
if (!SPY_Init()) return FALSE;

View file

@ -141,6 +141,9 @@ static DWORD WAVE_NotifyClient(UINT16 wDevID, WORD wMsg,
return MMSYSERR_NOERROR;
}
break;
default:
FIXME(wave, "Unknown CB message %u\n", wMsg);
break;
}
return 0;
}
@ -223,11 +226,13 @@ static BOOL wodPlayer_WriteFragments(WINE_WAVEOUT* wwo)
} else {
count = write(wwo->unixdev, lpData + wwo->dwOffCurrHdr, wwo->dwRemain);
TRACE(wave, "write(%p[%5lu], %5lu) => %d\n", lpData, wwo->dwOffCurrHdr, wwo->dwRemain, count);
wwo->dwOffCurrHdr += count;
if (count > 0) {
wwo->dwOffCurrHdr += wwo->dwRemain;
wwo->dwRemain = wwo->dwFragmentSize;
}
}
}
}
/**************************************************************************
* wodPlayer_WriteFragments [internal]

View file

@ -18,6 +18,7 @@
DECLARE_DEBUG_CHANNEL(mci)
DECLARE_DEBUG_CHANNEL(midi)
DECLARE_DEBUG_CHANNEL(mmsys)
#ifdef HAVE_OSS
@ -38,7 +39,7 @@ extern LPMIDIINCAPS16 midiInDevices [MAX_MIDIINDRV];
*
*/
#ifdef HAVE_OSS
int unixToWindowsDeviceType(int type)
static int unixToWindowsDeviceType(int type)
{
#if !defined(__NetBSD__) && !defined(__OpenBSD__)
/* MOD_MIDIPORT output port
@ -72,7 +73,7 @@ int unixToWindowsDeviceType(int type)
* Initializes the MIDI devices information variables
*
*/
BOOL MULTIMEDIA_MidiInit(void)
static BOOL MULTIMEDIA_MidiInit(void)
{
#if defined(HAVE_OSS) && !defined(__NetBSD__) && !defined(__OpenBSD__)
int i, status, numsynthdevs = 255, nummididevs = 255;
@ -256,10 +257,14 @@ BOOL MULTIMEDIA_MidiInit(void)
return TRUE;
}
BOOL MULTIMEDIA_MciInit(void)
/**************************************************************************
* MULTIMEDIA_MciInit [internal]
*
* Initializes the MCI internal variables.
*
*/static BOOL MULTIMEDIA_MciInit(void)
{
LPSTR ptr1, ptr2;
char buffer[1024];
mciInstalledCount = 0;
ptr1 = lpmciInstallNames = xmalloc(2048);
@ -286,25 +291,61 @@ BOOL MULTIMEDIA_MciInit(void)
}
mciInstalledListLen = ptr1 - lpmciInstallNames;
if (PROFILE_GetWineIniString("options", "mciExternal", "", buffer, sizeof(buffer)) > 0) {
int i;
return TRUE;
}
for (i = 0; MCI_InternalDescriptors[i].uDevType != 0xFFFF; i++) {
if (strstr(buffer, MCI_InternalDescriptors[i].lpstrName) != NULL) {
MCI_InternalDescriptors[i].uDevType = 0; /* disable slot */
HINSTANCE WINMM_hInstance = 0;
HINSTANCE MMSYSTEM_hInstance = 0;
static bInitDone = FALSE;
/**************************************************************************
* WINMM_LibMain [EntryPoint]
*
* WINMM DLL entry point
*
*/
BOOL WINAPI WINMM_LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
{
TRACE(mmsys, "0x%x 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
if (!bInitDone) {
if (MULTIMEDIA_MidiInit() && MULTIMEDIA_MciInit()) {
bInitDone = TRUE;
} else {
return FALSE;
}
}
WINMM_hInstance = hinstDLL;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
/**************************************************************************
* MULTIMEDIA_Init [internal]
*
* Initializes the multimedia information variables
*
*/
BOOL MULTIMEDIA_Init(void)
BOOL WINAPI MMSYSTEM_LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
{
return MULTIMEDIA_MidiInit() && MULTIMEDIA_MciInit();
TRACE(mmsys, "0x%x 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
if (!bInitDone) {
if (MULTIMEDIA_MidiInit() && MULTIMEDIA_MciInit()) {
bInitDone = TRUE;
} else {
return FALSE;
}
}
MMSYSTEM_hInstance = hinstDLL;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View file

@ -16,9 +16,9 @@
#include "mmsystem.h"
#include "multimedia.h"
#include "selectors.h"
#include "debug.h"
#include "digitalv.h"
#include "wine/winbase16.h"
#include "debug.h"
DEFAULT_DEBUG_CHANNEL(mci)
@ -28,6 +28,46 @@ int mciInstalledCount;
int mciInstalledListLen;
LPSTR lpmciInstallNames = NULL;
static struct MCI_StringType {
LPCSTR str;
UINT type;
} MCI_StringType_List[] = {
/* MCI types that are working */
{"CDAUDIO", MCI_DEVTYPE_CD_AUDIO},
{"WAVEAUDIO", MCI_DEVTYPE_WAVEFORM_AUDIO},
{"SEQUENCER", MCI_DEVTYPE_SEQUENCER},
/* MCI types that should be working */
{"ANIMATION1", MCI_DEVTYPE_ANIMATION},
{"MPEGVIDEO", MCI_DEVTYPE_DIGITAL_VIDEO},
{"AVIVIDEO", MCI_DEVTYPE_DIGITAL_VIDEO},
/* MCI types not likely to be supported */
{"VCR", MCI_DEVTYPE_VCR},
{"VIDEODISC", MCI_DEVTYPE_VIDEODISC},
{"OVERLAY", MCI_DEVTYPE_OVERLAY},
{"DAT", MCI_DEVTYPE_DAT},
{"SCANNER", MCI_DEVTYPE_SCANNER},
{NULL, 0}
};
WORD MCI_GetDevTypeFromString(LPCSTR str)
{
struct MCI_StringType* mst = MCI_StringType_List;
while (mst->str && strcmp(mst->str, str)) mst++;
return mst->type;
}
LPCSTR MCI_GetStringFromDevType(WORD type)
{
struct MCI_StringType* mst = MCI_StringType_List;
while (mst->str && mst->type != type) mst++;
return mst->str;
}
/* The wDevID's returned by wine were originally in the range
* 0 - (MAXMCIDRIVERS - 1) and used directly as array indices.
* Unfortunately, ms-windows uses wDevID of zero to indicate
@ -39,73 +79,6 @@ LPSTR lpmciInstallNames = NULL;
#define MCI_MAGIC 0x0F00
MCI_WineDesc MCI_InternalDescriptors[] = {
{MCI_DEVTYPE_CD_AUDIO, "CDAUDIO", MCICDAUDIO_DriverProc},
{MCI_DEVTYPE_WAVEFORM_AUDIO, "WAVEAUDIO", MCIWAVE_DriverProc},
{MCI_DEVTYPE_SEQUENCER, "SEQUENCER", MCIMIDI_DriverProc},
{MCI_DEVTYPE_ANIMATION, "ANIMATION1", MCIANIM_DriverProc},
{MCI_DEVTYPE_DIGITAL_VIDEO, "AVIVIDEO", MCIAVI_DriverProc},
{0xFFFF, NULL, NULL} /* sentinel */
};
#if 0
/**************************************************************************
* MCI_GetDevTypeString [internal]
*/
static LPCSTR MCI_GetDevTypeString(WORD uDevType)
{
LPCSTR str = "??? MCI ???";
int i;
for (i = 0; MCI_InternalDescriptors[i].uDevType != 0xFFFF; i++) {
if (MCI_InternalDescriptors[i].uDevType != 0 &&
MCI_InternalDescriptors[i].uDevType == uDevType) {
str = MCI_InternalDescriptors[i].lpstrName;
break;
}
}
/* TRACE(mci, "devType=%u => %s\n", uDevType, str);*/
return str;
}
#endif
/**************************************************************************
* MCI_GetProc [internal]
*/
static MCIPROC MCI_GetProc(UINT16 uDevType)
{
MCIPROC proc = 0;
int i;
for (i = 0; MCI_InternalDescriptors[i].uDevType != 0xFFFF; i++) {
if (MCI_InternalDescriptors[i].uDevType != 0 &&
MCI_InternalDescriptors[i].uDevType == uDevType) {
proc = MCI_InternalDescriptors[i].lpfnProc;
break;
}
}
return proc;
}
/**************************************************************************
* MCI_GetDevType [internal]
*/
WORD MCI_GetDevType(LPCSTR str)
{
WORD uDevType = 0;
int i;
for (i = 0; MCI_InternalDescriptors[i].uDevType != 0xFFFF; i++) {
if (MCI_InternalDescriptors[i].uDevType != 0 &&
strcmp(str, MCI_InternalDescriptors[i].lpstrName) == 0) {
uDevType = MCI_InternalDescriptors[i].uDevType;
break;
}
}
return uDevType;
}
/**************************************************************************
* MCI_DevIDToIndex [internal]
*/
@ -191,10 +164,10 @@ const char* MCI_CommandToString(UINT16 wMsg)
/**************************************************************************
* MCI_MapMsg16To32A [internal]
*/
int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
MCI_MapType MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
{
if (*lParam == 0)
return 0;
return MCI_MAP_OK;
/* FIXME: to add also (with seg/linear modifications to do):
* MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
* MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
@ -233,7 +206,7 @@ int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
case MCI_UPDATE:
case MCI_WHERE:
*lParam = (DWORD)PTR_SEG_TO_LIN(*lParam);
return 0;
return MCI_MAP_OK;
case MCI_WINDOW:
/* in fact, I would also need the dwFlags... to see
* which members of lParam are effectively used
@ -251,11 +224,11 @@ int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
mbp32->nVirtKey = mbp16->nVirtKey;
mbp32->hwndBreak = mbp16->hwndBreak;
} else {
return -2;
return MCI_MAP_NOMEM;
}
*lParam = (DWORD)mbp32;
}
return 1;
return MCI_MAP_OKMEM;
case MCI_ESCAPE:
{
LPMCI_VD_ESCAPE_PARMSA mvep32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_VD_ESCAPE_PARMSA));
@ -265,11 +238,11 @@ int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
mvep32a->dwCallback = mvep16->dwCallback;
mvep32a->lpstrCommand = PTR_SEG_TO_LIN(mvep16->lpstrCommand);
} else {
return -2;
return MCI_MAP_NOMEM;
}
*lParam = (DWORD)mvep32a;
}
return 1;
return MCI_MAP_OKMEM;
case MCI_INFO:
{
LPMCI_INFO_PARMSA mip32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_INFO_PARMSA));
@ -283,11 +256,11 @@ int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
mip32a->lpstrReturn = PTR_SEG_TO_LIN(mip16->lpstrReturn);
mip32a->dwRetSize = mip16->dwRetSize;
} else {
return -2;
return MCI_MAP_NOMEM;
}
*lParam = (DWORD)mip32a;
}
return 1;
return MCI_MAP_OKMEM;
case MCI_OPEN:
case MCI_OPEN_DRIVER:
{
@ -312,11 +285,11 @@ int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
*/
memcpy(mop32a + 1, mop16 + 1, 2 * sizeof(DWORD));
} else {
return -2;
return MCI_MAP_NOMEM;
}
*lParam = (DWORD)mop32a;
}
return 1;
return MCI_MAP_OKMEM;
case MCI_SYSINFO:
{
LPMCI_SYSINFO_PARMSA msip32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_SYSINFO_PARMSA));
@ -329,11 +302,11 @@ int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
msip32a->dwNumber = msip16->dwNumber;
msip32a->wDeviceType = msip16->wDeviceType;
} else {
return -2;
return MCI_MAP_NOMEM;
}
*lParam = (DWORD)msip32a;
}
return 1;
return MCI_MAP_OKMEM;
case DRV_LOAD:
case DRV_ENABLE:
case DRV_OPEN:
@ -348,18 +321,18 @@ int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
case DRV_EXITAPPLICATION:
case DRV_POWER:
FIXME(mci, "This is a hack\n");
return 0;
return MCI_MAP_OK;
default:
WARN(mci, "Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
}
return -1;
return MCI_MAP_MSGERROR;
}
/**************************************************************************
* MCI_UnMapMsg16To32A [internal]
*/
int MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
MCI_MapType MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
{
switch (wMsg) {
/* case MCI_CAPTURE */
@ -394,18 +367,18 @@ int MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
case MCI_UNFREEZE:
case MCI_UPDATE:
case MCI_WHERE:
return 0;
return MCI_MAP_OK;
case MCI_WINDOW:
/* FIXME ?? see Map function */
return 0;
return MCI_MAP_OK;
case MCI_BREAK:
case MCI_ESCAPE:
case MCI_INFO:
case MCI_SYSINFO:
HeapFree(SystemHeap, 0, (LPVOID)lParam);
return 0;
return MCI_MAP_OK;
case MCI_OPEN:
case MCI_OPEN_DRIVER:
if (lParam) {
@ -416,7 +389,7 @@ int MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
if (!HeapFree(SystemHeap, 0, (LPVOID)(lParam - sizeof(LPMCI_OPEN_PARMS16))))
FIXME(mci, "bad free line=%d\n", __LINE__);
}
return 0;
return MCI_MAP_OK;
case DRV_LOAD:
case DRV_ENABLE:
case DRV_OPEN:
@ -431,68 +404,13 @@ int MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
case DRV_EXITAPPLICATION:
case DRV_POWER:
FIXME(mci, "This is a hack\n");
return 0;
return MCI_MAP_OK;
default:
FIXME(mci, "Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
}
return -1;
return MCI_MAP_MSGERROR;
}
#if 0
/**************************************************************************
* MCI_MsgMapper32To16_Create [internal]
*
* Helper for MCI_MapMsg32ATo16.
* Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit segmented pointer.
* if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
* 1 : ok, some memory allocated
* -2 : ko, memory problem
*/
static int MCI_MsgMapper32To16_Create(void** ptr, int size, BOOLEAN keep)
{
void* lp = SEGPTR_ALLOC(sizeof(void**) + size);
if (!lp) {
return -2;
}
if (keep) {
*(void**)lp = *ptr;
memcpy((char*)lp + sizeof(void**), *ptr, size);
*ptr = (char*)SEGPTR_GET(lp) + sizeof(void**);
} else {
memcpy((char*)lp, *ptr, size);
*ptr = (void*)SEGPTR_GET(lp);
}
return 1;
}
/**************************************************************************
* MCI_MsgMapper32To16_Destroy [internal]
*
* Helper for MCI_UnMapMsg32ATo16.
*/
static int MCI_MsgMapper32To16_Destroy(void* ptr, int size, BOOLEAN kept)
{
if (ptr) {
void* msg16 = PTR_SEG_TO_LIN(ptr);
void* alloc;
if (kept) {
alloc = (char*)msg16 - sizeof(void**);
memcpy(*(void**)alloc, msg16, size);
} else {
alloc = msg16;
}
if (!SEGPTR_FREE(alloc)) {
FIXME(mci, "bad free line=%d\n", __LINE__);
}
}
return 0;
}
#endif
/*
* 0000 stop
* 0001 squeeze signed 4 bytes to 2 bytes *( LPINT16)D = ( INT16)*( LPINT16)S; D += 2; S += 4
@ -505,7 +423,7 @@ static int MCI_MsgMapper32To16_Destroy(void* ptr, int size, BOOLEAN kept)
*/
/**************************************************************************
* MCI_MsgMapper32To16_CreateV2 [internal]
* MCI_MsgMapper32To16_Create [internal]
*
* Helper for MCI_MapMsg32ATo16.
* Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit
@ -513,16 +431,14 @@ static int MCI_MsgMapper32To16_Destroy(void* ptr, int size, BOOLEAN kept)
* map contains a list of action to be performed for the mapping (see list
* above)
* if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
* 1 : ok, some memory allocated
* -2 : ko, memory problem
*/
static int MCI_MsgMapper32To16_CreateV2(void** ptr, int size16, DWORD map, BOOLEAN keep)
static MCI_MapType MCI_MsgMapper32To16_Create(void** ptr, int size16, DWORD map, BOOLEAN keep)
{
void* lp = SEGPTR_ALLOC((keep ? sizeof(void**) : 0) + size16);
LPBYTE p16, p32;
if (!lp) {
return -2;
return MCI_MAP_NOMEM;
}
p32 = (LPBYTE)(*ptr);
if (keep) {
@ -562,15 +478,15 @@ static int MCI_MsgMapper32To16_CreateV2(void** ptr, int size16, DWORD map, BOOLE
if (size16 != 0) /* DEBUG only */
FIXME(mci, "Mismatch between 16 bit struct size and map nibbles serie\n");
}
return 1;
return MCI_MAP_OKMEM;
}
/**************************************************************************
* MCI_MsgMapper32To16_DestroyV2 [internal]
* MCI_MsgMapper32To16_Destroy [internal]
*
* Helper for MCI_UnMapMsg32ATo16.
*/
static int MCI_MsgMapper32To16_DestroyV2(void* ptr, int size16, DWORD map, BOOLEAN kept)
static MCI_MapType MCI_MsgMapper32To16_Destroy(void* ptr, int size16, DWORD map, BOOLEAN kept)
{
if (ptr) {
void* msg16 = PTR_SEG_TO_LIN(ptr);
@ -619,26 +535,22 @@ static int MCI_MsgMapper32To16_DestroyV2(void* ptr, int size16, DWORD map, BOOLE
FIXME(mci, "bad free line=%d\n", __LINE__);
}
}
return 0;
return MCI_MAP_OK;
}
/**************************************************************************
* MCI_MapMsg32ATo16 [internal]
*
* Map a 32-A bit MCI message to a 16 bit MCI message.
* 1 : ok, some memory allocated, need to call MCI_UnMapMsg32ATo16
* 0 : ok, no memory allocated
* -1 : ko, unknown message
* -2 : ko, memory problem
*/
int MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
MCI_MapType MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
{
int size;
BOOLEAN keep = FALSE;
DWORD map = 0;
if (*lParam == 0)
return 0;
return MCI_MAP_OK;
/* FIXME: to add also (with seg/linear modifications to do):
* MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
@ -656,7 +568,7 @@ int MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
case MCI_CUE:
switch (uDevType) {
case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_CUE_PARMS); break;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_CUE_PARMS); break;*/ FIXME(mci, "NIY vcr\n"); return -2;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_CUE_PARMS); break;*/ FIXME(mci, "NIY vcr\n"); return MCI_MAP_NOMEM;
default: size = sizeof(MCI_GENERIC_PARMS); break;
}
break;
@ -703,11 +615,11 @@ int MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
((LPMCI_DGV_INFO_PARMS16)mip16)->dwItem = ((LPMCI_DGV_INFO_PARMSA)mip32a)->dwItem;
}
} else {
return -2;
return MCI_MAP_NOMEM;
}
*lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_INFO_PARMSA);
}
return 1;
return MCI_MAP_OKMEM;
/* case MCI_MARK: */
/* case MCI_MONITOR: */
case MCI_OPEN:
@ -759,11 +671,11 @@ int MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
*/
memcpy(mop16 + 1, mop32a + 1, 2 * sizeof(DWORD));
} else {
return -2;
return MCI_MAP_NOMEM;
}
*lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_OPEN_PARMSA);
}
return 1;
return MCI_MAP_OKMEM;
/* case MCI_PASTE:*/
case MCI_PAUSE:
size = sizeof(MCI_GENERIC_PARMS);
@ -784,7 +696,7 @@ int MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
case MCI_RECORD:
switch (uDevType) {
case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECORD_PARMS16); map = 0x0F1111FB; break;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_RECORD_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_RECORD_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return MCI_MAP_NOMEM;
default: size = sizeof(MCI_RECORD_PARMS); break;
}
break;
@ -793,14 +705,14 @@ int MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
break;
case MCI_SEEK:
switch (uDevType) {
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_SEEK_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_SEEK_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return MCI_MAP_NOMEM;
default: size = sizeof(MCI_SEEK_PARMS); break;
}
break;
case MCI_SET:
switch (uDevType) {
case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SET_PARMS); break;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_SET_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_SET_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return MCI_MAP_NOMEM;
case MCI_DEVTYPE_SEQUENCER: size = sizeof(MCI_SEQ_SET_PARMS); break;
/* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
* so not doing anything should work...
@ -823,14 +735,14 @@ int MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
* Assuming solution 2: provided by MCI driver, so zeroing on entry
*/
case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16); map = 0x0B6FF; break;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return MCI_MAP_NOMEM;
default: size = sizeof(MCI_STATUS_PARMS); break;
}
break;
case MCI_STEP:
switch (uDevType) {
case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STEP_PARMS); break;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STEP_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STEP_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return MCI_MAP_NOMEM;
case MCI_DEVTYPE_VIDEODISC: size = sizeof(MCI_VD_STEP_PARMS); break;
default: size = sizeof(MCI_GENERIC_PARMS); break;
}
@ -854,11 +766,11 @@ int MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
msip16->dwNumber = msip32a->dwNumber;
msip16->wDeviceType = msip32a->wDeviceType;
} else {
return -2;
return MCI_MAP_NOMEM;
}
*lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_SYSINFO_PARMSA);
}
return 1;
return MCI_MAP_OKMEM;
/* case MCI_UNDO: */
case MCI_UNFREEZE:
switch (uDevType) {
@ -900,20 +812,19 @@ int MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
case DRV_EXITSESSION:
case DRV_EXITAPPLICATION:
case DRV_POWER:
FIXME(mci, "This is a hack\n");
return 0;
return MCI_MAP_PASS;
default:
WARN(mci, "Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
return -1;
return MCI_MAP_MSGERROR;
}
return MCI_MsgMapper32To16_CreateV2((void**)lParam, size, map, keep);
return MCI_MsgMapper32To16_Create((void**)lParam, size, map, keep);
}
/**************************************************************************
* MCI_UnMapMsg32ATo16 [internal]
*/
int MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
MCI_MapType MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
{
int size = 0;
BOOLEAN kept = FALSE; /* there is no need to compute size when kept is FALSE */
@ -951,7 +862,7 @@ int MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
if (!SEGPTR_FREE((char*)mip16 - sizeof(LPMCI_INFO_PARMSA)))
FIXME(mci, "bad free line=%d\n", __LINE__);
}
return 0;
return MCI_MAP_OK;
/* case MCI_MARK: */
/* case MCI_MONITOR: */
case MCI_OPEN:
@ -976,7 +887,7 @@ int MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
if (!SEGPTR_FREE((char*)mop16 - sizeof(LPMCI_OPEN_PARMSA)))
FIXME(mci, "bad free line=%d\n", __LINE__);
}
return 0;
return MCI_MAP_OK;
/* case MCI_PASTE:*/
case MCI_PAUSE:
break;
@ -1019,11 +930,11 @@ int MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
if (!SEGPTR_FREE((char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA)))
FIXME(mci, "bad free line=%d\n", __LINE__);
} else {
return -2;
return MCI_MAP_NOMEM;
}
}
return 1;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
return MCI_MAP_OKMEM;
case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return MCI_MAP_NOMEM;
default: size = sizeof(MCI_STATUS_PARMS); break;
}
break;
@ -1045,10 +956,10 @@ int MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
if (!SEGPTR_FREE((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA)))
FIXME(mci, "bad free line=%d\n", __LINE__);
} else {
return -2;
return MCI_MAP_NOMEM;
}
}
return 1;
return MCI_MAP_OKMEM;
/* case MCI_UNDO: */
case MCI_UNFREEZE:
break;
@ -1084,51 +995,47 @@ int MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
case DRV_EXITAPPLICATION:
case DRV_POWER:
FIXME(mci, "This is a hack\n");
return 0;
return MCI_MAP_PASS;
default:
FIXME(mci, "Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
return -1;
return MCI_MAP_MSGERROR;
}
return MCI_MsgMapper32To16_DestroyV2((void*)lParam, size, map, kept);
return MCI_MsgMapper32To16_Destroy((void*)lParam, size, map, kept);
}
/**************************************************************************
* MCI_SendCommand [internal]
* MCI_SendCommandFrom32 [internal]
*/
DWORD MCI_SendCommand(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
DWORD MCI_SendCommandFrom32(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
{
DWORD dwRet = MCIERR_DEVICE_NOT_INSTALLED;
if (!MCI_DevIDValid(wDevID)) {
dwRet = MCIERR_INVALID_DEVICE_ID;
} else {
MCIPROC proc = MCI_GetProc(MCI_GetDrv(wDevID)->modp.wType);
if (proc) {
dwRet = (*proc)(MCI_GetDrv(wDevID)->modp.wDeviceID,
MCI_GetDrv(wDevID)->hDrv,
wMsg, dwParam1, dwParam2);
} else if (MCI_GetDrv(wDevID)->hDrv) {
switch (DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv)) {
case WINE_DI_TYPE_16:
{
int res;
MCI_MapType res;
switch (res = MCI_MapMsg32ATo16(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam1, &dwParam2)) {
case -1:
case MCI_MAP_MSGERROR:
TRACE(mci, "Not handled yet (%s)\n", MCI_CommandToString(wMsg));
dwRet = MCIERR_DRIVER_INTERNAL;
break;
case -2:
case MCI_MAP_NOMEM:
TRACE(mci, "Problem mapping msg=%s from 32a to 16\n", MCI_CommandToString(wMsg));
dwRet = MCIERR_OUT_OF_MEMORY;
break;
case 0:
case 1:
case MCI_MAP_OK:
case MCI_MAP_OKMEM:
dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
if (res)
if (res == MCI_MAP_OKMEM)
MCI_UnMapMsg32ATo16(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam1, dwParam2);
break;
case MCI_MAP_PASS:
dwRet = SendDriverMessage(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
break;
}
}
break;
@ -1139,8 +1046,50 @@ DWORD MCI_SendCommand(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
WARN(mci, "Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv));
dwRet = MCIERR_DRIVER_INTERNAL;
}
}
return dwRet;
}
/**************************************************************************
* MCI_SendCommandFrom16 [internal]
*/
DWORD MCI_SendCommandFrom16(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
{
DWORD dwRet = MCIERR_DEVICE_NOT_INSTALLED;
if (!MCI_DevIDValid(wDevID)) {
dwRet = MCIERR_INVALID_DEVICE_ID;
} else {
WARN(mci, "unknown device type=%04X !\n", MCI_GetDrv(wDevID)->modp.wType);
MCI_MapType res;
switch (DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv)) {
case WINE_DI_TYPE_16:
dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
break;
case WINE_DI_TYPE_32:
switch (res = MCI_MapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, &dwParam2)) {
case MCI_MAP_MSGERROR:
TRACE(mci, "Not handled yet (%s)\n", MCI_CommandToString(wMsg));
dwRet = MCIERR_DRIVER_INTERNAL;
break;
case MCI_MAP_NOMEM:
TRACE(mci, "Problem mapping msg=%s from 16 to 32a\n", MCI_CommandToString(wMsg));
dwRet = MCIERR_OUT_OF_MEMORY;
break;
case MCI_MAP_OK:
case MCI_MAP_OKMEM:
dwRet = SendDriverMessage(wDevID, wMsg, dwParam1, dwParam2);
if (res == MCI_MAP_OKMEM)
MCI_UnMapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam2);
break;
case MCI_MAP_PASS:
dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
break;
}
break;
default:
WARN(mci, "Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv));
dwRet = MCIERR_DRIVER_INTERNAL;
}
}
return dwRet;
@ -1155,12 +1104,15 @@ DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms)
UINT16 uDevType = 0;
UINT16 wDevID = MCI_FirstDevID();
DWORD dwRet;
HDRVR hDrv;
MCI_OPEN_DRIVER_PARMSA modp;
TRACE(mci, "(%08lX, %p)\n", dwParam, lpParms);
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
if ((dwParam & ~(MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY|MCI_WAIT)) != 0) {
FIXME(mci, "unsupported yet dwFlags=%08lX\n",
FIXME(mci, "Unsupported yet dwFlags=%08lX\n",
(dwParam & ~(MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY|MCI_WAIT)));
}
@ -1218,7 +1170,6 @@ DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms)
if (lpParms->lpstrDeviceType == NULL)
return MCIERR_NULL_PARAMETER_BLOCK;
TRACE(mci, "Dev='%s' !\n", lpParms->lpstrDeviceType);
/* FIXME is there any memory leak here ? */
strcpy(strDevTyp, lpParms->lpstrDeviceType);
}
}
@ -1230,12 +1181,6 @@ DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms)
CharUpperA(strDevTyp);
/* try Wine internal MCI drivers */
uDevType = MCI_GetDevType(strDevTyp);
if (uDevType == 0) { /* Nope, load external */
HDRVR hDrv;
MCI_OPEN_DRIVER_PARMSA modp;
modp.wDeviceID = wDevID;
modp.lpstrParams = NULL;
@ -1256,9 +1201,6 @@ DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms)
MCI_GetDrv(wDevID)->hDrv = hDrv;
TRACE(mci, "Loaded driver %u (%s), type is %d\n", hDrv, strDevTyp, uDevType);
} else {
MCI_GetDrv(wDevID)->hDrv = 0;
}
MCI_GetDrv(wDevID)->mop.lpstrDeviceType = strdup(strDevTyp);
MCI_GetDrv(wDevID)->modp.wType = uDevType;
@ -1269,16 +1211,18 @@ DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms)
TRACE(mci, "mcidev=%d, uDevType=%04X wDeviceID=%04X !\n",
wDevID, uDevType, lpParms->wDeviceID);
dwRet = MCI_SendCommand(wDevID, MCI_OPEN_DRIVER, dwParam, (DWORD)lpParms);
MCI_GetDrv(wDevID)->lpfnYieldProc = MCI_DefYieldProc;
MCI_GetDrv(wDevID)->dwYieldData = VK_CANCEL;
MCI_GetDrv(wDevID)->hCreatorTask = GetCurrentTask();
MCI_GetDrv(wDevID)->dwPrivate = 0;
dwRet = MCI_SendCommandFrom32(wDevID, MCI_OPEN_DRIVER, dwParam, (DWORD)lpParms);
if (dwRet == 0) {
/* only handled devices fall through */
TRACE(mci, "wDevID = %04X wDeviceID = %d dwRet = %ld\n", wDevID, lpParms->wDeviceID, dwRet);
} else {
TRACE(mci, "failed to open driver (MCI_OPEN_DRIVER msg) [%08lx], closing\n", dwRet);
TRACE(mci, "Failed to open driver (MCI_OPEN_DRIVER msg) [%08lx], closing\n", dwRet);
MCI_GetDrv(wDevID)->modp.wType = 0;
}
if (dwParam & MCI_NOTIFY)
@ -1301,9 +1245,9 @@ DWORD MCI_Close(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
return MCIERR_CANNOT_USE_ALL;
}
dwRet = MCI_SendCommand(wDevID, MCI_CLOSE_DRIVER, dwParam, (DWORD)lpParms);
dwRet = MCI_SendCommandFrom32(wDevID, MCI_CLOSE_DRIVER, dwParam, (DWORD)lpParms);
if (MCI_GetDrv(wDevID)->hDrv) {
#if 0
#if 1
CloseDriver(MCI_GetDrv(wDevID)->hDrv, 0, 0);
#endif
}

View file

@ -26,6 +26,7 @@ DEFAULT_DEBUG_CHANNEL(mcianim)
#define SECONDS_PERMIN 60
typedef struct {
UINT16 wDevID;
int nUseCount; /* Incremented for each shared open */
BOOL16 fShareable; /* TRUE if first open was shareable */
WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
@ -41,20 +42,69 @@ typedef struct {
LPDWORD lpdwTrackPos;
} WINE_MCIANIM;
static WINE_MCIANIM AnimDev[MAX_ANIMDRV];
static WINE_MCIANIM MCIAnimDev[MAX_ANIMDRV];
/*-----------------------------------------------------------------------*/
/**************************************************************************
* ANIM_drvGetDrv [internal]
*/
static WINE_MCIANIM* ANIM_drvGetDrv(UINT16 wDevID)
{
int i;
for (i = 0; i < MAX_ANIMDRV; i++) {
if (MCIAnimDev[i].wDevID == wDevID) {
return &MCIAnimDev[i];
}
}
return 0;
}
/**************************************************************************
* ANIM_drvOpen [internal]
*/
static DWORD ANIM_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
{
int i;
for (i = 0; i < MAX_ANIMDRV; i++) {
if (MCIAnimDev[i].wDevID == 0) {
MCIAnimDev[i].wDevID = modp->wDeviceID;
modp->wCustomCommandTable = -1;
modp->wType = MCI_DEVTYPE_CD_AUDIO;
return modp->wDeviceID;
}
}
return 0;
}
/**************************************************************************
* ANIM_drvClose [internal]
*/
static DWORD ANIM_drvClose(DWORD dwDevID)
{
WINE_MCIANIM* wma = ANIM_drvGetDrv(dwDevID);
if (wma) {
wma->wDevID = 0;
return 1;
}
return 0;
}
/**************************************************************************
* ANIM_mciGetOpenDrv [internal]
*/
static WINE_MCIANIM* ANIM_mciGetOpenDrv(UINT16 wDevID)
{
if (wDevID >= MAX_ANIMDRV || AnimDev[wDevID].nUseCount == 0) {
WINE_MCIANIM* wma = ANIM_drvGetDrv(wDevID);
if (wma == NULL || wma->nUseCount == 0) {
WARN(mcianim, "Invalid wDevID=%u\n", wDevID);
return 0;
}
return &AnimDev[wDevID];
return wma;
}
/**************************************************************************
@ -63,14 +113,12 @@ static WINE_MCIANIM* ANIM_mciGetOpenDrv(UINT16 wDevID)
static DWORD ANIM_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenParms)
{
DWORD dwDeviceID;
WINE_MCIANIM* wma;
WINE_MCIANIM* wma = ANIM_drvGetDrv(wDevID);
TRACE(mcianim,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpOpenParms);
if (lpOpenParms == NULL) return MCIERR_INTERNAL;
if (wDevID >= MAX_ANIMDRV) return MCIERR_INVALID_DEVICE_ID;
wma = &AnimDev[wDevID];
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
if (wma->nUseCount > 0) {
/* The driver already open on this channel */
@ -585,20 +633,20 @@ static DWORD ANIM_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
}
/**************************************************************************
* ANIM_DriverProc32 [sample driver]
* ANIM_DriverProc [sample driver]
*/
LONG MCIANIM_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
LONG MCIANIM_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2)
{
switch(wMsg) {
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return 1;
case DRV_CLOSE: return 1;
case DRV_OPEN: return ANIM_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
case DRV_CLOSE: return ANIM_drvClose(dwDevID);
case DRV_ENABLE: return 1;
case DRV_DISABLE: return 1;
case DRV_QUERYCONFIGURE: return 1;
case DRV_CONFIGURE: MessageBoxA(0, "Sample MultiMedia Linux Driver !", "MMLinux Driver", MB_OK); return 1;
case DRV_CONFIGURE: MessageBoxA(0, "Sample MultiMedia Driver !", "Wine Driver", MB_OK); return 1;
case DRV_INSTALL: return DRVCNF_RESTART;
case DRV_REMOVE: return DRVCNF_RESTART;
@ -642,5 +690,4 @@ LONG MCIANIM_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
return MCIERR_UNRECOGNIZED_COMMAND;
}
/*-----------------------------------------------------------------------*/

View file

@ -15,11 +15,10 @@
#include "digitalv.h"
#include "options.h"
DECLARE_DEBUG_CHANNEL(cdaudio)
DECLARE_DEBUG_CHANNEL(mciavi)
DECLARE_DEBUG_CHANNEL(mcimidi)
typedef struct {
UINT wDevID;
int nUseCount; /* Incremented for each shared open */
BOOL16 fShareable; /* TRUE if first open was shareable */
WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
@ -37,16 +36,65 @@ static WINE_MCIAVI MCIAviDev[MAX_MCIAVIDRV];
* MCI AVI implemantation *
*======================================================================*/
/**************************************************************************
* AVI_drvGetDrv [internal]
*/
static WINE_MCIAVI* AVI_drvGetDrv(UINT16 wDevID)
{
int i;
for (i = 0; i < MAX_MCIAVIDRV; i++) {
if (MCIAviDev[i].wDevID == wDevID) {
return &MCIAviDev[i];
}
}
return 0;
}
/**************************************************************************
* AVI_drvOpen [internal]
*/
static DWORD AVI_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
{
int i;
for (i = 0; i < MAX_MCIAVIDRV; i++) {
if (MCIAviDev[i].wDevID == 0) {
MCIAviDev[i].wDevID = modp->wDeviceID;
modp->wCustomCommandTable = -1;
modp->wType = MCI_DEVTYPE_CD_AUDIO;
return modp->wDeviceID;
}
}
return 0;
}
/**************************************************************************
* MCIAVI_drvClose [internal]
*/
static DWORD AVI_drvClose(DWORD dwDevID)
{
WINE_MCIAVI* wma = AVI_drvGetDrv(dwDevID);
if (wma) {
wma->wDevID = 0;
return 1;
}
return 0;
}
/**************************************************************************
* AVI_mciGetOpenDev [internal]
*/
static WINE_MCIAVI* AVI_mciGetOpenDev(UINT16 wDevID)
{
if (wDevID >= MAX_MCIAVIDRV || MCIAviDev[wDevID].nUseCount == 0) {
WINE_MCIAVI* wma = AVI_drvGetDrv(wDevID);
if (wma == NULL || wma->nUseCount == 0) {
WARN(mciavi, "Invalid wDevID=%u\n", wDevID);
return 0;
}
return &MCIAviDev[wDevID];
return wma;
}
static DWORD AVI_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
@ -56,14 +104,12 @@ static DWORD AVI_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpPar
*/
static DWORD AVI_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_DGV_OPEN_PARMSA lpParms)
{
WINE_MCIAVI* wma;
WINE_MCIAVI* wma = AVI_drvGetDrv(wDevID);
TRACE(mciavi, "(%04x, %08lX, %p) : semi-stub\n", wDevID, dwFlags, lpParms);
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
if (wDevID > MAX_MCIAVIDRV) return MCIERR_INVALID_DEVICE_ID;
wma = &MCIAviDev[wDevID];
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
if (wma->nUseCount > 0) {
/* The driver is already open on this channel */
@ -78,7 +124,7 @@ static DWORD AVI_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_DGV_OPEN_PARMSA lpP
wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
}
if (dwFlags & MCI_OPEN_ELEMENT) {
TRACE(cdaudio,"MCI_OPEN_ELEMENT !\n");
TRACE(mciavi,"MCI_OPEN_ELEMENT !\n");
/* return MCIERR_NO_ELEMENT_ALLOWED; */
}
@ -130,7 +176,7 @@ static DWORD AVI_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
wma->wStatus = MCI_MODE_PLAY;
if (lpParms && (dwFlags & MCI_NOTIFY)) {
TRACE(mcimidi, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
TRACE(mciavi, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
wma->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
}
@ -933,14 +979,14 @@ static DWORD AVI_mciRestore(UINT16 wDevID, DWORD dwFlags, LPMCI_DGV_RESTORE_PARM
/**************************************************************************
* MCIAVI_DriverProc [sample driver]
*/
LONG MCIAVI_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
LONG MCIAVI_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2)
{
switch (wMsg) {
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return 1;
case DRV_CLOSE: return 1;
case DRV_OPEN: return AVI_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
case DRV_CLOSE: return AVI_drvClose(dwDevID);
case DRV_ENABLE: return 1;
case DRV_DISABLE: return 1;
case DRV_QUERYCONFIGURE: return 1;

View file

@ -10,12 +10,13 @@
#include "winuser.h"
#include "driver.h"
#include "multimedia.h"
#include "debug.h"
#include "cdrom.h"
#include "debug.h"
DEFAULT_DEBUG_CHANNEL(cdaudio)
typedef struct {
UINT16 wDevID;
int nUseCount; /* Incremented for each shared open */
BOOL16 fShareable; /* TRUE if first open was shareable */
WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
@ -31,17 +32,65 @@ static WINE_MCICDAUDIO CDADev[MAX_CDAUDIODRV];
/*-----------------------------------------------------------------------*/
/**************************************************************************
* CDAUDIO_drvGetDrv [internal]
*/
static WINE_MCICDAUDIO* CDAUDIO_drvGetDrv(UINT16 wDevID)
{
int i;
for (i = 0; i < MAX_CDAUDIODRV; i++) {
if (CDADev[i].wDevID == wDevID) {
return &CDADev[i];
}
}
return 0;
}
/**************************************************************************
* CDAUDIO_drvOpen [internal]
*/
static DWORD CDAUDIO_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
{
int i;
for (i = 0; i < MAX_CDAUDIODRV; i++) {
if (CDADev[i].wDevID == 0) {
CDADev[i].wDevID = modp->wDeviceID;
modp->wCustomCommandTable = -1;
modp->wType = MCI_DEVTYPE_CD_AUDIO;
return modp->wDeviceID;
}
}
return 0;
}
/**************************************************************************
* CDAUDIO_drvClose [internal]
*/
static DWORD CDAUDIO_drvClose(DWORD dwDevID)
{
WINE_MCICDAUDIO* wmcda = CDAUDIO_drvGetDrv(dwDevID);
if (wmcda) {
wmcda->wDevID = 0;
return 1;
}
return 0;
}
/**************************************************************************
* CDAUDIO_mciGetOpenDrv [internal]
*/
static WINE_MCICDAUDIO* CDAUDIO_mciGetOpenDrv(UINT16 wDevID)
{
if (wDevID >= MAX_CDAUDIODRV || CDADev[wDevID].nUseCount == 0 ||
CDADev[wDevID].wcda.unixdev <= 0) {
WINE_MCICDAUDIO* wmcda = CDAUDIO_drvGetDrv(wDevID);
if (wmcda == NULL || wmcda->nUseCount == 0 || wmcda->wcda.unixdev <= 0) {
WARN(cdaudio, "Invalid wDevID=%u\n", wDevID);
return 0;
}
return &CDADev[wDevID];
return wmcda;
}
/**************************************************************************
@ -173,18 +222,16 @@ static DWORD CDAUDIO_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS l
static DWORD CDAUDIO_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenParms)
{
DWORD dwDeviceID;
WINE_MCICDAUDIO* wmcda;
WINE_MCICDAUDIO* wmcda = CDAUDIO_drvGetDrv(wDevID);
MCI_SEEK_PARMS seekParms;
TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpOpenParms);
if (lpOpenParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
if (wDevID > MAX_CDAUDIODRV) return MCIERR_INVALID_DEVICE_ID;
if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
dwDeviceID = lpOpenParms->wDeviceID;
wmcda = &CDADev[wDevID];
if (wmcda->nUseCount > 0) {
/* The driver is already open on this channel */
/* If the driver was opened shareable before and this open specifies */
@ -671,18 +718,18 @@ static DWORD CDAUDIO_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParm
/**************************************************************************
* MCICDAUDIO_DriverProc [sample driver]
*/
LONG MCICDAUDIO_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
LONG MCICDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2)
{
switch(wMsg) {
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return 1;
case DRV_CLOSE: return 1;
case DRV_OPEN: return CDAUDIO_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
case DRV_CLOSE: return CDAUDIO_drvClose(dwDevID);
case DRV_ENABLE: return 1;
case DRV_DISABLE: return 1;
case DRV_QUERYCONFIGURE: return 1;
case DRV_CONFIGURE: MessageBoxA(0, "Sample Multimedia Linux Driver !", "MMLinux Driver", MB_OK); return 1;
case DRV_CONFIGURE: MessageBoxA(0, "Sample Multimedia Driver !", "Wine Driver", MB_OK); return 1;
case DRV_INSTALL: return DRVCNF_RESTART;
case DRV_REMOVE: return DRVCNF_RESTART;

View file

@ -22,13 +22,11 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include "winuser.h"
#include "ldt.h"
#include "multimedia.h"
#include "user.h"
#include "driver.h"
#include "xmalloc.h"
#include "debug.h"
#include "heap.h"
#include "debug.h"
DECLARE_DEBUG_CHANNEL(mcimidi)
DECLARE_DEBUG_CHANNEL(midi)
@ -47,6 +45,8 @@ typedef struct {
} MCI_MIDITRACK;
typedef struct {
UINT16 wDevID;
UINT16 wMidiID;
int nUseCount; /* Incremented for each shared open */
WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
HANDLE16 hCallback; /* Callback handle for pending notification */
@ -74,16 +74,65 @@ static WINE_MCIMIDI MCIMidiDev[MAX_MCIMIDIDRV];
*======================================================================*/
#ifdef SNDCTL_MIDI_INFO
/**************************************************************************
* MIDI_drvGetDrv [internal]
*/
static WINE_MCIMIDI* MIDI_drvGetDrv(UINT16 wDevID)
{
int i;
for (i = 0; i < MAX_MCIMIDIDRV; i++) {
if (MCIMidiDev[i].wDevID == wDevID) {
return &MCIMidiDev[i];
}
}
return 0;
}
/**************************************************************************
* MIDI_drvOpen [internal]
*/
static DWORD MIDI_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
{
int i;
for (i = 0; i < MAX_MCIMIDIDRV; i++) {
if (MCIMidiDev[i].wDevID == 0) {
MCIMidiDev[i].wDevID = modp->wDeviceID;
modp->wCustomCommandTable = -1;
modp->wType = MCI_DEVTYPE_CD_AUDIO;
return modp->wDeviceID;
}
}
return 0;
}
/**************************************************************************
* MCIMIDI_drvClose [internal]
*/
static DWORD MIDI_drvClose(DWORD dwDevID)
{
WINE_MCIMIDI* wmm = MIDI_drvGetDrv(dwDevID);
if (wmm) {
wmm->wDevID = 0;
return 1;
}
return 0;
}
/**************************************************************************
* MIDI_mciGetOpenDev [internal]
*/
static WINE_MCIMIDI* MIDI_mciGetOpenDev(UINT16 wDevID)
{
if (wDevID >= MAX_MCIMIDIDRV || MCIMidiDev[wDevID].nUseCount == 0) {
WINE_MCIMIDI* wmm = MIDI_drvGetDrv(wDevID);
if (wmm == NULL || wmm->nUseCount == 0) {
WARN(mcimidi, "Invalid wDevID=%u\n", wDevID);
return 0;
}
return &MCIMidiDev[wDevID];
return wmm;
}
/**************************************************************************
@ -96,7 +145,7 @@ static DWORD MIDI_mciReadByte(WINE_MCIMIDI* wmm, BYTE *lpbyt)
if (lpbyt == NULL ||
mmioRead(wmm->hFile, (HPSTR)lpbyt, (long)sizeof(BYTE)) != (long)sizeof(BYTE)) {
WARN(mcimidi, "Error reading wmm=%p\n", wmm);
ret = MCIERR_INTERNAL;
ret = MCIERR_INVALID_FILE;
}
return ret;
@ -108,7 +157,7 @@ static DWORD MIDI_mciReadByte(WINE_MCIMIDI* wmm, BYTE *lpbyt)
static DWORD MIDI_mciReadWord(WINE_MCIMIDI* wmm, LPWORD lpw)
{
BYTE hibyte, lobyte;
DWORD ret = MCIERR_INTERNAL;
DWORD ret = MCIERR_INVALID_FILE;
if (lpw != NULL &&
MIDI_mciReadByte(wmm, &hibyte) == 0 &&
@ -125,7 +174,7 @@ static DWORD MIDI_mciReadWord(WINE_MCIMIDI* wmm, LPWORD lpw)
static DWORD MIDI_mciReadLong(WINE_MCIMIDI* wmm, LPDWORD lpdw)
{
WORD hiword, loword;
DWORD ret = MCIERR_INTERNAL;
DWORD ret = MCIERR_INVALID_FILE;
if (lpdw != NULL &&
MIDI_mciReadWord(wmm, &hiword) == 0 &&
@ -146,7 +195,7 @@ static WORD MIDI_mciReadVaryLen(WINE_MCIMIDI* wmm, LPDWORD lpdw)
WORD ret = 0;
if (lpdw == NULL) {
ret = MCIERR_INTERNAL;
ret = MCIERR_INVALID_FILE;
} else {
do {
if (MIDI_mciReadByte(wmm, &byte) != 0) {
@ -176,7 +225,7 @@ static DWORD MIDI_mciReadNextEvent(WINE_MCIMIDI* wmm, MCI_MIDITRACK* mmt)
if (mmioSeek(wmm->hFile, mmt->dwIndex, SEEK_SET) != mmt->dwIndex) {
WARN(mcimidi, "Can't seek at %08lX \n", mmt->dwIndex);
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
evtLength = MIDI_mciReadVaryLen(wmm, &evtPulse) + 1; /* > 0 */
MIDI_mciReadByte(wmm, &b1);
@ -244,16 +293,16 @@ static DWORD MIDI_mciReadMTrk(WINE_MCIMIDI* wmm, MCI_MIDITRACK* mmt)
if (mmioRead(wmm->hFile, (HPSTR)&fourcc, (long)sizeof(FOURCC)) !=
(long)sizeof(FOURCC)) {
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
if (fourcc != mmioFOURCC('M', 'T', 'r', 'k')) {
WARN(mcimidi, "Can't synchronize on 'MTrk' !\n");
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
if (MIDI_mciReadLong(wmm, &toberead) != 0) {
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
mmt->dwFirst = mmioSeek(wmm->hFile, 0, SEEK_CUR); /* >= 0 */
mmt->dwLast = mmt->dwFirst + toberead;
@ -298,24 +347,24 @@ static DWORD MIDI_mciReadMThd(WINE_MCIMIDI* wmm, DWORD dwOffset)
if (mmioSeek(wmm->hFile, dwOffset, SEEK_SET) != dwOffset) {
WARN(mcimidi, "Can't seek at %08lX begin of 'MThd' \n", dwOffset);
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
if (mmioRead(wmm->hFile, (HPSTR)&fourcc,
(long) sizeof(FOURCC)) != (long) sizeof(FOURCC))
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
if (fourcc != mmioFOURCC('M', 'T', 'h', 'd')) {
WARN(mcimidi, "Can't synchronize on 'MThd' !\n");
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
if (MIDI_mciReadLong(wmm, &toberead) != 0 || toberead < 3 * sizeof(WORD))
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
if (MIDI_mciReadWord(wmm, &wmm->wFormat) != 0 ||
MIDI_mciReadWord(wmm, &wmm->nTracks) != 0 ||
MIDI_mciReadWord(wmm, &wmm->nDivision) != 0) {
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
TRACE(mcimidi, "toberead=0x%08lX, wFormat=0x%04X nTracks=0x%04X nDivision=0x%04X\n",
@ -341,7 +390,7 @@ static DWORD MIDI_mciReadMThd(WINE_MCIMIDI* wmm, DWORD dwOffset)
case 0xE2: wmm->dwMciTimeFormat = MCI_FORMAT_SMPTE_30; break; /* -30 */
default:
WARN(mcimidi, "Unsupported number of frames %d\n", -(char)HIBYTE(wmm->nDivision));
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
switch (LOBYTE(wmm->nDivision)) {
case 4: /* MIDI Time Code */
@ -351,12 +400,11 @@ static DWORD MIDI_mciReadMThd(WINE_MCIMIDI* wmm, DWORD dwOffset)
case 100:
default:
WARN(mcimidi, "Unsupported number of sub-frames %d\n", LOBYTE(wmm->nDivision));
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
return MCIERR_INTERNAL;
} else if (wmm->nDivision == 0) {
WARN(mcimidi, "Number of division is 0, can't support that !!\n");
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
} else {
wmm->dwMciTimeFormat = MCI_FORMAT_MILLISECONDS;
}
@ -374,7 +422,7 @@ static DWORD MIDI_mciReadMThd(WINE_MCIMIDI* wmm, DWORD dwOffset)
default:
WARN(mcimidi, "Handling MIDI files which format = %d is not (yet) supported\n"
"Please report with MIDI file !\n", wmm->wFormat);
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
if (wmm->nTracks & 0x8000) {
@ -383,7 +431,9 @@ static DWORD MIDI_mciReadMThd(WINE_MCIMIDI* wmm, DWORD dwOffset)
wmm->nTracks = 0x7FFF;
}
wmm->tracks = xmalloc(sizeof(MCI_MIDITRACK) * wmm->nTracks);
if ((wmm->tracks = malloc(sizeof(MCI_MIDITRACK) * wmm->nTracks)) == NULL) {
return MCIERR_OUT_OF_MEMORY;
}
toberead -= 3 * sizeof(WORD);
if (toberead > 0) {
@ -395,7 +445,7 @@ static DWORD MIDI_mciReadMThd(WINE_MCIMIDI* wmm, DWORD dwOffset)
wmm->tracks[nt].wTrackNr = nt;
if (MIDI_mciReadMTrk(wmm, &wmm->tracks[nt]) != 0) {
WARN(mcimidi, "Can't read 'MTrk' header \n");
return MCIERR_INTERNAL;
return MCIERR_INVALID_FILE;
}
}
@ -547,20 +597,15 @@ static DWORD MIDI_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpParm
MIDIOPENDESC midiOpenDesc;
DWORD dwRet = 0;
DWORD dwDeviceID;
WINE_MCIMIDI* wmm;
WINE_MCIMIDI* wmm = MIDI_drvGetDrv(wDevID);
TRACE(mcimidi, "(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
if (wDevID >= MAX_MCIMIDIDRV) {
WARN(mcimidi, "Invalid wDevID=%u\n", wDevID);
return MCIERR_INVALID_DEVICE_ID;
}
if (wmm == NULL) return MCIERR_INVALID_DEVICE_ID;
if (dwFlags & MCI_OPEN_SHAREABLE)
return MCIERR_HARDWARE;
wmm = &MCIMidiDev[wDevID];
if (wmm->nUseCount > 0) {
/* The driver is already opened on this channel
* MIDI sequencer cannot be shared
@ -570,6 +615,7 @@ static DWORD MIDI_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpParm
wmm->nUseCount++;
wmm->hFile = 0;
wmm->wMidiID = 0;
dwDeviceID = lpParms->wDeviceID;
TRACE(mcimidi, "wDevID=%04X (lpParams->wDeviceID=%08lX)\n", wDevID, dwDeviceID);
@ -645,8 +691,8 @@ static DWORD MIDI_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpParm
wmm->dwStatus = MCI_MODE_STOP;
wmm->hMidiHdr = USER_HEAP_ALLOC(sizeof(MIDIHDR16));
dwRet = modMessage(wDevID, MODM_OPEN, 0, (DWORD)&midiOpenDesc, CALLBACK_NULL);
/* dwRet = midMessage(wDevID, MIDM_OPEN, 0, (DWORD)&midiOpenDesc, CALLBACK_NULL);*/
dwRet = modMessage(wmm->wMidiID, MODM_OPEN, 0, (DWORD)&midiOpenDesc, CALLBACK_NULL);
/* dwRet = midMessage(wmm->wMidiID, MIDM_OPEN, 0, (DWORD)&midiOpenDesc, CALLBACK_NULL);*/
}
return dwRet;
}
@ -699,10 +745,10 @@ static DWORD MIDI_mciClose(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpP
}
USER_HEAP_FREE(wmm->hMidiHdr);
free(wmm->tracks);
dwRet = modMessage(wDevID, MODM_CLOSE, 0, 0L, 0L);
dwRet = modMessage(wmm->wMidiID, MODM_CLOSE, 0, 0L, 0L);
if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
/*
dwRet = midMessage(wDevID, MIDM_CLOSE, 0, 0L, 0L);
dwRet = midMessage(wmm->wMidiID, MIDM_CLOSE, 0, 0L, 0L);
if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
*/
} else {
@ -974,7 +1020,7 @@ static DWORD MIDI_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
break;
default:
if (doPlay) {
dwRet = modMessage(wDevID, MODM_DATA, 0, mmt->dwEventData, 0);
dwRet = modMessage(wmm->wMidiID, MODM_DATA, 0, mmt->dwEventData, 0);
} else {
switch (LOBYTE(LOWORD(mmt->dwEventData)) & 0xF0) {
case MIDI_NOTEON:
@ -982,7 +1028,7 @@ static DWORD MIDI_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
dwRet = 0;
break;
default:
dwRet = modMessage(wDevID, MODM_DATA, 0, mmt->dwEventData, 0);
dwRet = modMessage(wmm->wMidiID, MODM_DATA, 0, mmt->dwEventData, 0);
}
}
}
@ -1006,7 +1052,7 @@ static DWORD MIDI_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
{
unsigned chn;
for (chn = 0; chn < 16; chn++)
modMessage(wDevID, MODM_DATA, 0, 0x78B0 | chn, 0);
modMessage(wmm->wMidiID, MODM_DATA, 0, 0x78B0 | chn, 0);
}
wmm->dwStatus = MCI_MODE_STOP;
@ -1051,24 +1097,26 @@ static DWORD MIDI_mciRecord(UINT16 wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpP
TRACE(mcimidi, "MCI_TO=%d \n", end);
}
lpMidiHdr = USER_HEAP_LIN_ADDR(wmm->hMidiHdr);
lpMidiHdr->lpData = (LPSTR) xmalloc(1200);
lpMidiHdr->lpData = (LPSTR) malloc(1200);
if (!lpMidiHdr)
return MCIERR_OUT_OF_MEMORY;
lpMidiHdr->dwBufferLength = 1024;
lpMidiHdr->dwUser = 0L;
lpMidiHdr->dwFlags = 0L;
dwRet = midMessage(wDevID, MIDM_PREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR16));
dwRet = midMessage(wmm->wMidiID, MIDM_PREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR16));
TRACE(mcimidi, "After MIDM_PREPARE \n");
wmm->dwStatus = MCI_MODE_RECORD;
while (wmm->dwStatus != MCI_MODE_STOP) {
TRACE(mcimidi, "wmm->dwStatus=%p %d\n",
&wmm->dwStatus, wmm->dwStatus);
lpMidiHdr->dwBytesRecorded = 0;
dwRet = midMessage(wDevID, MIDM_START, 0, 0L, 0L);
dwRet = midMessage(wmm->wMidiID, MIDM_START, 0, 0L, 0L);
TRACE(mcimidi, "After MIDM_START lpMidiHdr=%p dwBytesRecorded=%lu\n",
lpMidiHdr, lpMidiHdr->dwBytesRecorded);
if (lpMidiHdr->dwBytesRecorded == 0) break;
}
TRACE(mcimidi, "Before MIDM_UNPREPARE \n");
dwRet = midMessage(wDevID, MIDM_UNPREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR16));
dwRet = midMessage(wmm->wMidiID, MIDM_UNPREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR16));
TRACE(mcimidi, "After MIDM_UNPREPARE \n");
if (lpMidiHdr->lpData != NULL) {
free(lpMidiHdr->lpData);
@ -1099,7 +1147,7 @@ static DWORD MIDI_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpP
/* see note in MIDI_mciPlay */
unsigned chn;
for (chn = 0; chn < 16; chn++)
modMessage(wDevID, MODM_DATA, 0, 0x78B0 | chn, 0);
modMessage(wmm->wMidiID, MODM_DATA, 0, 0x78B0 | chn, 0);
wmm->dwStatus = MCI_MODE_PAUSE;
}
if (lpParms && (dwFlags & MCI_NOTIFY)) {
@ -1475,18 +1523,18 @@ static DWORD MIDI_mciSeek(UINT16 wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms
/**************************************************************************
* MCIMIDI_DriverProc [sample driver]
*/
LONG MCIMIDI_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
LONG MCIMIDI_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2)
{
switch (wMsg) {
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return 1;
case DRV_CLOSE: return 1;
case DRV_OPEN: return MIDI_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
case DRV_CLOSE: return MIDI_drvClose(dwDevID);
case DRV_ENABLE: return 1;
case DRV_DISABLE: return 1;
case DRV_QUERYCONFIGURE: return 1;
case DRV_CONFIGURE: MessageBoxA(0, "Sample Midi Linux Driver !", "MMLinux Driver", MB_OK); return 1;
case DRV_CONFIGURE: MessageBoxA(0, "Sample Midi Driver !", "OSS Driver", MB_OK); return 1;
case DRV_INSTALL: return DRVCNF_RESTART;
case DRV_REMOVE: return DRVCNF_RESTART;
#ifdef SNDCTL_MIDI_INFO

View file

@ -275,7 +275,7 @@ MCISTR_Open(_MCISTR_PROTO_)
pU->openParams.lpstrElementName = strdup(s);
dwFlags |= MCI_OPEN_ELEMENT;
}
uDevTyp = MCI_GetDevType(dev);
uDevTyp = MCI_GetDevTypeFromString(dev);
if (uDevTyp == 0) {
free(pU->openParams.lpstrElementName);
free(pU);

View file

@ -32,6 +32,8 @@ DEFAULT_DEBUG_CHANNEL(mciwave)
#define MAX_MCIWAVEDRV (1)
typedef struct {
UINT16 wDevID;
UINT16 wWavID;
int nUseCount; /* Incremented for each shared open */
BOOL16 fShareable; /* TRUE if first open was shareable */
WORD wNotifyDeviceID;/* MCI device ID with a pending notification */
@ -55,16 +57,65 @@ static WINE_MCIWAVE MCIWaveDev[MAX_MCIWAVEDRV];
* MCI WAVE implemantation *
*======================================================================*/
/**************************************************************************
* MCIWAVE_drvGetDrv [internal]
*/
static WINE_MCIWAVE* WAVE_drvGetDrv(UINT16 wDevID)
{
int i;
for (i = 0; i < MAX_MCIWAVEDRV; i++) {
if (MCIWaveDev[i].wDevID == wDevID) {
return &MCIWaveDev[i];
}
}
return 0;
}
/**************************************************************************
* MCIWAVE_drvOpen [internal]
*/
static DWORD WAVE_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
{
int i;
for (i = 0; i < MAX_MCIWAVEDRV; i++) {
if (MCIWaveDev[i].wDevID == 0) {
MCIWaveDev[i].wDevID = modp->wDeviceID;
modp->wCustomCommandTable = -1;
modp->wType = MCI_DEVTYPE_WAVEFORM_AUDIO;
return modp->wDeviceID;
}
}
return 0;
}
/**************************************************************************
* MCIWAVE_drvClose [internal]
*/
static DWORD WAVE_drvClose(DWORD dwDevID)
{
WINE_MCIWAVE* wmcda = WAVE_drvGetDrv(dwDevID);
if (wmcda) {
wmcda->wDevID = 0;
return 1;
}
return 0;
}
/**************************************************************************
* WAVE_mciGetOpenDev [internal]
*/
static WINE_MCIWAVE* WAVE_mciGetOpenDev(UINT16 wDevID)
{
if (wDevID >= MAX_MCIWAVEDRV || MCIWaveDev[wDevID].nUseCount == 0) {
WINE_MCIWAVE* wmw = WAVE_drvGetDrv(wDevID);
if (wmw == NULL || wmw->nUseCount == 0) {
WARN(mciwave, "Invalid wDevID=%u\n", wDevID);
return 0;
}
return &MCIWaveDev[wDevID];
return wmw;
}
static DWORD WAVE_ConvertByteToTimeFormat(WINE_MCIWAVE* wmw, DWORD val)
@ -147,20 +198,15 @@ static DWORD WAVE_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMSA l
{
DWORD dwRet = 0;
DWORD dwDeviceID;
WINE_MCIWAVE* wmw;
WINE_MCIWAVE* wmw = WAVE_drvGetDrv(wDevID);
TRACE(mciwave, "(%04X, %08lX, %p)\n", wDevID, dwFlags, lpOpenParms);
if (lpOpenParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
if (wDevID >= MAX_MCIWAVEDRV) {
WARN(mciwave, "Invalid wDevID=%u\n", wDevID);
return MCIERR_INVALID_DEVICE_ID;
}
if (dwFlags & MCI_OPEN_SHAREABLE)
return MCIERR_HARDWARE;
wmw = &MCIWaveDev[wDevID];
if (wmw->nUseCount > 0) {
/* The driver is already opened on this channel
* Wave driver cannot be shared
@ -172,6 +218,7 @@ static DWORD WAVE_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMSA l
dwDeviceID = lpOpenParms->wDeviceID;
wmw->fInput = FALSE;
wmw->wWavID = 0;
TRACE(mciwave, "wDevID=%04X (lpParams->wDeviceID=%08lX)\n", wDevID, dwDeviceID);
@ -272,14 +319,14 @@ static DWORD WAVE_mciCue(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpPar
dwRet = MMSYSERR_NOERROR; /* assume success */
if ((dwParam & MCI_WAVE_INPUT) && !wmw->fInput) {
dwRet = wodMessage(wDevID, WODM_CLOSE, 0, 0L, 0L);
dwRet = wodMessage(wmw->wWavID, WODM_CLOSE, 0, 0L, 0L);
if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
dwRet = widMessage(wDevID, WIDM_OPEN, 0, (DWORD)&wmw->waveDesc, CALLBACK_NULL);
dwRet = widMessage(wmw->wWavID, WIDM_OPEN, 0, (DWORD)&wmw->waveDesc, CALLBACK_NULL);
wmw->fInput = TRUE;
} else if (wmw->fInput) {
dwRet = widMessage(wDevID, WIDM_CLOSE, 0, 0L, 0L);
dwRet = widMessage(wmw->wWavID, WIDM_CLOSE, 0, 0L, 0L);
if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
dwRet = wodMessage(wDevID, WODM_OPEN, 0, (DWORD)&wmw->waveDesc, CALLBACK_NULL);
dwRet = wodMessage(wmw->wWavID, WODM_OPEN, 0, (DWORD)&wmw->waveDesc, CALLBACK_NULL);
wmw->fInput = FALSE;
}
return (dwRet == MMSYSERR_NOERROR) ? 0 : MCIERR_INTERNAL;
@ -303,9 +350,9 @@ static DWORD WAVE_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpPa
TRACE(mciwave, "wmw->dwStatus=%d\n", wmw->dwStatus);
if (wmw->fInput)
dwRet = widMessage(wDevID, WIDM_STOP, 0, dwFlags, (DWORD)lpParms);
dwRet = widMessage(wmw->wWavID, WIDM_STOP, 0, dwFlags, (DWORD)lpParms);
else
dwRet = wodMessage(wDevID, WODM_STOP, 0, dwFlags, (DWORD)lpParms);
dwRet = wodMessage(wmw->wWavID, WODM_STOP, 0, dwFlags, (DWORD)lpParms);
if (dwFlags & MCI_NOTIFY) {
TRACE(mciwave, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
@ -340,8 +387,8 @@ static DWORD WAVE_mciClose(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpP
mmioClose(wmw->hFile, 0);
wmw->hFile = 0;
}
mmRet = (wmw->fInput) ? widMessage(wDevID, WIDM_CLOSE, 0, 0L, 0L) :
wodMessage(wDevID, WODM_CLOSE, 0, 0L, 0L);
mmRet = (wmw->fInput) ? widMessage(wmw->wWavID, WIDM_CLOSE, 0, 0L, 0L) :
wodMessage(wmw->wWavID, WODM_CLOSE, 0, 0L, 0L);
if (mmRet != MMSYSERR_NOERROR) dwRet = MCIERR_INTERNAL;
}
@ -402,7 +449,8 @@ static DWORD WAVE_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
/* By default the device will be opened for output, the MCI_CUE function is there to
* change from output to input and back
*/
dwRet = wodMessage(wDevID, WODM_OPEN, 0, (DWORD)&wmw->waveDesc, CALLBACK_NULL);
/* FIXME: how to choose between several output channels ? here 0 is forced */
dwRet = wodMessage(0, WODM_OPEN, 0, (DWORD)&wmw->waveDesc, CALLBACK_NULL);
if (dwRet != 0) {
TRACE(mciwave, "Can't open low level audio device %ld\n", dwRet);
return MCIERR_DEVICE_OPEN;
@ -416,6 +464,8 @@ static DWORD WAVE_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
wmw->dwStatus = MCI_MODE_PLAY;
/* FIXME: this doesn't work if wmw->dwPosition != 0 */
/* FIXME: use several WaveHdr for smoother playback */
/* FIXME: use only regular MMSYS functions, not calling directly the driver */
while (wmw->dwStatus != MCI_MODE_STOP) {
wmw->WaveHdr.dwUser = 0L;
wmw->WaveHdr.dwFlags = 0L;
@ -424,12 +474,14 @@ static DWORD WAVE_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
TRACE(mciwave, "mmioRead bufsize=%ld count=%ld\n", bufsize, count);
if (count < 1)
break;
dwRet = wodMessage(wDevID, WODM_PREPARE, 0, (DWORD)&wmw->WaveHdr, sizeof(WAVEHDR));
dwRet = wodMessage(wmw->wWavID, WODM_PREPARE, 0, (DWORD)&wmw->WaveHdr, sizeof(WAVEHDR));
wmw->WaveHdr.dwBufferLength = count;
wmw->WaveHdr.dwBytesRecorded = 0;
/* FIXME */
wmw->WaveHdr.reserved = (DWORD)&wmw->WaveHdr;
TRACE(mciwave, "before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
&wmw->WaveHdr, wmw->WaveHdr.dwBufferLength, wmw->WaveHdr.dwBytesRecorded);
dwRet = wodMessage(wDevID, WODM_WRITE, 0, (DWORD)&wmw->WaveHdr, sizeof(WAVEHDR));
dwRet = wodMessage(wmw->wWavID, WODM_WRITE, 0, (DWORD)&wmw->WaveHdr, sizeof(WAVEHDR));
/* FIXME: should use callback mechanisms from audio driver */
#if 1
while (!(wmw->WaveHdr.dwFlags & WHDR_DONE))
@ -437,7 +489,7 @@ static DWORD WAVE_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
#endif
wmw->dwPosition += count;
TRACE(mciwave, "after WODM_WRITE dwPosition=%lu\n", wmw->dwPosition);
dwRet = wodMessage(wDevID, WODM_UNPREPARE, 0, (DWORD)&wmw->WaveHdr, sizeof(WAVEHDR));
dwRet = wodMessage(wmw->wWavID, WODM_UNPREPARE, 0, (DWORD)&wmw->WaveHdr, sizeof(WAVEHDR));
}
if (wmw->WaveHdr.lpData != NULL) {
@ -446,8 +498,8 @@ static DWORD WAVE_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
wmw->WaveHdr.lpData = NULL;
}
wodMessage(wDevID, WODM_STOP, 0, 0L, 0L);
wodMessage(wDevID, WODM_CLOSE, 0, 0L, 0L);
wodMessage(wmw->wWavID, WODM_STOP, 0, 0L, 0L);
wodMessage(wmw->wWavID, WODM_CLOSE, 0, 0L, 0L);
wmw->dwStatus = MCI_MODE_STOP;
if (lpParms && (dwFlags & MCI_NOTIFY)) {
@ -502,17 +554,17 @@ static DWORD WAVE_mciRecord(UINT16 wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpP
lpWaveHdr->dwUser = 0L;
lpWaveHdr->dwFlags = 0L;
lpWaveHdr->dwLoops = 0L;
dwRet = widMessage(wDevID,WIDM_PREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
dwRet = widMessage(wmw->wWavID,WIDM_PREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
TRACE(mciwave, "after WIDM_PREPARE \n");
while (TRUE) {
lpWaveHdr->dwBytesRecorded = 0;
dwRet = widMessage(wDevID, WIDM_START, 0, 0L, 0L);
dwRet = widMessage(wmw->wWavID, WIDM_START, 0, 0L, 0L);
TRACE(mciwave, "after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
lpWaveHdr, lpWaveHdr->dwBytesRecorded);
if (lpWaveHdr->dwBytesRecorded == 0) break;
}
TRACE(mciwave, "before WIDM_UNPREPARE \n");
dwRet = widMessage(wDevID,WIDM_UNPREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
dwRet = widMessage(wmw->wWavID,WIDM_UNPREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
TRACE(mciwave, "after WIDM_UNPREPARE \n");
if (lpWaveHdr->lpData != NULL) {
GlobalUnlock16(hData);
@ -544,8 +596,8 @@ static DWORD WAVE_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpP
wmw->dwStatus = MCI_MODE_PAUSE;
}
if (wmw->fInput) dwRet = widMessage(wDevID, WIDM_PAUSE, 0, dwFlags, (DWORD)lpParms);
else dwRet = wodMessage(wDevID, WODM_PAUSE, 0, dwFlags, (DWORD)lpParms);
if (wmw->fInput) dwRet = widMessage(wmw->wWavID, WIDM_PAUSE, 0, dwFlags, (DWORD)lpParms);
else dwRet = wodMessage(wmw->wWavID, WODM_PAUSE, 0, dwFlags, (DWORD)lpParms);
return (dwRet == MMSYSERR_NOERROR) ? 0 : MCIERR_INTERNAL;
}
@ -568,8 +620,8 @@ static DWORD WAVE_mciResume(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lp
}
#if 0
if (wmw->fInput) dwRet = widMessage(wDevID, WIDM_PLAY, 0, dwFlags, (DWORD)lpParms);
else dwRet = wodMessage(wDevID, WODM_PLAY, 0, dwFlags, (DWORD)lpParms);
if (wmw->fInput) dwRet = widMessage(wmw->wWavID, WIDM_PLAY, 0, dwFlags, (DWORD)lpParms);
else dwRet = wodMessage(wmw->wWavID, WODM_PLAY, 0, dwFlags, (DWORD)lpParms);
return (dwRet == MMSYSERR_NOERROR) ? 0 : MCIERR_INTERNAL;
#else
return dwRet;
@ -906,7 +958,7 @@ static DWORD WAVE_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS16 lpPar
/**************************************************************************
* MCIWAVE_DriverProc [sample driver]
*/
LONG MCIWAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
LONG MCIWAVE_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2)
{
TRACE(mciwave, "(%08lX, %04X, %08lX, %08lX, %08lX)\n",
@ -915,12 +967,12 @@ LONG MCIWAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg,
switch(wMsg) {
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return 1;
case DRV_CLOSE: return 1;
case DRV_OPEN: return WAVE_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
case DRV_CLOSE: return WAVE_drvClose(dwDevID);
case DRV_ENABLE: return 1;
case DRV_DISABLE: return 1;
case DRV_QUERYCONFIGURE: return 1;
case DRV_CONFIGURE: MessageBoxA(0, "Sample MultiMedia Linux Driver !", "MMLinux Driver", MB_OK); return 1;
case DRV_CONFIGURE: MessageBoxA(0, "Sample MultiMedia Driver !", "OSS Driver", MB_OK); return 1;
case DRV_INSTALL: return DRVCNF_RESTART;
case DRV_REMOVE: return DRVCNF_RESTART;
case MCI_OPEN_DRIVER: return WAVE_mciOpen (dwDevID, dwParam1, (LPMCI_WAVE_OPEN_PARMSA) dwParam2);

View file

@ -8,7 +8,9 @@
/*
* Eric POUECH :
* 98/9 added support for Win32 MCI
* 98/9 added Win32 MCI support
* 99/4 added mmTask and mmThread functions support
* added midiStream support
*/
/* FIXME: I think there are some segmented vs. linear pointer weirdnesses
@ -223,6 +225,8 @@ static BOOL16 WINAPI proc_PlaySound(LPCSTR lpszSoundName, UINT uFlags)
if (count < 1) break;
left -= count;
waveHdr.dwBufferLength = count;
/* FIXME */
waveHdr.reserved = (DWORD)&waveHdr;
/* waveHdr.dwBytesRecorded = count; */
/* FIXME: doesn't expect async ops */
wodMessage(0, WODM_WRITE, 0, (DWORD)&waveHdr, sizeof(WAVEHDR));
@ -434,34 +438,53 @@ BOOL16 WINAPI DriverCallback16(DWORD dwCallBack, UINT16 uFlags, HANDLE16 hDev,
switch (uFlags & DCB_TYPEMASK) {
case DCB_NULL:
TRACE(mmsys, "CALLBACK_NULL !\n");
TRACE(mmsys, "Null !\n");
break;
case DCB_WINDOW:
TRACE(mmsys, "CALLBACK_WINDOW = %04lX handle = %04X!\n",
dwCallBack, hDev);
TRACE(mmsys, "Window(%04lX) handle=%04X!\n", dwCallBack, hDev);
if (!IsWindow(dwCallBack) || USER_HEAP_LIN_ADDR(hDev) == NULL)
return FALSE;
Callout.PostMessageA((HWND16)dwCallBack, wMsg, hDev, dwParam1);
break;
case DCB_TASK:
TRACE(mmsys, "CALLBACK_TASK !\n");
case DCB_TASK: /* aka DCB_THREAD */
TRACE(mmsys, "Task(%04lx) !\n", dwCallBack);
Callout.PostThreadMessageA(dwCallBack, wMsg, hDev, dwParam1);
break;
case DCB_FUNCTION:
TRACE(mmsys, "CALLBACK_FUNCTION !\n");
TRACE(mmsys, "Function (16bit) !\n");
Callbacks->CallDriverCallback((FARPROC16)dwCallBack, hDev, wMsg, dwUser,
dwParam1, dwParam2);
break;
case DCB_EVENT:
TRACE(mmsys, "CALLBACK_EVENT !\n");
SetEvent((HANDLE)dwCallBack);
break;
case DCB_FUNC32:
TRACE(mmsys, "CALLBACK_FUNCTION 32bit !\n");
case DCB_FUNC32: /* This is a Wine only value - AKAIF not used yet by MS */
TRACE(mmsys, "Function (32bit) !\n");
((LPDRVCALLBACK)dwCallBack)(hDev, wMsg, dwUser, dwParam1, dwParam2);
break;
case DCB_EVENT:
TRACE(mmsys, "Event(%08lx) !\n", dwCallBack);
SetEvent((HANDLE)dwCallBack);
break;
case 6: /* I would dub it DCB_MMTHREADSIGNAL */
/* this is an undocumented DCB_ value used for mmThreads
* loword of dwCallBack contains the handle of the lpMMThd block
* which dwSignalCount has to be incremented
*/
{
WINE_MMTHREAD* lpMMThd = (WINE_MMTHREAD*)PTR_SEG_OFF_TO_LIN(LOWORD(dwCallBack), 0);
TRACE(mmsys, "mmThread (%04x, %p) !\n", LOWORD(dwCallBack), lpMMThd);
/* same as mmThreadSignal16 */
InterlockedIncrement(&lpMMThd->dwSignalCount);
SetEvent(lpMMThd->hEvent);
/* some other stuff on lpMMThd->hVxD */
}
break;
#if 0
case 4:
/* this is an undocumented DCB_ value for... I don't know */
break;
#endif
default:
WARN(mmsys, "Unknown callback type\n");
WARN(mmsys, "Unknown callback type %d\n", uFlags & DCB_TYPEMASK);
return FALSE;
}
TRACE(mmsys, "Done\n");
@ -1502,7 +1525,7 @@ DWORD WINAPI mciSendCommandA(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwPar
FIXME(mmsys, "unhandled MCI_ALL_DEVICE_ID\n");
dwRet = MCIERR_CANNOT_USE_ALL;
} else {
dwRet = MCI_SendCommand(wDevID, wMsg, dwParam1, dwParam2);
dwRet = MCI_SendCommandFrom32(wDevID, wMsg, dwParam1, dwParam2);
}
break;
}
@ -1516,7 +1539,8 @@ DWORD WINAPI mciSendCommandA(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwPar
*/
DWORD WINAPI mciSendCommandW(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2)
{
return 0x1; /* !ok */
FIXME(mmsys, "(%08x, %s, %08lx, %08lx): stub\n", wDevID, MCI_CommandToString(wMsg), dwParam1, dwParam2);
return MCIERR_UNSUPPORTED_FUNCTION;
}
/**************************************************************************
@ -1531,9 +1555,13 @@ DWORD WINAPI mciSendCommand16(UINT16 wDevID, UINT16 wMsg, DWORD dwParam1, DWORD
switch (wMsg) {
case MCI_OPEN:
if (MCI_MapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, &dwParam2) >= 0) {
switch (MCI_MapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, &dwParam2)) {
case MCI_MAP_OK:
case MCI_MAP_OKMEM:
dwRet = MCI_Open(dwParam1, (LPMCI_OPEN_PARMSA)dwParam2);
MCI_UnMapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam2);
break;
default: break; /* so that gcc does bark */
}
break;
case MCI_CLOSE:
@ -1542,15 +1570,25 @@ DWORD WINAPI mciSendCommand16(UINT16 wDevID, UINT16 wMsg, DWORD dwParam1, DWORD
dwRet = MCIERR_CANNOT_USE_ALL;
} else if (!MCI_DevIDValid(wDevID)) {
dwRet = MCIERR_INVALID_DEVICE_ID;
} else if (MCI_MapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, &dwParam2) >= 0) {
} else {
switch (MCI_MapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, &dwParam2)) {
case MCI_MAP_OK:
case MCI_MAP_OKMEM:
dwRet = MCI_Close(wDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
MCI_UnMapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam2);
break;
default: break; /* so that gcc does bark */
}
}
break;
case MCI_SYSINFO:
if (MCI_MapMsg16To32A(0, wDevID, &dwParam2) >= 0) {
switch (MCI_MapMsg16To32A(0, wDevID, &dwParam2)) {
case MCI_MAP_OK:
case MCI_MAP_OKMEM:
dwRet = MCI_SysInfo(wDevID, dwParam1, (LPMCI_SYSINFO_PARMSA)dwParam2);
MCI_UnMapMsg16To32A(0, wDevID, dwParam2);
break;
default: break; /* so that gcc does bark */
}
break;
/* FIXME: it seems that MCI_BREAK and MCI_SOUND need the same handling */
@ -1558,38 +1596,10 @@ DWORD WINAPI mciSendCommand16(UINT16 wDevID, UINT16 wMsg, DWORD dwParam1, DWORD
if (wDevID == MCI_ALL_DEVICE_ID) {
FIXME(mmsys, "unhandled MCI_ALL_DEVICE_ID\n");
dwRet = MCIERR_CANNOT_USE_ALL;
} else if (!MCI_DevIDValid(wDevID)) {
dwRet = MCIERR_INVALID_DEVICE_ID;
} else {
int res;
switch (DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv)) {
case WINE_DI_TYPE_16:
dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
break;
case WINE_DI_TYPE_32:
switch (res = MCI_MapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, &dwParam2)) {
case -1:
TRACE(mmsys, "Not handled yet (%s)\n", MCI_CommandToString(wMsg));
dwRet = MCIERR_DRIVER_INTERNAL;
break;
case -2:
TRACE(mmsys, "Problem mapping msg=%s from 16 to 32a\n", MCI_CommandToString(wMsg));
dwRet = MCIERR_OUT_OF_MEMORY;
break;
case 0:
case 1:
dwRet = MCI_SendCommand(wDevID, wMsg, dwParam1, dwParam2);
if (res)
MCI_UnMapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam2);
break;
dwRet = MCI_SendCommandFrom16(wDevID, wMsg, dwParam1, dwParam2);
}
break;
default:
WARN(mmsys, "Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv));
dwRet = MCIERR_DRIVER_INTERNAL;
}
}
}
dwRet = MCI_CleanUp(dwRet, wMsg, dwParam2, FALSE);
TRACE(mmsys, "=> %ld\n", dwRet);
@ -1651,9 +1661,11 @@ UINT WINAPI mciGetDeviceIDW(LPCWSTR lpwstrName)
return ret;
}
/**************************************************************************
* MCI_DefYieldProc [internal]
*/
UINT16 WINAPI MCI_DefYieldProc(UINT16 wDevID, DWORD data)
{
MSG msg;
INT16 ret;
TRACE(mmsys, "(0x%04x, 0x%08lx)\n", wDevID, data);
@ -1663,8 +1675,9 @@ UINT16 WINAPI MCI_DefYieldProc(UINT16 wDevID, DWORD data)
UserYield16();
ret = 0;
} else {
msg.hwnd = HIWORD(data);
MSG msg;
msg.hwnd = HIWORD(data);
while (!PeekMessageA(&msg, HIWORD(data), WM_KEYFIRST, WM_KEYLAST, PM_REMOVE));
ret = 0xFFFF;
}
@ -2028,6 +2041,7 @@ UINT WINAPI midiOutOpen(HMIDIOUT* lphMidiOut, UINT uDeviceID,
UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
{
HMIDIOUT16 hMidiOut;
LPMIDIOPENDESC lpDesc;
UINT16 ret = 0;
BOOL bMapperFlg = FALSE;
@ -2043,7 +2057,7 @@ UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
uDeviceID = 0;
}
lpDesc = MIDI_OutAlloc(lphMidiOut, dwCallback, dwInstance, 0, NULL);
lpDesc = MIDI_OutAlloc(&hMidiOut, dwCallback, dwInstance, 0, NULL);
if (lpDesc == NULL)
return MMSYSERR_NOMEM;
@ -2058,10 +2072,11 @@ UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
}
TRACE(mmsys, "=> wDevID=%u (%d)\n", uDeviceID, ret);
if (ret != MMSYSERR_NOERROR) {
HeapFree(GetProcessHeap(), 0, lpDesc);
USER_HEAP_FREE(hMidiOut);
if (lphMidiOut) *lphMidiOut = 0;
} else {
lpDesc->wDevID = uDeviceID;
if (lphMidiOut) *lphMidiOut = hMidiOut;
}
return ret;
@ -2089,7 +2104,7 @@ UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
dwRet = modMessage(lpDesc->wDevID, MODM_CLOSE, lpDesc->dwInstance, 0L, 0L);
HeapFree(GetProcessHeap(), 0, lpDesc);
USER_HEAP_FREE(hMidiOut);
return dwRet;
}
@ -3070,7 +3085,7 @@ MMRESULT WINAPI midiStreamClose(HMIDISTRM hMidiStrm)
midiStreamStop(hMidiStrm);
HeapFree(GetProcessHeap(), 0, lpMidiStrm);
USER_HEAP_FREE(hMidiStrm);
return midiOutClose(hMidiStrm);
}
@ -4181,8 +4196,7 @@ UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
if (dwFlags & WAVE_FORMAT_QUERY) {
TRACE(mmsys, "End of WAVE_FORMAT_QUERY !\n");
dwRet = waveInClose16(hWaveIn);
}
else if (dwRet != MMSYSERR_NOERROR) {
} else if (dwRet != MMSYSERR_NOERROR) {
USER_HEAP_FREE(hWaveIn);
if (lphWaveIn) *lphWaveIn = 0;
}
@ -4613,6 +4627,8 @@ LRESULT WINAPI DefDriverProc(DWORD dwDriverIdentifier, HDRVR hDrv,
}
}
/*#define USE_MM_TSK_WINE*/
/**************************************************************************
* mmTaskCreate [MMSYSTEM.900]
*
@ -4629,6 +4645,14 @@ HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD d
HINSTANCE16 handle;
TRACE(mmsys, "(%08lx, %p, %08lx);\n", spProc, lphMmTask, dwPmt);
/* This to work requires NE modules to be started with a binary command line
* which is not currently the case. A patch exists but has never been committed.
* A workaround would be to integrate code for mmtask.tsk into Wine, but
* this requires tremendous work (starting with patching tools/build to
* create NE executables (and not only DLLs) for builtins modules.
* EP 99/04/25
*/
FIXME(mmsys, "This is currently broken. It will fail\n");
cmdline = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 0x0d);
cmdline[0] = 0x0d;
@ -4646,7 +4670,11 @@ HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD d
lp->showCmd = PTR_SEG_OFF_TO_SEGPTR(sel2, 0);
lp->reserved = 0;
#ifndef USE_MM_TSK_WINE
handle = LoadModule16("c:\\windows\\system\\mmtask.tsk", lp);
#else
handle = LoadModule16("mmtask.tsk", lp);
#endif
if (handle < 32) {
ret = (handle) ? 1 : 2;
handle = 0;
@ -4666,23 +4694,25 @@ HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD d
return ret;
}
#if 0
#ifdef USE_MM_TSK_WINE
/* C equivalent to mmtask.tsk binary content */
void mmTaskEntryPoint(LPSTR cmdLine, WORD di, WORD si)
void mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
{
int len = cmdLine[0x80];
if (len/2 == 6) {
void (*fpProc)(DWORD) = (void (*)(DWORD))SEG_PTR_TO_LIN(*((DWORD*)(cmdLine + 1)));
void (*fpProc)(DWORD) = (void (*)(DWORD))PTR_SEG_TO_LIN(*((DWORD*)(cmdLine + 1)));
DWORD dwPmt = *((DWORD*)(cmdLine + 5));
#if 0
InitTask16(); /* fixme: pmts / from context ? */
InitApp(di);
#endif
if (SetMessageQueue16(0x40)) {
WaitEvent16(0);
if (HIWORD(fpProc)) {
OldYield16();
StackEnter16();
/* EPP StackEnter16(); */
(fpProc)(dwPmt);
}
}
@ -4731,20 +4761,23 @@ void WINAPI mmTaskYield16(void)
}
}
void WINAPI WINE_mmThreadingEntryPoint(DWORD _pmt);
DWORD WINAPI GetProcessFlags(DWORD);
/**************************************************************************
* mmThreadCreate [MMSYSTEM.1120]
*
* undocumented
* Creates a MM thread, calling fpThreadAddr(dwPmt).
* dwFlags:
* bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
* bit.1 set means to open a VxD for this thread (unsupported)
*/
LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE lpHndl, DWORD dwPmt, DWORD dwFlags)
{
HANDLE16 hndl;
LRESULT ret;
FARPROC16 fp;
FIXME(mmsys, "(%p, %p, %08lx, %08lx): semi-stub!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
TRACE(mmsys, "(%p, %p, %08lx, %08lx)!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
hndl = GlobalAlloc16(sizeof(WINE_MMTHREAD), GMEM_SHARE|GMEM_ZEROINIT);
@ -4753,71 +4786,81 @@ LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE lpHndl, DWORD d
} else {
WINE_MMTHREAD* lpMMThd = (WINE_MMTHREAD*)PTR_SEG_OFF_TO_LIN(hndl, 0);
#if 0
/* force mmtask routines even if mmthread is required */
/* this will work only if the patch about binary cmd line and NE tasks
* is committed
*/
dwFlags |= 1;
#endif
lpMMThd->dwSignature = WINE_MMTHREAD_CREATED;
lpMMThd->dwCounter = 0;
lpMMThd->hThread = 0;
lpMMThd->dwThreadId = 0;
lpMMThd->dwThreadID = 0;
lpMMThd->fpThread = fpThreadAddr;
lpMMThd->dwThreadPmt = dwPmt;
/* FIXME lpMMThd->dwUnknown3; */
lpMMThd->dwSignalCount = 0;
lpMMThd->hEvent = 0;
/* FIXME lpMMThd->dwUnknown5; */
lpMMThd->hVxD = 0;
lpMMThd->dwStatus = 0;
lpMMThd->dwFlags = dwFlags;
lpMMThd->hTask = 0;
/* FIXME: Since main task in Wine is 16 bit (not 32, which is the case for
* win 9x the test below may not work.
*/
#ifdef WINE_MAIN_TASK_IS_32BIT
if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) != 0)
FIXME(mmsys, "(NIY) Oooch: seems to require a real thread, not a 16 bit task !!\n");
#else
if ((dwFlags & 1) == 0)
FIXME(mmsys, "(NIY) Oooch: seems to require a real thread, not a 16 bit task !!\n");
#endif
#if 0
if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8)) {
leavewin16lock();
if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
lpMMThd->hEvent = CreateEventA(0, 0, 1, 0);
if (lpMMThd->dwFlags & 2)
lpMMThd->dwUnknown5 = OpenVxDHandle(lpMMThd->hEvent);
if (!CreateThread(0, 0, proc, SEGPTR(hndl, 0), 4, x)) {
clean-up(event, VxDhandle...);
} else {
lpMMThd->hThread = return from CreateThread;
}
}
else; /* do what's below */
#endif
/* get WINE_mmThreadingEntryPoint()
TRACE(mmsys, "Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd);
if (lpMMThd->dwFlags & 2) {
/* as long as we don't support MM VxD in wine, we don't need
* to care about this flag
*/
/* FIXME(mmsys, "Don't know how to properly open VxD handles\n"); */
/* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
}
lpMMThd->hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)WINE_mmThreadEntryPoint,
(LPVOID)(DWORD)hndl, CREATE_SUSPENDED, &lpMMThd->dwThreadID);
if (lpMMThd->hThread == 0) {
WARN(mmsys, "Couldn't create thread\n");
/* clean-up(VxDhandle...); devicedirectio... */
if (lpMMThd->hEvent != 0)
CloseHandle(lpMMThd->hEvent);
ret = 2;
} else {
TRACE(mmsys, "Got a nice thread hndl=0x%04x id=0x%08lx\n", lpMMThd->hThread, lpMMThd->dwThreadID);
ret = 0;
}
} else {
/* get WINE_mmThreadEntryPoint()
* 2047 is its ordinal in mmsystem.spec
*/
fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (SEGPTR)2047);
FARPROC16 fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (SEGPTR)2047);
TRACE(mmsys, "farproc seg=0x%08lx lin=%p\n", (DWORD)fp, PTR_SEG_TO_LIN(fp));
if (fp == 0 || mmTaskCreate16((DWORD)fp, 0, hndl) != 0) {
GlobalFree16(hndl);
hndl = 0;
ret = 1;
} else {
ret = 0;
while (lpMMThd->dwStatus < 10) {
ret = (fp == 0) ? 2 : mmTaskCreate16((DWORD)fp, 0, hndl);
}
if (ret == 0) {
if (lpMMThd->hThread && !ResumeThread(lpMMThd->hThread))
WARN(mmsys, "Couldn't resume thread\n");
while (lpMMThd->dwStatus != 0x10) { /* test also HIWORD of dwStatus */
UserYield16();
}
}
}
#if 0
if (lpMMThd->hThread)
ResumeThread(lpMMThd->hThread);
#endif
if (ret != 0) {
GlobalFree16(hndl);
hndl = 0;
}
if (lpHndl)
*lpHndl = hndl;
TRACE(mmsys, "ok => %ld\n", ret);
return ret;
}
@ -4832,24 +4875,54 @@ void WINAPI mmThreadSignal16(HANDLE16 hndl)
WINE_MMTHREAD* lpMMThd = (WINE_MMTHREAD*)PTR_SEG_OFF_TO_LIN(hndl, 0);
lpMMThd->dwCounter++;
#if 0
if (lpMMThd->hThread != 0) {
/* FIXME ??
* SYSLEVEL_ReleaseWin16Lock();
* InterlockedIncrement(lpMMThd->hThread [18]);
* SetEvent(lpMMThd->hThread [1C]);
* SYSLEVEL_RestoreWin16Lock();
*/
InterlockedIncrement(&lpMMThd->dwSignalCount);
SetEvent(lpMMThd->hEvent);
} else {
mmTaskSignal16(lpMMThd->hTask);
}
#else
mmTaskSignal16(lpMMThd->hTask);
#endif
lpMMThd->dwCounter--;
}
}
/**************************************************************************
* MMSYSTEM_ThreadBlock [internal]
*/
static void MMSYSTEM_ThreadBlock(WINE_MMTHREAD* lpMMThd)
{
MSG msg;
DWORD ret;
if (lpMMThd->dwThreadID != GetCurrentThreadId())
ERR(mmsys, "Not called by thread itself\n");
for (;;) {
ResetEvent(lpMMThd->hEvent);
if (InterlockedDecrement(&lpMMThd->dwSignalCount) >= 0)
break;
InterlockedIncrement(&lpMMThd->dwSignalCount);
TRACE(mmsys, "S1\n");
ret = MsgWaitForMultipleObjects(1, &lpMMThd->hEvent, FALSE, INFINITE, QS_ALLINPUT);
switch (ret) {
case WAIT_OBJECT_0: /* Event */
TRACE(mmsys, "S2.1\n");
break;
case WAIT_OBJECT_0 + 1: /* Msg */
TRACE(mmsys, "S2.2\n");
if (Callout.PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
Callout.TranslateMessage(&msg);
Callout.DispatchMessageA(&msg);
}
break;
default:
WARN(mmsys, "S2.x unsupported ret val 0x%08lx\n", ret);
}
TRACE(mmsys, "S3\n");
}
}
/**************************************************************************
* mmThreadBlock [MMSYSTEM.1122]
*/
@ -4860,41 +4933,35 @@ void WINAPI mmThreadBlock16(HANDLE16 hndl)
if (hndl) {
WINE_MMTHREAD* lpMMThd = (WINE_MMTHREAD*)PTR_SEG_OFF_TO_LIN(hndl, 0);
#if 0
if (lpMMThd->hThread != 0) {
/* FIXME
* DPMI: lock linear region lpMMThd
*/
SYSLEVEL_ReleaseWin16Lock();
MMSYSTEM_ThreadBlock(lpMMThd);
SYSLEVEL_RestoreWin16Lock();
} else {
mmTaskBlock16(lpMMThd->hTask);
}
#else
mmTaskBlock16(lpMMThd->hTask);
#endif
}
TRACE(mmsys, "done\n");
}
HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl);
BOOL16 WINAPI mmThreadIsValid16(HANDLE16 hndl);
/**************************************************************************
* mmThreadIsCurrent [MMSYSTEM.1123]
*/
BOOL16 WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
{
WINE_MMTHREAD* lpMMThd;
BOOL16 ret = FALSE;
TRACE(mmsys, "(%04x)! stub\n", hndl);
TRACE(mmsys, "(%04x)!\n", hndl);
if (!hndl)
return FALSE;
if (!mmThreadIsValid16(hndl))
return FALSE;
lpMMThd = (WINE_MMTHREAD*)PTR_SEG_OFF_TO_LIN(hndl, 0);
return GetCurrentThreadId() == lpMMThd->dwThreadId;
if (hndl && mmThreadIsValid16(hndl)) {
WINE_MMTHREAD* lpMMThd = (WINE_MMTHREAD*)PTR_SEG_OFF_TO_LIN(hndl, 0);
ret = (GetCurrentThreadId() == lpMMThd->dwThreadID);
/* FIXME: just a test */
SYSLEVEL_ReleaseWin16Lock();
SYSLEVEL_RestoreWin16Lock();
}
TRACE(mmsys, "=> %d\n", ret);
return ret;
}
/**************************************************************************
@ -4902,34 +4969,30 @@ BOOL16 WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
*/
BOOL16 WINAPI mmThreadIsValid16(HANDLE16 hndl)
{
WINE_MMTHREAD* lpMMThd;
BOOL16 ret = TRUE;
BOOL16 ret = FALSE;
TRACE(mmsys, "(%04x)!\n", hndl);
if (!hndl)
return FALSE;
lpMMThd = (WINE_MMTHREAD*)PTR_SEG_OFF_TO_LIN(hndl, 0);
if (hndl) {
WINE_MMTHREAD* lpMMThd = (WINE_MMTHREAD*)PTR_SEG_OFF_TO_LIN(hndl, 0);
if (IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) ||
lpMMThd->dwSignature != WINE_MMTHREAD_CREATED ||
!IsTask16(lpMMThd->hTask))
return FALSE;
#if 0
if (!IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) &&
lpMMThd->dwSignature == WINE_MMTHREAD_CREATED &&
IsTask16(lpMMThd->hTask)) {
lpMMThd->dwCounter++;
if (lpMMThd->hThread != 0) {
DWORD dwThreadRet;
SYSLEVEL_ReleaseWin16Lock();
if (!GetExitCodeThread(lpMMThd->hThread, &locvar) ||
dwThreadRet != STATUS_PENDING) {
ret = FALSE;
if (GetExitCodeThread(lpMMThd->hThread, &dwThreadRet) &&
dwThreadRet == STATUS_PENDING) {
ret = TRUE;
}
SYSLEVEL_RestoreWin16Lock();
} else {
ret = TRUE;
}
lpMMThd->dwCounter--;
#endif
}
}
TRACE(mmsys, "=> %d\n", ret);
return ret;
}
@ -4949,49 +5012,82 @@ HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
return ret;
}
void WINAPI WINE_mmThreadingEntryPoint(DWORD _pmt)
/**************************************************************************
* mmThreadGetTask [internal]
*/
void WINAPI WINE_mmThreadEntryPoint(DWORD _pmt)
{
HANDLE16 hndl = (HANDLE16)_pmt;
WINE_MMTHREAD* lpMMThd = (WINE_MMTHREAD*)PTR_SEG_OFF_TO_LIN(hndl, 0);
CRITICAL_SECTION* cs;
TRACE(mmsys, "(%04x %p)\n", hndl, lpMMThd);
GetpWin16Lock(&cs);
TRACE(mmsys, "lc=%ld rc=%ld ot=%08lx\n", cs->LockCount, cs->RecursionCount, (DWORD)cs->OwningThread);
lpMMThd->hTask = LOWORD(GetCurrentTask());
TRACE(mmsys, "[10-%08x] setting hTask to 0x%08x\n", lpMMThd->hThread, lpMMThd->hTask);
lpMMThd->dwStatus = 0x10;
mmThreadBlock16(hndl);
MMSYSTEM_ThreadBlock(lpMMThd);
TRACE(mmsys, "[20-%08x]\n", lpMMThd->hThread);
lpMMThd->dwStatus = 0x20;
if (lpMMThd->fpThread)
if (lpMMThd->fpThread) {
#if 0
extern DWORD CALLBACK CallTo16_long_l_x(FARPROC16, DWORD);
TRACE(mmsys, "Calling %08lx(%08lx)\n", (DWORD)lpMMThd->fpThread, lpMMThd->dwThreadPmt);$
CallTo16_long_l_x(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
#else
Callbacks->CallWOWCallbackProc(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
lpMMThd->dwStatus = 0x30;
while (lpMMThd->dwCounter) {
Yield16();
#endif
}
lpMMThd->dwStatus = 0x30;
TRACE(mmsys, "[30-%08x]\n", lpMMThd->hThread);
while (lpMMThd->dwCounter) {
Sleep(1);
/* Yield16();*/
}
TRACE(mmsys, "[XX-%08x]\n", lpMMThd->hThread);
/* paranoia */
lpMMThd->dwSignature = WINE_MMTHREAD_DELETED;
/* close lpMMThread->hVxD directio */
if (lpMMThd->hEvent)
CloseHandle(lpMMThd->hEvent);
GlobalFree16(hndl);
TRACE(mmsys, "lc=%ld rc=%ld ot=%08lx\n", cs->LockCount, cs->RecursionCount, (DWORD)cs->OwningThread);
TRACE(mmsys, "done\n");
}
/**************************************************************************
* mmShowMMCPLPropertySheet [MMSYSTEM.1150]
*/
BOOL16 WINAPI mmShowMMCPLPropertySheet16(WORD w1, WORD w2, WORD w3, WORD w4, WORD w5, WORD w6, WORD w7)
BOOL16 WINAPI mmShowMMCPLPropertySheet16(HWND hWnd, char* lpStrDevice,
char* lpStrTab, char* lpStrTitle)
{
FIXME(mmsys, "(%04x %04x %04x %04x %04x %04x %04x): stub!\n", w1, w2, w3, w4, w5, w6, w7);
#if 0
HANDLE hndl;
FARPROC fp;
BOOL16 ret = FALSE;
/* to be tested */
if ((hndl = LoadLibraryA("MMSYS.CPL")) != 0) {
if ((fp = GetProcAddressA(hndl, "ShowMMCPLPropertySheet")) != NULL) {
ret = ((BOOL16 (WINAPI *)(WORD, WORD, WORD, WORD, WORD, WORD, WORD, WORD))fp)(0, w1, w2, w3, w4, w5, w6, w7);
}
FreeLibraryA(hndl);
}
#endif
TRACE(mmsys, "(%04x \"%s\" \"%s\" \"%s\")\n", hWnd, lpStrDevice, lpStrTab, lpStrTitle);
return TRUE;
hndl = LoadLibraryA("MMSYS.CPL");
if (hndl != 0) {
BOOL16 (WINAPI *fp)(HWND, LPSTR, LPSTR, LPSTR);
fp = (BOOL16 (WINAPI *)(HWND, LPSTR, LPSTR, LPSTR))GetProcAddress(hndl, "ShowMMCPLPropertySheet");
if (fp != NULL) {
/* FIXME: wine hangs and/or seg faults in this call,
* after the window is correctly displayed
*/
TRACE(mmsys, "Ready to go ThreadID=%08lx\n", GetCurrentThreadId());
SYSLEVEL_ReleaseWin16Lock();
ret = (fp)(hWnd, lpStrDevice, lpStrTab, lpStrTitle);
SYSLEVEL_RestoreWin16Lock();
}
FreeLibrary(hndl);
}
return ret;
}
/**************************************************************************

View file

@ -16,6 +16,11 @@ imagehlp.c
imm32.c
kernel32.c
lz32.c
mcianim.c
mciavi.c
mcicda.c
mciseq.c
mciwave.c
mpr.c
msacm32.c
msnet32.c

View file

@ -23,6 +23,11 @@ DLLS = \
kernel32.spec \
lz32.spec \
mpr.spec \
mcianim.spec \
mciavi.spec \
mcicda.spec \
mciseq.spec \
mciwave.spec \
msacm32.spec \
msnet32.spec \
msvfw32.spec \

View file

@ -63,6 +63,11 @@ extern const BUILTIN32_DESCRIPTOR IMM32_Descriptor;
extern const BUILTIN32_DESCRIPTOR KERNEL32_Descriptor;
extern const BUILTIN32_DESCRIPTOR LZ32_Descriptor;
extern const BUILTIN32_DESCRIPTOR MPR_Descriptor;
extern const BUILTIN32_DESCRIPTOR MCIAVI_Descriptor;
extern const BUILTIN32_DESCRIPTOR MCIANIM_Descriptor;
extern const BUILTIN32_DESCRIPTOR MCICDA_Descriptor;
extern const BUILTIN32_DESCRIPTOR MCISEQ_Descriptor;
extern const BUILTIN32_DESCRIPTOR MCIWAVE_Descriptor;
extern const BUILTIN32_DESCRIPTOR MSACM32_Descriptor;
extern const BUILTIN32_DESCRIPTOR MSNET32_Descriptor;
extern const BUILTIN32_DESCRIPTOR MSVFW32_Descriptor;
@ -108,6 +113,11 @@ static BUILTIN32_DLL BuiltinDLLs[] =
{ &IMM32_Descriptor, 0, NULL },
{ &KERNEL32_Descriptor, 0, NULL },
{ &LZ32_Descriptor, 0, NULL },
{ &MCIANIM_Descriptor, 0, NULL },
{ &MCIAVI_Descriptor, 0, NULL },
{ &MCICDA_Descriptor, 0, NULL },
{ &MCISEQ_Descriptor, 0, NULL },
{ &MCIWAVE_Descriptor, 0, NULL },
{ &MPR_Descriptor, 0, NULL },
{ &MSACM32_Descriptor, 0, NULL },
{ &MSNET32_Descriptor, 0, NULL },

5
relay32/mcianim.spec Normal file
View file

@ -0,0 +1,5 @@
name mcianim
file mcianim.drv
type win32
1 stdcall DriverProc(long long long long long) MCIANIM_DriverProc

5
relay32/mciavi.spec Normal file
View file

@ -0,0 +1,5 @@
name mciavi
file mciavi.drv
type win32
1 stdcall DriverProc(long long long long long) MCIAVI_DriverProc

5
relay32/mcicda.spec Normal file
View file

@ -0,0 +1,5 @@
name mcicda
file mcicda.drv
type win32
1 stdcall DriverProc(long long long long long) MCICDAUDIO_DriverProc

5
relay32/mciseq.spec Normal file
View file

@ -0,0 +1,5 @@
name mciseq
file mciseq.drv
type win32
1 stdcall DriverProc(long long long long long) MCIMIDI_DriverProc

5
relay32/mciwave.spec Normal file
View file

@ -0,0 +1,5 @@
name mciwave
file mciwave.drv
type win32
1 stdcall DriverProc(long long long long long) MCIWAVE_DriverProc

View file

@ -1,5 +1,6 @@
name winmm
type win32
init WINMM_LibMain
1 stdcall PlaySoundA(ptr long long) PlaySoundA
2 stdcall WINMM_2(ptr long long) PlaySoundA

View file

@ -88,6 +88,9 @@ mpr, winspool = builtin, native
ddraw, dinput, dsound = builtin, native
winmm, mmsystem = builtin
msvideo, msvfw32 = builtin, native
mcicda.drv, mciseq.drv = builtin, native
mciwave.drv = builtin, native
mciavi.drv, mcianim.drv = native, builtin
w32skrnl = builtin
wnaspi32, wow32 = builtin
system, display, wprocs = builtin