*Major soundcard support update*

ReactOS remains silent for now, but for anyone wishing to further work on the Sound Blaster driver and/or mmdrv.dll, this should help immensely :)

- Imported midimap from WINE
- Imported wavemap from WINE
- Imported msacm from WINE (32-bit only)
- Minor changes to mpu401
- Basic IRP_MJ_WRITE dispatch routine for sndblst.sys (receives buffers, does nothing else.)
- Added various WINE headers to include\wine

svn path=/trunk/; revision=8620
This commit is contained in:
Andrew Greenwood 2004-03-10 15:22:45 +00:00
parent 69208dc611
commit a306af21c2
63 changed files with 8517 additions and 31 deletions

View file

@ -31,8 +31,8 @@ HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList","ProfilesDirecto
;HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList","AllUsersProfile",0x00000000,"All Users.REACTOS"
;HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList","DefaultUserProfile",0x00000000,"Default User.REACTOS"
;HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Shell",0x00020000,"%SystemRoot%\system32\cmd.exe"
HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Shell",0x00020000,"%SystemRoot%\explorer.exe"
HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Shell",0x00020000,"%SystemRoot%\system32\cmd.exe"
;HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Shell",0x00020000,"%SystemRoot%\explorer.exe"
HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","StartServices",0x00010001,0x00000001
HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","StartGUI",0x00010001,0x00000000
HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Userinit",0x00020000,"%SystemRoot%\system32\userinit.exe"

View file

@ -238,6 +238,59 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Keyboard","ImagePath",0x00020000,"system
HKLM,"SYSTEM\CurrentControlSet\Services\Keyboard","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\Keyboard","Type",0x00010001,0x00000001
; SB16 driver
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","Group",0x00000000,"Base"
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","ServiceType",0x00010001,0x00000001
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","Type",0x00010001,0x00000001
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","Start",0x00010001,0x00000001
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","ErrorControl",0x00010001,0x00000001
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","ImagePath",0x00020000,"system32\drivers\sb16snd.sys"
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd\Parameters\Device0","DmaChannel",0x00010001,0x00000001
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd\Parameters\Device0","DmaChannel16",0x00010001,0x00000005
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd\Parameters\Device0","Port",0x00010001,0x00000220
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd\Parameters\Device0","Interrupt",0x00010001,0x00000005
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd\Parameters\Device0","DSP Version",0x00010001,0x00000401
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd\Parameters\Device0\Devices","SBWaveIn0",0x00010001,0x00000001
;HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd\Parameters\Device0\Devices","SBWaveOut0",0x00010001,0x00000002
HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","Group",0x00000000,"Base"
HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","ServiceType",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","Type",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","ErrorControl",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\sb16snd","ImagePath",0x00020000,"system32\drivers\sndblst.sys"
HKLM,"SYSTEM\CurrentControlSet\Services\es137140","Group",0x00000000,"Base"
HKLM,"SYSTEM\CurrentControlSet\Services\es137140","ServiceType",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\es137140","Type",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\es137140","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\es137140","ErrorControl",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\es137140","ImagePath",0x00020000,"system32\drivers\es137140.sys"
HKLM,"SYSTEM\CurrentControlSet\Services\es137140","DisplayName",0x00020000,"ENSONIQ AudioPCI"
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0","Configuration Error",0x00010001,0xffffffff
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0","Joystick",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0","Port",0x00010001,0x00001080
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0","Interrupt",0x00010001,0x00000044
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0","RequestedSystemResources",0x00000001,88,00,00,00,05,00,00,00,00,00,00,00,11,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,01,00,01,00,03,00,00,00,00,02,03,00,00,00,00,00,44,00,00,00,44,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,01,01,00,01,00,00,00,40,00,00,00,40,00,00,00,80,10,00,00,00,00,00,00,bf,10,00,00,00,00,00,00,08,01,01,00,01,00,00,00,40,00,00,00,40,00,00,00,80,10,00,00,00,00,00,00,bf,10,00,00,00,00,00,00
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0\Devices","EAPWaveIn0",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0\Devices","EAPWaveOut0",0x00010001,0x00000002
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0\Devices","EAPMidiIn0",0x00010001,0x00000003
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0\Devices","EAPMidiOut0",0x00010001,0x00000004
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0\Devices","EAPMidiOut1",0x00010001,0x00000004
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0\Devices","EAPMixer0",0x00010001,0x00000006
HKLM,"SYSTEM\CurrentControlSet\Services\es137140\Parameters\Device0\Devices","EAPAux0",0x00010001,0x00000005
; MPU-401 MIDI driver
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Group",0x00000000,"Base"
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ServiceType",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Type",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ErrorControl",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ImagePath",0x00020000,"system32\drivers\mpu401.sys"
; Mouse driver
HKLM,"SYSTEM\CurrentControlSet\Services\Mouse","ErrorControl",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\Mouse","Group",0x00000000,"Pointer Class"

View file

@ -150,12 +150,12 @@ MPU401Create(PDEVICE_OBJECT DeviceObject,
// Play a note to say we're alive:
/* WaitToSend(MPU401_PORT);
WaitToSend(MPU401_PORT);
MPU401_WRITE_DATA(MPU401_PORT, 0x90);
WaitToSend(MPU401_PORT);
MPU401_WRITE_DATA(MPU401_PORT, 0x50);
WaitToSend(MPU401_PORT);
MPU401_WRITE_DATA(MPU401_PORT, 0x7f);*/
MPU401_WRITE_DATA(MPU401_PORT, 0x7f);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
@ -248,6 +248,9 @@ MPU401DeviceControl(PDEVICE_OBJECT DeviceObject,
DeviceExtension = DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
DPRINT("Control code %d [0x%x]\n", Stack->Parameters.DeviceIoControl.IoControlCode,
Stack->Parameters.DeviceIoControl.IoControlCode);
switch(Stack->Parameters.DeviceIoControl.IoControlCode)
{

View file

@ -12,6 +12,12 @@
#ifndef __INCLUDES_MPU401_H__
#define __INCLUDES_MPU401_H__
#include <windows.h>
//#include <mmsystem.h>
//#include <mmddk.h>
//#include <winioctl.h>
#include "../../../lib/mmdrv/mmdef.h"
#define DEFAULT_PORT 0x330
#define DEFAULT_IRQ 9
@ -26,6 +32,7 @@
#define MPU401_TIMEOUT 10000
/* OBSOLETE - see mmdef.h instead:
#define IOCTL_SOUND_BASE FILE_DEVICE_SOUND
// wave base 0
#define IOCTL_MIDI_BASE 0x0080
@ -39,7 +46,7 @@
#define IOCTL_MIDI_RECORD CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0007, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_CACHE_PATCHES CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0008, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_CACHE_DRUM_PATCHES CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0009, METHOD_BUFFERED, FILE_WRITE_ACCESS)
*/
// The MPU-401 has 2 ports, usually 0x330 and 0x331, which are known as
// "data" and "status/command", respectively. These macros deal with

View file

@ -35,8 +35,8 @@ NTSTATUS InitDevice(
// PDEVICE_INSTANCE Instance = Context;
PDEVICE_OBJECT DeviceObject; // = Context;
PDEVICE_EXTENSION Parameters; // = DeviceObject->DeviceExtension;
UNICODE_STRING DeviceName = ROS_STRING_INITIALIZER(L"\\Device\\WaveOut"); // CHANGE THESE!
UNICODE_STRING SymlinkName = ROS_STRING_INITIALIZER(L"\\??\\WaveOut");
UNICODE_STRING DeviceName = ROS_STRING_INITIALIZER(L"\\Device\\WaveOut0"); // CHANGE THESE?
UNICODE_STRING SymlinkName = ROS_STRING_INITIALIZER(L"\\??\\WaveOut0");
// CONFIG Config;
RTL_QUERY_REGISTRY_TABLE Table[2];
@ -140,10 +140,10 @@ NTSTATUS InitDevice(
if (! CreateDMA(DeviceObject))
DPRINT("FAILURE!\n");
// TEMPORARY TESTING STUFF:
// TEMPORARY TESTING STUFF: should be in BlasterCreate
EnableSpeaker(Parameters->Port, TRUE);
SetOutputSampleRate(Parameters->Port, 11025);
BeginPlayback(Parameters->Port, 8, 1, Parameters->BufferSize);
SetOutputSampleRate(Parameters->Port, 2205);
BeginPlayback(Parameters->Port, 16, 2, Parameters->BufferSize);
DeviceCount ++;
@ -178,9 +178,14 @@ BlasterCreate(PDEVICE_OBJECT DeviceObject,
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
DPRINT("IoCompleteRequest()\n");
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
DPRINT("BlasterCreate() completed\n");
return(STATUS_SUCCESS);
}
@ -247,6 +252,39 @@ BlasterCleanup(PDEVICE_OBJECT DeviceObject,
}
static NTSTATUS STDCALL
BlasterWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION Stack;
PDEVICE_EXTENSION DeviceExtension;
UINT ByteCount;
PBYTE Data;
DPRINT("BlasterWrite() called!\n");
DeviceExtension = DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
DPRINT("%d bytes\n", Stack->Parameters.Write.Length);
Data = (PBYTE) Irp->AssociatedIrp.SystemBuffer;
for (ByteCount = 0; ByteCount < Stack->Parameters.Write.Length; ByteCount ++)
{
// DPRINT("0x%x ", Data[ByteCount]);
// MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]);
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
static NTSTATUS STDCALL
BlasterDeviceControl(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
@ -392,7 +430,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
// Doesn't support multiple instances (yet ...)
NTSTATUS Status;
DPRINT("Sound Blaster Device Driver 0.0.1\n");
DPRINT("Sound Blaster Device Driver 0.0.2\n");
// Instance.DriverObject = DriverObject;
// previous instance = NULL...
@ -404,6 +442,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
DriverObject->MajorFunction[IRP_MJ_CLOSE] = BlasterClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BlasterCleanup;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BlasterDeviceControl;
DriverObject->MajorFunction[IRP_MJ_WRITE] = BlasterWrite;
DriverObject->DriverUnload = BlasterUnload;
// Major hack to just get this damn thing working:

View file

@ -165,6 +165,7 @@ extern "C" {
#define MF_USECHECKBITMAPS (0x200L)
#define MF_RIGHTJUSTIFY MF_HELP
/* Ternary Raster Operations - BitBlt */
#define BLACKNESS 0x00000042
#define NOTSRCERASE 0x001100A6
@ -254,6 +255,13 @@ extern "C" {
#define DISP_CHANGE_NOTUPDATED (-3)
#define DISP_CHANGE_BADPARAM (-5)
/* ChangeMenu */
#define MF_INSERT 0
#define MF_CHANGE 128
#define MF_APPEND 256
#define MF_DELETE 512
#define MF_REMOVE 4096
/* ChangeServiceConfig */
#define SERVICE_NO_CHANGE (-1)
#define SERVICE_KERNEL_DRIVER (1)

View file

@ -0,0 +1,408 @@
/*
* Declarations for MultiMedia-REGistration
*
* Copyright (C) 1999 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_MMREG_H
#define __WINE_MMREG_H
/***********************************************************************
* Defines/Enums
*/
#ifndef _ACM_WAVEFILTER
#define _ACM_WAVEFILTER
#define WAVE_FILTER_UNKNOWN 0x0000
#define WAVE_FILTER_DEVELOPMENT 0xFFFF
typedef struct _WAVEFILTER {
DWORD cbStruct;
DWORD dwFilterTag;
DWORD fdwFilter;
DWORD dwReserved[5];
} WAVEFILTER, *PWAVEFILTER, *NPWAVEFILTER, *LPWAVEFILTER;
#endif /* _ACM_WAVEFILTER */
#ifndef WAVE_FILTER_VOLUME
#define WAVE_FILTER_VOLUME 0x0001
typedef struct _WAVEFILTER_VOLUME {
WAVEFILTER wfltr;
DWORD dwVolume;
} VOLUMEWAVEFILTER, *PVOLUMEWAVEFILTER, *NPVOLUMEWAVEFILTER, *LPVOLUMEWAVEFILTER;
#endif /* WAVE_FILTER_VOLUME */
#ifndef WAVE_FILTER_ECHO
#define WAVE_FILTER_ECHO 0x0002
typedef struct WAVEFILTER_ECHO {
WAVEFILTER wfltr;
DWORD dwVolume;
DWORD dwDelay;
} ECHOWAVEFILTER, *PECHOWAVEFILTER, *NPECHOWAVEFILTER, *LPECHOWAVEFILTER;
#endif /* WAVEFILTER_ECHO */
#ifndef _WAVEFORMATEX_
#define _WAVEFORMATEX_
typedef struct _WAVEFORMATEX {
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
} WAVEFORMATEX, *PWAVEFORMATEX, *NPWAVEFORMATEX, *LPWAVEFORMATEX;
#endif /* _WAVEFORMATEX_ */
/* WAVE form wFormatTag IDs */
#define WAVE_FORMAT_UNKNOWN 0x0000 /* Microsoft Corporation */
#define WAVE_FORMAT_ADPCM 0x0002 /* Microsoft Corporation */
#define WAVE_FORMAT_IBM_CVSD 0x0005 /* IBM Corporation */
#define WAVE_FORMAT_ALAW 0x0006 /* Microsoft Corporation */
#define WAVE_FORMAT_MULAW 0x0007 /* Microsoft Corporation */
#define WAVE_FORMAT_OKI_ADPCM 0x0010 /* OKI */
#define WAVE_FORMAT_DVI_ADPCM 0x0011 /* Intel Corporation */
#define WAVE_FORMAT_IMA_ADPCM (WAVE_FORMAT_DVI_ADPCM) /* Intel Corporation */
#define WAVE_FORMAT_MEDIASPACE_ADPCM 0x0012 /* Videologic */
#define WAVE_FORMAT_SIERRA_ADPCM 0x0013 /* Sierra Semiconductor Corp */
#define WAVE_FORMAT_G723_ADPCM 0x0014 /* Antex Electronics Corporation */
#define WAVE_FORMAT_DIGISTD 0x0015 /* DSP Solutions, Inc. */
#define WAVE_FORMAT_DIGIFIX 0x0016 /* DSP Solutions, Inc. */
#define WAVE_FORMAT_DIALOGIC_OKI_ADPCM 0x0017 /* Dialogic Corporation */
#define WAVE_FORMAT_YAMAHA_ADPCM 0x0020 /* Yamaha Corporation of America */
#define WAVE_FORMAT_SONARC 0x0021 /* Speech Compression */
#define WAVE_FORMAT_DSPGROUP_TRUESPEECH 0x0022 /* DSP Group, Inc */
#define WAVE_FORMAT_ECHOSC1 0x0023 /* Echo Speech Corporation */
#define WAVE_FORMAT_AUDIOFILE_AF36 0x0024 /* */
#define WAVE_FORMAT_APTX 0x0025 /* Audio Processing Technology */
#define WAVE_FORMAT_AUDIOFILE_AF10 0x0026 /* */
#define WAVE_FORMAT_DOLBY_AC2 0x0030 /* Dolby Laboratories */
#define WAVE_FORMAT_GSM610 0x0031 /* Microsoft Corporation */
#define WAVE_FORMAT_ANTEX_ADPCME 0x0033 /* Antex Electronics Corporation */
#define WAVE_FORMAT_CONTROL_RES_VQLPC 0x0034 /* Control Resources Limited */
#define WAVE_FORMAT_DIGIREAL 0x0035 /* DSP Solutions, Inc. */
#define WAVE_FORMAT_DIGIADPCM 0x0036 /* DSP Solutions, Inc. */
#define WAVE_FORMAT_CONTROL_RES_CR10 0x0037 /* Control Resources Limited */
#define WAVE_FORMAT_NMS_VBXADPCM 0x0038 /* Natural MicroSystems */
#define WAVE_FORMAT_G721_ADPCM 0x0040 /* Antex Electronics Corporation */
#define WAVE_FORMAT_MPEG 0x0050 /* Microsoft Corporation */
#define WAVE_FORMAT_MPEGLAYER3 0x0055
#define WAVE_FORMAT_CREATIVE_ADPCM 0x0200 /* Creative Labs, Inc */
#define WAVE_FORMAT_CREATIVE_FASTSPEECH8 0x0202 /* Creative Labs, Inc */
#define WAVE_FORMAT_CREATIVE_FASTSPEECH10 0x0203 /* Creative Labs, Inc */
#define WAVE_FORMAT_FM_TOWNS_SND 0x0300 /* Fujitsu Corp. */
#define WAVE_FORMAT_OLIGSM 0x1000 /* Ing C. Olivetti & C., S.p.A. */
#define WAVE_FORMAT_OLIADPCM 0x1001 /* Ing C. Olivetti & C., S.p.A. */
#define WAVE_FORMAT_OLICELP 0x1002 /* Ing C. Olivetti & C., S.p.A. */
#define WAVE_FORMAT_OLISBC 0x1003 /* Ing C. Olivetti & C., S.p.A. */
#define WAVE_FORMAT_OLIOPR 0x1004 /* Ing C. Olivetti & C., S.p.A. */
#define WAVE_FORMAT_DEVELOPMENT (0xFFFF)
typedef struct adpcmcoef_tag {
short iCoef1;
short iCoef2;
} ADPCMCOEFSET;
typedef ADPCMCOEFSET *PADPCMCOEFSET,
*NPADPCMCOEFSET, *LPADPCMCOEFSET;
typedef struct adpcmwaveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
WORD wNumCoef;
/* FIXME: this should be aCoef[0] */
ADPCMCOEFSET aCoef[1];
} ADPCMWAVEFORMAT;
typedef ADPCMWAVEFORMAT *PADPCMWAVEFORMAT,
*NPADPCMWAVEFORMAT, *LPADPCMWAVEFORMAT;
typedef struct dvi_adpcmwaveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
} DVIADPCMWAVEFORMAT;
typedef DVIADPCMWAVEFORMAT *PDVIADPCMWAVEFORMAT,
*NPDVIADPCMWAVEFORMAT, *LPDVIADPCMWAVEFORMAT;
typedef struct ima_adpcmwaveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
} IMAADPCMWAVEFORMAT;
typedef IMAADPCMWAVEFORMAT *PIMAADPCMWAVEFORMAT, *NPIMAADPCMWAVEFORMAT,
*LPIMAADPCMWAVEFORMAT;
typedef struct mediaspace_adpcmwaveformat_tag {
WAVEFORMATEX wfx;
WORD wRevision;
} MEDIASPACEADPCMWAVEFORMAT;
typedef MEDIASPACEADPCMWAVEFORMAT *PMEDIASPACEADPCMWAVEFORMAT,
*NPMEDIASPACEADPCMWAVEFORMAT, *LPMEDIASPACEADPCMWAVEFORMAT;
typedef struct sierra_adpcmwaveformat_tag {
WAVEFORMATEX wfx;
WORD wRevision;
} SIERRAADPCMWAVEFORMAT;
typedef SIERRAADPCMWAVEFORMAT *PSIERRAADPCMWAVEFORMAT,
*NPSIERRAADPCMWAVEFORMAT, *LPSIERRAADPCMWAVEFORMAT;
typedef struct g723_adpcmwaveformat_tag {
WAVEFORMATEX wfx;
WORD cbExtraSize;
WORD nAuxBlockSize;
} G723_ADPCMWAVEFORMAT;
typedef G723_ADPCMWAVEFORMAT *PG723_ADPCMWAVEFORMAT,
*NPG723_ADPCMWAVEFORMAT, *LPG723_ADPCMWAVEFORMAT;
typedef struct digistdwaveformat_tag {
WAVEFORMATEX wfx;
} DIGISTDWAVEFORMAT;
typedef DIGISTDWAVEFORMAT *PDIGISTDWAVEFORMAT,
*NPDIGISTDWAVEFORMAT, *LPDIGISTDWAVEFORMAT;
typedef struct digifixwaveformat_tag {
WAVEFORMATEX wfx;
} DIGIFIXWAVEFORMAT;
typedef DIGIFIXWAVEFORMAT *PDIGIFIXWAVEFORMAT,
*NPDIGIFIXWAVEFORMAT, *LPDIGIFIXWAVEFORMAT;
typedef struct creative_fastspeechformat_tag {
WAVEFORMATEX ewf;
} DIALOGICOKIADPCMWAVEFORMAT;
typedef DIALOGICOKIADPCMWAVEFORMAT *PDIALOGICOKIADPCMWAVEFORMAT,
*NPDIALOGICOKIADPCMWAVEFORMAT, *LPDIALOGICOKIADPCMWAVEFORMAT;
typedef struct yamaha_adpmcwaveformat_tag {
WAVEFORMATEX wfx;
} YAMAHA_ADPCMWAVEFORMAT;
typedef YAMAHA_ADPCMWAVEFORMAT *PYAMAHA_ADPCMWAVEFORMAT,
*NPYAMAHA_ADPCMWAVEFORMAT, *LPYAMAHA_ADPCMWAVEFORMAT;
typedef struct sonarcwaveformat_tag {
WAVEFORMATEX wfx;
WORD wCompType;
} SONARCWAVEFORMAT;
typedef SONARCWAVEFORMAT *PSONARCWAVEFORMAT,
*NPSONARCWAVEFORMAT,*LPSONARCWAVEFORMAT;
typedef struct truespeechwaveformat_tag {
WAVEFORMATEX wfx;
WORD wRevision;
WORD nSamplesPerBlock;
BYTE abReserved[28];
} TRUESPEECHWAVEFORMAT;
typedef TRUESPEECHWAVEFORMAT *PTRUESPEECHWAVEFORMAT,
*NPTRUESPEECHWAVEFORMAT, *LPTRUESPEECHWAVEFORMAT;
typedef struct echosc1waveformat_tag {
WAVEFORMATEX wfx;
} ECHOSC1WAVEFORMAT;
typedef ECHOSC1WAVEFORMAT *PECHOSC1WAVEFORMAT,
*NPECHOSC1WAVEFORMAT, *LPECHOSC1WAVEFORMAT;
typedef struct audiofile_af36waveformat_tag {
WAVEFORMATEX wfx;
} AUDIOFILE_AF36WAVEFORMAT;
typedef AUDIOFILE_AF36WAVEFORMAT *PAUDIOFILE_AF36WAVEFORMAT,
*NPAUDIOFILE_AF36WAVEFORMAT, *LPAUDIOFILE_AF36WAVEFORMAT;
typedef struct aptxwaveformat_tag {
WAVEFORMATEX wfx;
} APTXWAVEFORMAT;
typedef APTXWAVEFORMAT *PAPTXWAVEFORMAT,
*NPAPTXWAVEFORMAT, *LPAPTXWAVEFORMAT;
typedef struct audiofile_af10waveformat_tag {
WAVEFORMATEX wfx;
} AUDIOFILE_AF10WAVEFORMAT;
typedef AUDIOFILE_AF10WAVEFORMAT *PAUDIOFILE_AF10WAVEFORMAT,
*NPAUDIOFILE_AF10WAVEFORMAT, *LPAUDIOFILE_AF10WAVEFORMAT;
typedef struct dolbyac2waveformat_tag {
WAVEFORMATEX wfx;
WORD nAuxBitsCode;
} DOLBYAC2WAVEFORMAT;
typedef struct gsm610waveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
} GSM610WAVEFORMAT;
typedef GSM610WAVEFORMAT *PGSM610WAVEFORMAT,
*NPGSM610WAVEFORMAT, *LPGSM610WAVEFORMAT;
typedef struct adpcmewaveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
} ADPCMEWAVEFORMAT;
typedef ADPCMEWAVEFORMAT *PADPCMEWAVEFORMAT,
*NPADPCMEWAVEFORMAT, *LPADPCMEWAVEFORMAT;
typedef struct contres_vqlpcwaveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
} CONTRESVQLPCWAVEFORMAT;
typedef CONTRESVQLPCWAVEFORMAT *PCONTRESVQLPCWAVEFORMAT,
*NPCONTRESVQLPCWAVEFORMAT, *LPCONTRESVQLPCWAVEFORMAT;
typedef struct digirealwaveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
} DIGIREALWAVEFORMAT;
typedef DIGIREALWAVEFORMAT *PDIGIREALWAVEFORMAT,
*NPDIGIREALWAVEFORMAT, *LPDIGIREALWAVEFORMAT;
typedef struct digiadpcmmwaveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
} DIGIADPCMWAVEFORMAT;
typedef DIGIADPCMWAVEFORMAT *PDIGIADPCMWAVEFORMAT,
*NPDIGIADPCMWAVEFORMAT, *LPDIGIADPCMWAVEFORMAT;
typedef struct contres_cr10waveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
} CONTRESCR10WAVEFORMAT;
typedef CONTRESCR10WAVEFORMAT *PCONTRESCR10WAVEFORMAT,
*NPCONTRESCR10WAVEFORMAT, *LPCONTRESCR10WAVEFORMAT;
typedef struct nms_vbxadpcmmwaveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
} NMS_VBXADPCMWAVEFORMAT;
typedef NMS_VBXADPCMWAVEFORMAT *PNMS_VBXADPCMWAVEFORMAT,
*NPNMS_VBXADPCMWAVEFORMAT, *LPNMS_VBXADPCMWAVEFORMAT;
typedef struct g721_adpcmwaveformat_tag {
WAVEFORMATEX wfx;
WORD nAuxBlockSize;
} G721_ADPCMWAVEFORMAT;
typedef G721_ADPCMWAVEFORMAT *PG721_ADPCMWAVEFORMAT,
*NG721_ADPCMWAVEFORMAT, *LPG721_ADPCMWAVEFORMAT;
typedef struct creative_adpcmwaveformat_tag {
WAVEFORMATEX wfx;
WORD wRevision;
} CREATIVEADPCMWAVEFORMAT;
typedef CREATIVEADPCMWAVEFORMAT *PCREATIVEADPCMWAVEFORMAT,
*NPCREATIVEADPCMWAVEFORMAT, *LPCREATIVEADPCMWAVEFORMAT;
typedef struct creative_fastspeech8format_tag {
WAVEFORMATEX wfx;
WORD wRevision;
} CREATIVEFASTSPEECH8WAVEFORMAT;
typedef CREATIVEFASTSPEECH8WAVEFORMAT *PCREATIVEFASTSPEECH8WAVEFORMAT,
*NPCREATIVEFASTSPEECH8WAVEFORMAT, *LPCREATIVEFASTSPEECH8WAVEFORMAT;
typedef struct creative_fastspeech10format_tag {
WAVEFORMATEX wfx;
WORD wRevision;
} CREATIVEFASTSPEECH10WAVEFORMAT;
typedef CREATIVEFASTSPEECH10WAVEFORMAT *PCREATIVEFASTSPEECH10WAVEFORMAT,
*NPCREATIVEFASTSPEECH10WAVEFORMAT, *LPCREATIVEFASTSPEECH10WAVEFORMAT;
typedef struct fmtowns_snd_waveformat_tag {
WAVEFORMATEX wfx;
WORD wRevision;
} FMTOWNS_SND_WAVEFORMAT;
typedef FMTOWNS_SND_WAVEFORMAT *PFMTOWNS_SND_WAVEFORMAT,
*NPFMTOWNS_SND_WAVEFORMAT, *LPFMTOWNS_SND_WAVEFORMAT;
typedef struct oligsmwaveformat_tag {
WAVEFORMATEX wfx;
} OLIGSMWAVEFORMAT;
typedef OLIGSMWAVEFORMAT *POLIGSMWAVEFORMAT,
*NPOLIGSMWAVEFORMAT, *LPOLIGSMWAVEFORMAT;
typedef struct oliadpcmwaveformat_tag {
WAVEFORMATEX wfx;
} OLIADPCMWAVEFORMAT;
typedef OLIADPCMWAVEFORMAT *POLIADPCMWAVEFORMAT,
*NPOLIADPCMWAVEFORMAT, *LPOLIADPCMWAVEFORMAT;
typedef struct olicelpwaveformat_tag {
WAVEFORMATEX wfx;
} OLICELPWAVEFORMAT;
typedef OLICELPWAVEFORMAT *POLICELPWAVEFORMAT,
*NPOLICELPWAVEFORMAT, *LPOLICELPWAVEFORMAT;
typedef struct olisbcwaveformat_tag {
WAVEFORMATEX wfx;
} OLISBCWAVEFORMAT;
typedef OLISBCWAVEFORMAT *POLISBCWAVEFORMAT,
*NPOLISBCWAVEFORMAT, *LPOLISBCWAVEFORMAT;
typedef struct olioprwaveformat_tag {
WAVEFORMATEX wfx;
} OLIOPRWAVEFORMAT;
typedef OLIOPRWAVEFORMAT *POLIOPRWAVEFORMAT,
*NPOLIOPRWAVEFORMAT, *LPOLIOPRWAVEFORMAT;
typedef struct csimaadpcmwaveformat_tag {
WAVEFORMATEX wfx;
} CSIMAADPCMWAVEFORMAT;
typedef CSIMAADPCMWAVEFORMAT *PCSIMAADPCMWAVEFORMAT,
*NPCSIMAADPCMWAVEFORMAT, *LPCSIMAADPCMWAVEFORMAT;
typedef struct
{
WAVEFORMATEX wfx;
WORD fwHeadLayer;
DWORD dwHeadBitrate;
WORD fwHeadMode;
WORD fwHeadModeExt;
WORD wHeadEmphasis;
WORD fwHeadFlags;
DWORD dwPTSLow;
DWORD dwPTSHigh;
} MPEG1WAVEFORMAT,* PMPEG1WAVEFORMAT;
#define ACM_MPEG_LAYER1 0x0001
#define ACM_MPEG_LAYER2 0x0002
#define ACM_MPEG_LAYER3 0x0004
#define ACM_MPEG_STEREO 0x0001
#define ACM_MPEG_JOINTSTEREO 0x0002
#define ACM_MPEG_DUALCHANNEL 0x0004
#define ACM_MPEG_SINGLECHANNEL 0x0008
#define ACM_MPEG_PRIVATEBIT 0x0001
#define ACM_MPEG_COPYRIGHT 0x0002
#define ACM_MPEG_ORIGINALHOME 0x0004
#define ACM_MPEG_PROTECTIONBIT 0x0008
#define ACM_MPEG_ID_MPEG1 0x0010
typedef struct
{
WAVEFORMATEX wfx;
WORD wID;
DWORD fdwFlags;
WORD nBlockSize;
WORD nFramesPerBlock;
WORD nCodecDelay;
} MPEGLAYER3WAVEFORMAT;
#define MPEGLAYER3_WFX_EXTRA_BYTES 12
#define MPEGLAYER3_ID_UNKNOWN 0
#define MPEGLAYER3_ID_MPEG 1
#define MPEGLAYER3_ID_CONSTANTFRAMESIZE 2
#define MPEGLAYER3_FLAG_PADDING_ISO 0x00000000
#define MPEGLAYER3_FLAG_PADDING_ON 0x00000001
#define MPEGLAYER3_FLAG_PADDING_OFF 0x00000002
#endif /* __WINE_MMREG_H */

View file

@ -0,0 +1,779 @@
/*
* Declarations for MSACM
*
* Copyright (C) the Wine project
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_MSACM_H
#define __WINE_MSACM_H
#ifdef __cplusplus
extern "C" {
#endif /* defined(__cplusplus) */
#define ACMAPI WINAPI
/***********************************************************************
* Defines/Enums
*/
#define ACMERR_BASE 512
#define ACMERR_NOTPOSSIBLE (ACMERR_BASE + 0)
#define ACMERR_BUSY (ACMERR_BASE + 1)
#define ACMERR_UNPREPARED (ACMERR_BASE + 2)
#define ACMERR_CANCELED (ACMERR_BASE + 3)
#define MM_ACM_OPEN MM_STREAM_OPEN
#define MM_ACM_CLOSE MM_STREAM_CLOSE
#define MM_ACM_DONE MM_STREAM_DONE
#define ACM_DRIVERADDF_FUNCTION 0x00000003L
#define ACM_DRIVERADDF_NOTIFYHWND 0x00000004L
#define ACM_DRIVERADDF_TYPEMASK 0x00000007L
#define ACM_DRIVERADDF_LOCAL 0x00000000L
#define ACM_DRIVERADDF_GLOBAL 0x00000008L
#define ACMDRIVERDETAILS_SHORTNAME_CHARS 32
#define ACMDRIVERDETAILS_LONGNAME_CHARS 128
#define ACMDRIVERDETAILS_COPYRIGHT_CHARS 80
#define ACMDRIVERDETAILS_LICENSING_CHARS 128
#define ACMDRIVERDETAILS_FEATURES_CHARS 512
#define ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC mmioFOURCC('a', 'u', 'd', 'c')
#define ACMDRIVERDETAILS_FCCCOMP_UNDEFINED mmioFOURCC('\0', '\0', '\0', '\0')
#define ACMDRIVERDETAILS_SUPPORTF_CODEC 0x00000001L
#define ACMDRIVERDETAILS_SUPPORTF_CONVERTER 0x00000002L
#define ACMDRIVERDETAILS_SUPPORTF_FILTER 0x00000004L
#define ACMDRIVERDETAILS_SUPPORTF_HARDWARE 0x00000008L
#define ACMDRIVERDETAILS_SUPPORTF_ASYNC 0x00000010L
#define ACMDRIVERDETAILS_SUPPORTF_LOCAL 0x40000000L
#define ACMDRIVERDETAILS_SUPPORTF_DISABLED 0x80000000L
#define ACM_DRIVERENUMF_NOLOCAL 0x40000000L
#define ACM_DRIVERENUMF_DISABLED 0x80000000L
#define ACM_DRIVERPRIORITYF_ENABLE 0x00000001L
#define ACM_DRIVERPRIORITYF_DISABLE 0x00000002L
#define ACM_DRIVERPRIORITYF_ABLEMASK 0x00000003L
#define ACM_DRIVERPRIORITYF_BEGIN 0x00010000L
#define ACM_DRIVERPRIORITYF_END 0x00020000L
#define ACM_DRIVERPRIORITYF_DEFERMASK 0x00030000L
#define MM_ACM_FILTERCHOOSE 0x8000
#define FILTERCHOOSE_MESSAGE 0
#define FILTERCHOOSE_FILTERTAG_VERIFY (FILTERCHOOSE_MESSAGE+0)
#define FILTERCHOOSE_FILTER_VERIFY (FILTERCHOOSE_MESSAGE+1)
#define FILTERCHOOSE_CUSTOM_VERIFY (FILTERCHOOSE_MESSAGE+2)
#define ACMFILTERCHOOSE_STYLEF_SHOWHELP 0x00000004L
#define ACMFILTERCHOOSE_STYLEF_ENABLEHOOK 0x00000008L
#define ACMFILTERCHOOSE_STYLEF_ENABLETEMPLATE 0x00000010L
#define ACMFILTERCHOOSE_STYLEF_ENABLETEMPLATEHANDLE 0x00000020L
#define ACMFILTERCHOOSE_STYLEF_INITTOFILTERSTRUCT 0x00000040L
#define ACMFILTERCHOOSE_STYLEF_CONTEXTHELP 0x00000080L
#define ACMFILTERDETAILS_FILTER_CHARS 128
#define ACM_FILTERDETAILSF_INDEX 0x00000000L
#define ACM_FILTERDETAILSF_FILTER 0x00000001L
#define ACM_FILTERDETAILSF_QUERYMASK 0x0000000FL
#define ACMFILTERTAGDETAILS_FILTERTAG_CHARS 48
#define ACM_FILTERTAGDETAILSF_INDEX 0x00000000L
#define ACM_FILTERTAGDETAILSF_FILTERTAG 0x00000001L
#define ACM_FILTERTAGDETAILSF_LARGESTSIZE 0x00000002L
#define ACM_FILTERTAGDETAILSF_QUERYMASK 0x0000000FL
#define ACM_FILTERENUMF_DWFILTERTAG 0x00010000L
#define ACMHELPMSGSTRINGA "acmchoose_help"
#if defined(__GNUC__)
# define ACMHELPMSGSTRINGW (const WCHAR []){ 'a','c','m', \
'c','h','o','o','s','e','_','h','e','l','p',0 }
#elif defined(_MSC_VER)
# define ACMHELPMSGSTRINGW L"acmchoose_help"
#else
static const WCHAR ACMHELPMSGSTRINGW[] = { 'a','c','m',
'c','h','o','o','s','e','_','h','e','l','p',0 };
#endif
#define ACMHELPMSGSTRING WINELIB_NAME_AW(ACMHELPMSGSTRING)
#define ACMHELPMSGCONTEXTMENUA "acmchoose_contextmenu"
#if defined(__GNUC__)
# define ACMHELPMSGCONTEXTMENUW (const WCHAR []){ 'a','c','m', \
'c','h','o','o','s','e','_','c','o','n','t','e','x','t','m','e','n','u',0 }
#elif defined(_MSC_VER)
# define ACMHELPMSGCONTEXTMENUW L"acmchoose_contextmenu"
#else
static const WCHAR ACMHELPMSGCONTEXTMENUW[] = { 'a','c','m',
'c','h','o','o','s','e','_','c','o','n','t','e','x','t','m','e','n','u',0 };
#endif
#define ACMHELPMSGCONTEXTMENU WINELIB_NAME_AW(ACMHELPMSGCONTEXTMENU)
#define ACMHELPMSGCONTEXTHELPA "acmchoose_contexthelp"
#if defined(__GNUC__)
# define ACMHELPMSGCONTEXTHELPW (const WCHAR []){ 'a','c','m', \
'c','h','o','o','s','e','_','c','o','n','t','e','x','t','h','e','l','p',0 }
#elif defined(_MSC_VER)
# define ACMHELPMSGCONTEXTHELPW L"acmchoose_contexthelp"
#else
static const WCHAR ACMHELPMSGCONTEXTHELPW[] = { 'a','c','m',
'c','h','o','o','s','e','_','c','o','n','t','e','x','t','h','e','l','p',0 };
#endif
#define ACMHELPMSGCONTEXTHELP WINELIB_NAME_AW(ACMHELPMSGCONTEXTHELP)
#define MM_ACM_FORMATCHOOSE 0x8000
#define FORMATCHOOSE_MESSAGE 0
#define FORMATCHOOSE_FORMATTAG_VERIFY (FORMATCHOOSE_MESSAGE+0)
#define FORMATCHOOSE_FORMAT_VERIFY (FORMATCHOOSE_MESSAGE+1)
#define FORMATCHOOSE_CUSTOM_VERIFY (FORMATCHOOSE_MESSAGE+2)
#define ACMFORMATCHOOSE_STYLEF_SHOWHELP 0x00000004L
#define ACMFORMATCHOOSE_STYLEF_ENABLEHOOK 0x00000008L
#define ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE 0x00000010L
#define ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE 0x00000020L
#define ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT 0x00000040L
#define ACMFORMATCHOOSE_STYLEF_CONTEXTHELP 0x00000080L
#define ACMFORMATDETAILS_FORMAT_CHARS 128
#define ACM_FORMATDETAILSF_INDEX 0x00000000L
#define ACM_FORMATDETAILSF_FORMAT 0x00000001L
#define ACM_FORMATDETAILSF_QUERYMASK 0x0000000FL
#define ACM_FORMATENUMF_WFORMATTAG 0x00010000L
#define ACM_FORMATENUMF_NCHANNELS 0x00020000L
#define ACM_FORMATENUMF_NSAMPLESPERSEC 0x00040000L
#define ACM_FORMATENUMF_WBITSPERSAMPLE 0x00080000L
#define ACM_FORMATENUMF_CONVERT 0x00100000L
#define ACM_FORMATENUMF_SUGGEST 0x00200000L
#define ACM_FORMATENUMF_HARDWARE 0x00400000L
#define ACM_FORMATENUMF_INPUT 0x00800000L
#define ACM_FORMATENUMF_OUTPUT 0x01000000L
#define ACM_FORMATSUGGESTF_WFORMATTAG 0x00010000L
#define ACM_FORMATSUGGESTF_NCHANNELS 0x00020000L
#define ACM_FORMATSUGGESTF_NSAMPLESPERSEC 0x00040000L
#define ACM_FORMATSUGGESTF_WBITSPERSAMPLE 0x00080000L
#define ACM_FORMATSUGGESTF_TYPEMASK 0x00FF0000L
#define ACMFORMATTAGDETAILS_FORMATTAG_CHARS 48
#define ACM_FORMATTAGDETAILSF_INDEX 0x00000000L
#define ACM_FORMATTAGDETAILSF_FORMATTAG 0x00000001L
#define ACM_FORMATTAGDETAILSF_LARGESTSIZE 0x00000002L
#define ACM_FORMATTAGDETAILSF_QUERYMASK 0x0000000FL
#define ACM_METRIC_COUNT_DRIVERS 1
#define ACM_METRIC_COUNT_CODECS 2
#define ACM_METRIC_COUNT_CONVERTERS 3
#define ACM_METRIC_COUNT_FILTERS 4
#define ACM_METRIC_COUNT_DISABLED 5
#define ACM_METRIC_COUNT_HARDWARE 6
#define ACM_METRIC_COUNT_LOCAL_DRIVERS 20
#define ACM_METRIC_COUNT_LOCAL_CODECS 21
#define ACM_METRIC_COUNT_LOCAL_CONVERTERS 22
#define ACM_METRIC_COUNT_LOCAL_FILTERS 23
#define ACM_METRIC_COUNT_LOCAL_DISABLED 24
#define ACM_METRIC_HARDWARE_WAVE_INPUT 30
#define ACM_METRIC_HARDWARE_WAVE_OUTPUT 31
#define ACM_METRIC_MAX_SIZE_FORMAT 50
#define ACM_METRIC_MAX_SIZE_FILTER 51
#define ACM_METRIC_DRIVER_SUPPORT 100
#define ACM_METRIC_DRIVER_PRIORITY 101
#define ACM_STREAMCONVERTF_BLOCKALIGN 0x00000004
#define ACM_STREAMCONVERTF_START 0x00000010
#define ACM_STREAMCONVERTF_END 0x00000020
#define ACMSTREAMHEADER_STATUSF_DONE 0x00010000L
#define ACMSTREAMHEADER_STATUSF_PREPARED 0x00020000L
#define ACMSTREAMHEADER_STATUSF_INQUEUE 0x00100000L
#define ACM_STREAMOPENF_QUERY 0x00000001
#define ACM_STREAMOPENF_ASYNC 0x00000002
#define ACM_STREAMOPENF_NONREALTIME 0x00000004
#define ACM_STREAMSIZEF_SOURCE 0x00000000L
#define ACM_STREAMSIZEF_DESTINATION 0x00000001L
#define ACM_STREAMSIZEF_QUERYMASK 0x0000000FL
#define ACMDM_USER (DRV_USER + 0x0000)
#define ACMDM_RESERVED_LOW (DRV_USER + 0x2000)
#define ACMDM_RESERVED_HIGH (DRV_USER + 0x2FFF)
#define ACMDM_BASE ACMDM_RESERVED_LOW
#define ACMDM_DRIVER_ABOUT (ACMDM_BASE + 11)
/* handles */
DECLARE_HANDLE(HACMDRIVERID);
DECLARE_HANDLE(HACMDRIVER);
DECLARE_HANDLE(HACMSTREAM);
DECLARE_HANDLE(HACMOBJ);
typedef HACMDRIVERID *PHACMDRIVERID, *LPHACMDRIVERID;
typedef HACMDRIVER *PHACMDRIVER, *LPHACMDRIVER;
typedef HACMSTREAM *PHACMSTREAM, *LPHACMSTREAM;
typedef HACMOBJ *PHACMOBJ, *LPHACMOBJ;
/***********************************************************************
* Callbacks
*/
typedef BOOL (CALLBACK *ACMDRIVERENUMCB)(
HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport
);
typedef UINT (CALLBACK *ACMFILTERCHOOSEHOOKPROCA)(
HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam
);
typedef UINT (CALLBACK *ACMFILTERCHOOSEHOOKPROCW)(
HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam
);
#define ACMFILTERCHOOSEHOOKPROC WINELIB_NAME_AW(ACMFILTERCHOOSEHOOKPROC)
typedef UINT (CALLBACK *ACMFORMATCHOOSEHOOKPROCA)(
HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam
);
typedef UINT (CALLBACK *ACMFORMATCHOOSEHOOKPROCW)(
HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam
);
#define ACMFORMATCHOOSEHOOKPROC WINELIB_NAME_AW(ACMFORMATCHOOSEHOOKPROC)
/***********************************************************************
* Structures
*/
typedef struct _ACMDRIVERDETAILSA
{
DWORD cbStruct;
FOURCC fccType;
FOURCC fccComp;
WORD wMid;
WORD wPid;
DWORD vdwACM;
DWORD vdwDriver;
DWORD fdwSupport;
DWORD cFormatTags;
DWORD cFilterTags;
HICON hicon;
CHAR szShortName[ACMDRIVERDETAILS_SHORTNAME_CHARS];
CHAR szLongName[ACMDRIVERDETAILS_LONGNAME_CHARS];
CHAR szCopyright[ACMDRIVERDETAILS_COPYRIGHT_CHARS];
CHAR szLicensing[ACMDRIVERDETAILS_LICENSING_CHARS];
CHAR szFeatures[ACMDRIVERDETAILS_FEATURES_CHARS];
} ACMDRIVERDETAILSA, *PACMDRIVERDETAILSA, *LPACMDRIVERDETAILSA;
typedef struct _ACMDRIVERDETAILSW
{
DWORD cbStruct;
FOURCC fccType;
FOURCC fccComp;
WORD wMid;
WORD wPid;
DWORD vdwACM;
DWORD vdwDriver;
DWORD fdwSupport;
DWORD cFormatTags;
DWORD cFilterTags;
HICON hicon;
WCHAR szShortName[ACMDRIVERDETAILS_SHORTNAME_CHARS];
WCHAR szLongName[ACMDRIVERDETAILS_LONGNAME_CHARS];
WCHAR szCopyright[ACMDRIVERDETAILS_COPYRIGHT_CHARS];
WCHAR szLicensing[ACMDRIVERDETAILS_LICENSING_CHARS];
WCHAR szFeatures[ACMDRIVERDETAILS_FEATURES_CHARS];
} ACMDRIVERDETAILSW, *PACMDRIVERDETAILSW, *LPACMDRIVERDETAILSW;
DECL_WINELIB_TYPE_AW(ACMDRIVERDETAILS)
DECL_WINELIB_TYPE_AW(PACMDRIVERDETAILS)
DECL_WINELIB_TYPE_AW(LPACMDRIVERDETAILS)
typedef struct _ACMFILTERCHOOSEA
{
DWORD cbStruct;
DWORD fdwStyle;
HWND hwndOwner;
PWAVEFILTER pwfltr;
DWORD cbwfltr;
LPCSTR pszTitle;
CHAR szFilterTag[ACMFILTERTAGDETAILS_FILTERTAG_CHARS];
CHAR szFilter[ACMFILTERDETAILS_FILTER_CHARS];
LPSTR pszName;
DWORD cchName;
DWORD fdwEnum;
PWAVEFILTER pwfltrEnum;
HINSTANCE hInstance;
LPCSTR pszTemplateName;
LPARAM lCustData;
ACMFILTERCHOOSEHOOKPROCA pfnHook;
} ACMFILTERCHOOSEA, *PACMFILTERCHOOSEA, *LPACMFILTERCHOOSEA;
typedef struct _ACMFILTERCHOOSEW
{
DWORD cbStruct;
DWORD fdwStyle;
HWND hwndOwner;
PWAVEFILTER pwfltr;
DWORD cbwfltr;
LPCWSTR pszTitle;
WCHAR szFilterTag[ACMFILTERTAGDETAILS_FILTERTAG_CHARS];
WCHAR szFilter[ACMFILTERDETAILS_FILTER_CHARS];
LPWSTR pszName;
DWORD cchName;
DWORD fdwEnum;
PWAVEFILTER pwfltrEnum;
HINSTANCE hInstance;
LPCWSTR pszTemplateName;
LPARAM lCustData;
ACMFILTERCHOOSEHOOKPROCW pfnHook;
} ACMFILTERCHOOSEW, *PACMFILTERCHOOSEW, *LPACMFILTERCHOOSEW;
DECL_WINELIB_TYPE_AW(ACMFILTERCHOOSE)
DECL_WINELIB_TYPE_AW(PACMFILTERCHOOSE)
DECL_WINELIB_TYPE_AW(LPACMFILTERCHOOSE)
typedef struct _ACMFILTERDETAILSA
{
DWORD cbStruct;
DWORD dwFilterIndex;
DWORD dwFilterTag;
DWORD fdwSupport;
PWAVEFILTER pwfltr;
DWORD cbwfltr;
CHAR szFilter[ACMFILTERDETAILS_FILTER_CHARS];
} ACMFILTERDETAILSA, *PACMFILTERDETAILSA, *LPACMFILTERDETAILSA;
typedef struct _ACMFILTERDETAILSW
{
DWORD cbStruct;
DWORD dwFilterIndex;
DWORD dwFilterTag;
DWORD fdwSupport;
PWAVEFILTER pwfltr;
DWORD cbwfltr;
WCHAR szFilter[ACMFILTERDETAILS_FILTER_CHARS];
} ACMFILTERDETAILSW, *PACMFILTERDETAILSW, *LPACMFILTERDETAILSW;
DECL_WINELIB_TYPE_AW(ACMFILTERDETAILS)
DECL_WINELIB_TYPE_AW(PACMFILTERDETAILS)
DECL_WINELIB_TYPE_AW(LPACMFILTERDETAILS)
typedef struct _ACMFILTERTAGDETAILSA
{
DWORD cbStruct;
DWORD dwFilterTagIndex;
DWORD dwFilterTag;
DWORD cbFilterSize;
DWORD fdwSupport;
DWORD cStandardFilters;
CHAR szFilterTag[ACMFILTERTAGDETAILS_FILTERTAG_CHARS];
} ACMFILTERTAGDETAILSA, *PACMFILTERTAGDETAILSA, *LPACMFILTERTAGDETAILSA;
typedef struct _ACMFILTERTAGDETAILSW
{
DWORD cbStruct;
DWORD dwFilterTagIndex;
DWORD dwFilterTag;
DWORD cbFilterSize;
DWORD fdwSupport;
DWORD cStandardFilters;
WCHAR szFilterTag[ACMFILTERTAGDETAILS_FILTERTAG_CHARS];
} ACMFILTERTAGDETAILSW, *PACMFILTERTAGDETAILSW, *LPACMFILTERTAGDETAILSW;
DECL_WINELIB_TYPE_AW(ACMFILTERTAGDETAILS)
DECL_WINELIB_TYPE_AW(PACMFILTERTAGDETAILS)
DECL_WINELIB_TYPE_AW(LPACMFILTERTAGDETAILS)
typedef struct _ACMFORMATCHOOSEA
{
DWORD cbStruct;
DWORD fdwStyle;
HWND hwndOwner;
PWAVEFORMATEX pwfx;
DWORD cbwfx;
LPCSTR pszTitle;
CHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
CHAR szFormat[ACMFORMATDETAILS_FORMAT_CHARS];
LPSTR pszName;
DWORD cchName;
DWORD fdwEnum;
PWAVEFORMATEX pwfxEnum;
HINSTANCE hInstance;
LPCSTR pszTemplateName;
LPARAM lCustData;
ACMFORMATCHOOSEHOOKPROCA pfnHook;
} ACMFORMATCHOOSEA, *PACMFORMATCHOOSEA, *LPACMFORMATCHOOSEA;
typedef struct _ACMFORMATCHOOSEW
{
DWORD cbStruct;
DWORD fdwStyle;
HWND hwndOwner;
PWAVEFORMATEX pwfx;
DWORD cbwfx;
LPCWSTR pszTitle;
WCHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
WCHAR szFormat[ACMFORMATDETAILS_FORMAT_CHARS];
LPWSTR pszName;
DWORD cchName;
DWORD fdwEnum;
LPWAVEFORMATEX pwfxEnum;
HINSTANCE hInstance;
LPCWSTR pszTemplateName;
LPARAM lCustData;
ACMFORMATCHOOSEHOOKPROCW pfnHook;
} ACMFORMATCHOOSEW, *PACMFORMATCHOOSEW, *LPACMFORMATCHOOSEW;
DECL_WINELIB_TYPE_AW(ACMFORMATCHOOSE)
DECL_WINELIB_TYPE_AW(PACMFORMATCHOOSE)
DECL_WINELIB_TYPE_AW(LPACMFORMATCHOOSE)
typedef struct _ACMFORMATDETAILSA
{
DWORD cbStruct;
DWORD dwFormatIndex;
DWORD dwFormatTag;
DWORD fdwSupport;
PWAVEFORMATEX pwfx;
DWORD cbwfx;
CHAR szFormat[ACMFORMATDETAILS_FORMAT_CHARS];
} ACMFORMATDETAILSA, *PACMFORMATDETAILSA, *LPACMFORMATDETAILSA;
typedef struct _ACMFORMATDETAILSW
{
DWORD cbStruct;
DWORD dwFormatIndex;
DWORD dwFormatTag;
DWORD fdwSupport;
PWAVEFORMATEX pwfx;
DWORD cbwfx;
WCHAR szFormat[ACMFORMATDETAILS_FORMAT_CHARS];
} ACMFORMATDETAILSW, *PACMFORMATDETAILSW, *LPACMFORMATDETAILSW;
DECL_WINELIB_TYPE_AW(ACMFORMATDETAILS)
DECL_WINELIB_TYPE_AW(PACMFORMATDETAILS)
DECL_WINELIB_TYPE_AW(LPACMFORMATDETAILS)
typedef struct _ACMFORMATTAGDETAILSA
{
DWORD cbStruct;
DWORD dwFormatTagIndex;
DWORD dwFormatTag;
DWORD cbFormatSize;
DWORD fdwSupport;
DWORD cStandardFormats;
CHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
} ACMFORMATTAGDETAILSA, *PACMFORMATTAGDETAILSA, *LPACMFORMATTAGDETAILSA;
typedef struct _ACMFORMATTAGDETAILSW
{
DWORD cbStruct;
DWORD dwFormatTagIndex;
DWORD dwFormatTag;
DWORD cbFormatSize;
DWORD fdwSupport;
DWORD cStandardFormats;
WCHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
} ACMFORMATTAGDETAILSW, *PACMFORMATTAGDETAILSW, *LPACMFORMATTAGDETAILSW;
DECL_WINELIB_TYPE_AW(ACMFORMATTAGDETAILS)
DECL_WINELIB_TYPE_AW(PACMFORMATTAGDETAILS)
DECL_WINELIB_TYPE_AW(LPACMFORMATTAGDETAILS)
typedef struct _ACMSTREAMHEADER
{
DWORD cbStruct;
DWORD fdwStatus;
DWORD dwUser;
LPBYTE pbSrc;
DWORD cbSrcLength;
DWORD cbSrcLengthUsed;
DWORD dwSrcUser;
LPBYTE pbDst;
DWORD cbDstLength;
DWORD cbDstLengthUsed;
DWORD dwDstUser;
DWORD dwReservedDriver[10];
} ACMSTREAMHEADER, *PACMSTREAMHEADER, *LPACMSTREAMHEADER;
/***********************************************************************
* Callbacks 2
*/
typedef BOOL (CALLBACK *ACMFILTERENUMCBA)(
HACMDRIVERID hadid, PACMFILTERDETAILSA pafd,
DWORD dwInstance, DWORD fdwSupport
);
typedef BOOL (CALLBACK *ACMFILTERENUMCBW)(
HACMDRIVERID hadid, PACMFILTERDETAILSW pafd,
DWORD dwInstance, DWORD fdwSupport
);
#define ACMFILTERENUMCB WINELIB_NAME_AW(ACMFILTERENUMCB)
typedef BOOL (CALLBACK *ACMFILTERTAGENUMCBA)(
HACMDRIVERID hadid, PACMFILTERTAGDETAILSA paftd,
DWORD dwInstance, DWORD fdwSupport
);
typedef BOOL (CALLBACK *ACMFILTERTAGENUMCBW)(
HACMDRIVERID hadid, PACMFILTERTAGDETAILSW paftd,
DWORD dwInstance, DWORD fdwSupport
);
#define ACMFILTERTAGENUMCB WINELIB_NAME_AW(ACMFILTERTAGENUMCB)
typedef BOOL (CALLBACK *ACMFORMATENUMCBA)(
HACMDRIVERID hadid, PACMFORMATDETAILSA pafd,
DWORD dwInstance, DWORD fdwSupport
);
typedef BOOL (CALLBACK *ACMFORMATENUMCBW)(
HACMDRIVERID hadid, PACMFORMATDETAILSW pafd,
DWORD dwInstance, DWORD fdwSupport
);
#define ACMFORMATENUMCB WINELIB_NAME_AW(ACMFORMATENUMCB)
typedef BOOL (CALLBACK *ACMFORMATTAGENUMCBA)(
HACMDRIVERID hadid, PACMFORMATTAGDETAILSA paftd,
DWORD dwInstance, DWORD fdwSupport
);
typedef BOOL (CALLBACK *ACMFORMATTAGENUMCBW)(
HACMDRIVERID hadid, PACMFORMATTAGDETAILSW paftd,
DWORD dwInstance, DWORD fdwSupport
);
#define ACMFORMATTAGENUMCB WINELIB_NAME_AW(ACMFORMATTAGENUMCB)
/***********************************************************************
* Functions - Win32
*/
MMRESULT WINAPI acmDriverAddA(
PHACMDRIVERID phadid, HINSTANCE hinstModule,
LPARAM lParam, DWORD dwPriority, DWORD fdwAdd
);
MMRESULT WINAPI acmDriverAddW(
PHACMDRIVERID phadid, HINSTANCE hinstModule,
LPARAM lParam, DWORD dwPriority, DWORD fdwAdd
);
#define acmDriverAdd WINELIB_NAME_AW(acmDriverAdd)
MMRESULT WINAPI acmDriverClose(
HACMDRIVER had, DWORD fdwClose
);
MMRESULT WINAPI acmDriverDetailsA(
HACMDRIVERID hadid, PACMDRIVERDETAILSA padd, DWORD fdwDetails
);
MMRESULT WINAPI acmDriverDetailsW(
HACMDRIVERID hadid, PACMDRIVERDETAILSW padd, DWORD fdwDetails
);
#define acmDriverDetails WINELIB_NAME_AW(acmDriverDetails)
MMRESULT WINAPI acmDriverEnum(
ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum
);
MMRESULT WINAPI acmDriverID(
HACMOBJ hao, PHACMDRIVERID phadid, DWORD fdwDriverID
);
LRESULT WINAPI acmDriverMessage(
HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2
);
MMRESULT WINAPI acmDriverOpen(
PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen
);
MMRESULT WINAPI acmDriverPriority(
HACMDRIVERID hadid, DWORD dwPriority, DWORD fdwPriority
);
MMRESULT WINAPI acmDriverRemove(
HACMDRIVERID hadid, DWORD fdwRemove
);
MMRESULT WINAPI acmFilterChooseA(
PACMFILTERCHOOSEA pafltrc
);
MMRESULT WINAPI acmFilterChooseW(
PACMFILTERCHOOSEW pafltrc
);
#define acmFilterChoose WINELIB_NAME_AW(acmFilterChoose)
MMRESULT WINAPI acmFilterDetailsA(
HACMDRIVER had, PACMFILTERDETAILSA pafd, DWORD fdwDetails
);
MMRESULT WINAPI acmFilterDetailsW(
HACMDRIVER had, PACMFILTERDETAILSW pafd, DWORD fdwDetails
);
#define acmFilterDetails WINELIB_NAME_AW(acmFilterDetails)
MMRESULT WINAPI acmFilterEnumA(
HACMDRIVER had, PACMFILTERDETAILSA pafd,
ACMFILTERENUMCBA fnCallback, DWORD dwInstance, DWORD fdwEnum
);
MMRESULT WINAPI acmFilterEnumW(
HACMDRIVER had, PACMFILTERDETAILSW pafd,
ACMFILTERENUMCBW fnCallback, DWORD dwInstance, DWORD fdwEnum
);
#define acmFilterEnum WINELIB_NAME_AW(acmFilterEnum)
MMRESULT WINAPI acmFilterTagDetailsA(
HACMDRIVER had, PACMFILTERTAGDETAILSA paftd, DWORD fdwDetails
);
MMRESULT WINAPI acmFilterTagDetailsW(
HACMDRIVER had, PACMFILTERTAGDETAILSW paftd, DWORD fdwDetails
);
#define acmFilterTagDetails WINELIB_NAME_AW(acmFilterTagDetails)
MMRESULT WINAPI acmFilterTagEnumA(
HACMDRIVER had, PACMFILTERTAGDETAILSA paftd,
ACMFILTERTAGENUMCBA fnCallback, DWORD dwInstance, DWORD fdwEnum
);
MMRESULT WINAPI acmFilterTagEnumW(
HACMDRIVER had, PACMFILTERTAGDETAILSW paftd,
ACMFILTERTAGENUMCBW fnCallback, DWORD dwInstance, DWORD fdwEnum
);
#define acmFilterTagEnum WINELIB_NAME_AW(acmFilterTagEnum)
MMRESULT WINAPI acmFormatChooseA(
PACMFORMATCHOOSEA pafmtc
);
MMRESULT WINAPI acmFormatChooseW(
PACMFORMATCHOOSEW pafmtc
);
#define acmFormatChoose WINELIB_NAME_AW(acmFormatChoose)
MMRESULT WINAPI acmFormatDetailsA(
HACMDRIVER had, PACMFORMATDETAILSA pafd, DWORD fdwDetails
);
MMRESULT WINAPI acmFormatDetailsW(
HACMDRIVER had, PACMFORMATDETAILSW pafd, DWORD fdwDetails
);
#define acmFormatDetails WINELIB_NAME_AW(acmFormatDetails)
MMRESULT WINAPI acmFormatEnumA(
HACMDRIVER had, PACMFORMATDETAILSA pafd,
ACMFORMATENUMCBA fnCallback, DWORD dwInstance, DWORD fdwEnum
);
MMRESULT WINAPI acmFormatEnumW(
HACMDRIVER had, PACMFORMATDETAILSW pafd,
ACMFORMATENUMCBW fnCallback, DWORD dwInstance, DWORD fdwEnum
);
#define acmFormatEnum WINELIB_NAME_AW(acmFormatEnum)
MMRESULT WINAPI acmFormatSuggest(
HACMDRIVER had, PWAVEFORMATEX pwfxSrc, PWAVEFORMATEX pwfxDst,
DWORD cbwfxDst, DWORD fdwSuggest
);
MMRESULT WINAPI acmFormatTagDetailsA(
HACMDRIVER had, PACMFORMATTAGDETAILSA paftd, DWORD fdwDetails
);
MMRESULT WINAPI acmFormatTagDetailsW(
HACMDRIVER had, PACMFORMATTAGDETAILSW paftd, DWORD fdwDetails
);
#define acmFormatTagDetails WINELIB_NAME_AW(acmFormatTagDetails)
MMRESULT WINAPI acmFormatTagEnumA(
HACMDRIVER had, PACMFORMATTAGDETAILSA paftd,
ACMFORMATTAGENUMCBA fnCallback, DWORD dwInstance, DWORD fdwEnum
);
MMRESULT WINAPI acmFormatTagEnumW(
HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
ACMFORMATTAGENUMCBW fnCallback, DWORD dwInstance, DWORD fdwEnum
);
#define acmFormatTagEnum WINELIB_NAME_AW(acmFormatTagEnum)
DWORD WINAPI acmGetVersion(void
);
MMRESULT WINAPI acmMetrics(
HACMOBJ hao, UINT uMetric, LPVOID pMetric
);
MMRESULT WINAPI acmStreamClose(
HACMSTREAM has, DWORD fdwClose
);
MMRESULT WINAPI acmStreamConvert(
HACMSTREAM has, PACMSTREAMHEADER pash, DWORD fdwConvert
);
MMRESULT WINAPI acmStreamMessage(
HACMSTREAM has, UINT uMsg, LPARAM lParam1, LPARAM lParam2
);
MMRESULT WINAPI acmStreamOpen(
PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD dwCallback,
DWORD dwInstance, DWORD fdwOpen
);
MMRESULT WINAPI acmStreamPrepareHeader(
HACMSTREAM has, PACMSTREAMHEADER pash, DWORD fdwPrepare
);
MMRESULT WINAPI acmStreamReset(
HACMSTREAM has, DWORD fdwReset
);
MMRESULT WINAPI acmStreamSize(
HACMSTREAM has, DWORD cbInput,
LPDWORD pdwOutputBytes, DWORD fdwSize
);
MMRESULT WINAPI acmStreamUnprepareHeader(
HACMSTREAM has, PACMSTREAMHEADER pash, DWORD fdwUnprepare
);
#ifdef __cplusplus
} /* extern "C" */
#endif /* defined(__cplusplus) */
#endif /* __WINE_MSACM_H */

View file

@ -0,0 +1,36 @@
/*
* definitions for MSACM dialog boxes
*
* Copyright (C) 2001 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define DLG_ACMFORMATCHOOSE_ID 70
#define IDD_ACMFORMATCHOOSE_BTN_HELP 9
#define IDD_ACMFORMATCHOOSE_CMB_CUSTOM 100
#define IDD_ACMFORMATCHOOSE_CMB_FORMATTAG 101
#define IDD_ACMFORMATCHOOSE_CMB_FORMAT 102
#define IDD_ACMFORMATCHOOSE_BTN_SETNAME 103
#define IDD_ACMFORMATCHOOSE_BTN_DELNAME 104
#define DLG_ACMFILTERCHOOSE_ID 71
#define IDD_ACMFILTERCHOOSE_BTN_HELP 9
#define IDD_ACMFILTERCHOOSE_CMB_CUSTOM 100
#define IDD_ACMFILTERCHOOSE_CMB_FILTERTAG 101
#define IDD_ACMFILTERCHOOSE_CMB_FILTER 102
#define IDD_ACMFILTERCHOOSE_BTN_SETNAME 103
#define IDD_ACMFILTERCHOOSE_BTN_DELNAME 104

View file

@ -0,0 +1,157 @@
/*
* Declarations for MSACM driver
*
* Copyright 1998 Patrik Stridvall
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_MSACMDRV_H
#define __WINE_MSACMDRV_H
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "mmsystem.h"
#include "mmreg.h"
#include "msacm.h"
/***********************************************************************
* Types
*/
/***********************************************************************
* Defines/Enums
*/
#define MAKE_ACM_VERSION(mjr, mnr, bld) \
(((long)(mjr)<<24) | ((long)(mnr)<<16) | ((long)bld))
#define ACMDRVOPENDESC_SECTIONNAME_CHARS
#define ACMDM_DRIVER_NOTIFY (ACMDM_BASE + 1)
#define ACMDM_DRIVER_DETAILS (ACMDM_BASE + 10)
#define ACMDM_HARDWARE_WAVE_CAPS_INPUT (ACMDM_BASE + 20)
#define ACMDM_HARDWARE_WAVE_CAPS_OUTPUT (ACMDM_BASE + 21)
#define ACMDM_FORMATTAG_DETAILS (ACMDM_BASE + 25)
#define ACMDM_FORMAT_DETAILS (ACMDM_BASE + 26)
#define ACMDM_FORMAT_SUGGEST (ACMDM_BASE + 27)
#define ACMDM_FILTERTAG_DETAILS (ACMDM_BASE + 50)
#define ACMDM_FILTER_DETAILS (ACMDM_BASE + 51)
#define ACMDM_STREAM_OPEN (ACMDM_BASE + 76)
#define ACMDM_STREAM_CLOSE (ACMDM_BASE + 77)
#define ACMDM_STREAM_SIZE (ACMDM_BASE + 78)
#define ACMDM_STREAM_CONVERT (ACMDM_BASE + 79)
#define ACMDM_STREAM_RESET (ACMDM_BASE + 80)
#define ACMDM_STREAM_PREPARE (ACMDM_BASE + 81)
#define ACMDM_STREAM_UNPREPARE (ACMDM_BASE + 82)
#define ACMDM_STREAM_UPDATE (ACMDM_BASE + 83)
/***********************************************************************
* Structures
*/
typedef struct _ACMDRVOPENDESCA
{
DWORD cbStruct;
FOURCC fccType;
FOURCC fccComp;
DWORD dwVersion;
DWORD dwFlags;
DWORD dwError;
LPCSTR pszSectionName;
LPCSTR pszAliasName;
DWORD dnDevNode;
} ACMDRVOPENDESCA, *PACMDRVOPENDESCA;
typedef struct _ACMDRVOPENDESCW
{
DWORD cbStruct;
FOURCC fccType;
FOURCC fccComp;
DWORD dwVersion;
DWORD dwFlags;
DWORD dwError;
LPCWSTR pszSectionName;
LPCWSTR pszAliasName;
DWORD dnDevNode;
} ACMDRVOPENDESCW, *PACMDRVOPENDESCW;
typedef struct _ACMDRVSTREAMINSTANCE
{
DWORD cbStruct;
PWAVEFORMATEX pwfxSrc;
PWAVEFORMATEX pwfxDst;
PWAVEFILTER pwfltr;
DWORD dwCallback;
DWORD dwInstance;
DWORD fdwOpen;
DWORD fdwDriver;
DWORD dwDriver;
HACMSTREAM has;
} ACMDRVSTREAMINSTANCE, *PACMDRVSTREAMINSTANCE;
typedef struct _ACMDRVSTREAMHEADER *PACMDRVSTREAMHEADER;
typedef struct _ACMDRVSTREAMHEADER {
DWORD cbStruct;
DWORD fdwStatus;
DWORD dwUser;
LPBYTE pbSrc;
DWORD cbSrcLength;
DWORD cbSrcLengthUsed;
DWORD dwSrcUser;
LPBYTE pbDst;
DWORD cbDstLength;
DWORD cbDstLengthUsed;
DWORD dwDstUser;
DWORD fdwConvert;
PACMDRVSTREAMHEADER *padshNext;
DWORD fdwDriver;
DWORD dwDriver;
/* Internal fields for ACM */
DWORD fdwPrepared;
DWORD dwPrepared;
LPBYTE pbPreparedSrc;
DWORD cbPreparedSrcLength;
LPBYTE pbPreparedDst;
DWORD cbPreparedDstLength;
} ACMDRVSTREAMHEADER;
typedef struct _ACMDRVSTREAMSIZE
{
DWORD cbStruct;
DWORD fdwSize;
DWORD cbSrcLength;
DWORD cbDstLength;
} ACMDRVSTREAMSIZE, *PACMDRVSTREAMSIZE;
typedef struct _ACMDRVFORMATSUGGEST
{
DWORD cbStruct;
DWORD fdwSuggest;
PWAVEFORMATEX pwfxSrc;
DWORD cbwfxSrc;
PWAVEFORMATEX pwfxDst;
DWORD cbwfxDst;
} ACMDRVFORMATSUGGEST, *PACMDRVFORMATSUGGEST;
#endif /* __WINE_MSACMDRV_H */

View file

@ -118,6 +118,8 @@ static DWORD OpenMidiDevice(UINT DeviceType, DWORD ID, DWORD User, DWORD Param1,
static DWORD WriteMidi(PBYTE pData, ULONG Length, PMIDIALLOC pClient)
{
DWORD BytesReturned;
printf("IOCTL_MIDI_PLAY == %d [%x]\n", IOCTL_MIDI_PLAY, IOCTL_MIDI_PLAY);
if ( !DeviceIoControl(pClient->DeviceHandle, IOCTL_MIDI_PLAY, (PVOID)pData,
Length, NULL, 0, &BytesReturned, NULL))

87
reactos/lib/mmdrv/mmdef.h Normal file
View file

@ -0,0 +1,87 @@
/*
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: lib/mmdrv/mmdef.h
* PURPOSE: Multimedia Definitions (for mmdrv.dll)
* PROGRAMMER: Andrew Greenwood
*
*/
#ifndef __INCLUDES_MMDEF_H__
#define __INCLUDES_MMDEF_H__
//#define UNICODE
#define EXPORT __declspec(dllexport)
//#include <stdio.h>
//#include <windows.h>
//#include <mmsystem.h>
//#include <mmddk.h>
// This needs to be done to get winioctl.h to work:
//typedef unsigned __int64 DWORD64, *PDWORD64;
//#include <winioctl.h>
//#include "mmddk.h"
#define SOUND_MAX_DEVICE_NAME 1024 // GUESSWORK
#define SOUND_MAX_DEVICES 256 // GUESSWORK
// If the root is \Device and the Device type is
// WaveIn and the device number is 2, the full name is \Device\WaveIn2
#define WAVE_IN_DEVICE_NAME "\\Device\\WaveIn"
#define WAVE_IN_DEVICE_NAME_U L"\\Device\\WaveIn"
#define WAVE_OUT_DEVICE_NAME "\\Device\\WaveOut"
#define WAVE_OUT_DEVICE_NAME_U L"\\Device\\WaveOut"
#define MIDI_IN_DEVICE_NAME "\\Device\\MidiIn"
#define MIDI_IN_DEVICE_NAME_U L"\\Device\\MidiIn"
#define MIDI_OUT_DEVICE_NAME "\\Device\\MidiOut"
#define MIDI_OUT_DEVICE_NAME_U L"\\Device\\MidiOut"
#define AUX_DEVICE_NAME "\\Device\\MMAux"
#define AUX_DEVICE_NAME_U L"\\Device\\MMAux"
#define IOCTL_SOUND_BASE FILE_DEVICE_SOUND
#define IOCTL_WAVE_BASE 0x0000
#define IOCTL_MIDI_BASE 0x0080
// Wave device driver IOCTLs
#define IOCTL_WAVE_QUERY_FORMAT CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_WAVE_SET_FORMAT CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x0002, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_GET_CAPABILITIES CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_WAVE_SET_STATE CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x0004, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_GET_STATE CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x0005, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_GET_POSITION CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x0006, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_SET_VOLUME CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x0007, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_WAVE_GET_VOLUME CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x0008, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_WAVE_SET_PITCH CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x0009, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_GET_PITCH CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x000A, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_SET_PLAYBACK_RATE CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x000B, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_GET_PLAYBACK_RATE CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x000C, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_PLAY CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x000D, METHOD_IN_DIRECT, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_RECORD CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x000E, METHOD_OUT_DIRECT, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_BREAK_LOOP CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x000F, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_WAVE_SET_LOW_PRIORITY CTL_CODE(IOCTL_SOUND_BASE, IOCTL_WAVE_BASE + 0x0010, METHOD_BUFFERED, FILE_WRITE_ACCESS)
// MIDI device driver IOCTLs
#define IOCTL_MIDI_GET_CAPABILITIES CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MIDI_SET_STATE CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0002, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_GET_STATE CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0003, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_SET_VOLUME CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MIDI_GET_VOLUME CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MIDI_PLAY CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0006, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_RECORD CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0007, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_CACHE_PATCHES CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0008, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_CACHE_DRUM_PATCHES CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0009, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#endif

View file

@ -23,15 +23,17 @@
#include <mmddk.h>
// This needs to be done to get winioctl.h to work:
typedef unsigned __int64 DWORD64, *PDWORD64;
//typedef unsigned __int64 DWORD64, *PDWORD64;
#include <winioctl.h>
//#include "mmddk.h"
#include "mmdef.h"
/*
#define SOUND_MAX_DEVICE_NAME 1024 // GUESSWORK
#define SOUND_MAX_DEVICES 256 // GUESSWORK
*/
// If the root is \Device and the Device type is
// WaveIn and the device number is 2, the full name is \Device\WaveIn2
@ -49,7 +51,7 @@ typedef unsigned __int64 DWORD64, *PDWORD64;
#define AUX_DEVICE_NAME "\\Device\\MMAux"
#define AUX_DEVICE_NAME_U L"\\Device\\MMAux"
/*
#define IOCTL_SOUND_BASE FILE_DEVICE_SOUND
#define IOCTL_WAVE_BASE 0x0000
#define IOCTL_MIDI_BASE 0x0080
@ -80,11 +82,11 @@ typedef unsigned __int64 DWORD64, *PDWORD64;
#define IOCTL_MIDI_GET_STATE CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0003, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_SET_VOLUME CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MIDI_GET_VOLUME CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MIDI_PLAY CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0006, METHOD_NEITHER, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_PLAY CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0006, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_RECORD CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0007, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_CACHE_PATCHES CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0008, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MIDI_CACHE_DRUM_PATCHES CTL_CODE(IOCTL_SOUND_BASE, IOCTL_MIDI_BASE + 0x0009, METHOD_BUFFERED, FILE_WRITE_ACCESS)
*/
CRITICAL_SECTION CS; // Serialize access to device lists

View file

@ -60,28 +60,42 @@ MMRESULT OpenDevice(UINT DeviceType, DWORD ID, PHANDLE pDeviceHandle,
DWORD Access)
{
printf("OpenDevice()\n");
WCHAR Name[SOUND_MAX_DEVICE_NAME];
WCHAR DeviceName[SOUND_MAX_DEVICE_NAME];
*pDeviceHandle = INVALID_HANDLE_VALUE;
if (ID > SOUND_MAX_DEVICES)
return MMSYSERR_BADDEVICEID;
wsprintf(Name, L"\\\\.%ls%d",
(DeviceType == WaveOutDevice ? WAVE_OUT_DEVICE_NAME_U :
DeviceType == WaveInDevice ? WAVE_IN_DEVICE_NAME_U :
DeviceType == MidiOutDevice ? MIDI_OUT_DEVICE_NAME_U :
DeviceType == MidiInDevice ? MIDI_IN_DEVICE_NAME_U :
AUX_DEVICE_NAME_U) + strlen("\\Device"), ID);
printf("Attempting to open %S\n", Name);
switch(DeviceType)
{
case WaveOutDevice :
wsprintf(DeviceName, L"\\\\.%ls%d", WAVE_OUT_DEVICE_NAME_U + strlen("\\Device"), ID);
break;
case WaveInDevice :
wsprintf(DeviceName, L"\\\\.%ls%d", WAVE_IN_DEVICE_NAME_U + strlen("\\Device"), ID);
break;
case MidiOutDevice :
wsprintf(DeviceName, L"\\\\.%ls%d", MIDI_OUT_DEVICE_NAME_U + strlen("\\Device"), ID);
break;
case MidiInDevice :
wsprintf(DeviceName, L"\\\\.%ls%d", MIDI_IN_DEVICE_NAME_U + strlen("\\Device"), ID);
break;
default : // Aux
wsprintf(DeviceName, L"\\\\.%ls%d", AUX_DEVICE_NAME_U + strlen("\\Device"), ID);
};
*pDeviceHandle = CreateFile(Name, Access, FILE_SHARE_WRITE, NULL,
printf("Attempting to open %S\n", DeviceName);
*pDeviceHandle = CreateFile(DeviceName, Access, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, Access != GENERIC_READ ? FILE_FLAG_OVERLAPPED : 0,
NULL);
printf("DeviceHandle == 0x%x\n", (int)*pDeviceHandle);
return *pDeviceHandle != INVALID_HANDLE_VALUE ? MMSYSERR_NOERROR : TranslateStatus();
if (pDeviceHandle == INVALID_HANDLE_VALUE)
return TranslateStatus();
return MMSYSERR_NOERROR;
}

View file

@ -0,0 +1,9 @@
*.a
*.d
*.o
*.dll
*.coff
*.sym
*.map
*.tmp
temp.exp

View file

@ -0,0 +1,27 @@
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = msacm32.dll
IMPORTS = winmm user32 advapi32 kernel32
ALTNAMES = msacm.dll
SPEC_SRCS16 = $(ALTNAMES:.dll=.spec)
C_SRCS = \
driver.c \
filter.c \
format.c \
internal.c \
msacm32_main.c \
pcmconverter.c \
stream.c
C_SRCS16 = \
msacm_main.c
RC_SRCS = msacm.rc
@MAKE_DLL_RULES@
### Dependencies:

View file

@ -0,0 +1,21 @@
# $Id: Makefile.ros,v 1.1 2004/03/10 15:22:44 silverblade Exp $
TARGET_NAME = msacm32
TARGET_OBJECTS = driver.o filter.o format.o internal.o msacm32_main.o pcmconverter.o stream.o
TARGET_CFLAGS = -D__REACTOS__
TARGET_SDKLIBS = winmm.a libwine.a advapi32.a kernel32.a ws2_32.a wine_uuid.a ntdll.a
TARGET_BASE = 0x77300000
TARGET_RC_SRCS = msacm.rc
TARGET_RC_BINSRC = msacm.rc
TARGET_RC_BINARIES =
default: all
DEP_OBJECTS = $(TARGET_OBJECTS)
include $(TOOLS_PATH)/depend.mk

View file

@ -0,0 +1,21 @@
# $Id: Makefile.ros-template,v 1.1 2004/03/10 15:22:44 silverblade Exp $
TARGET_NAME = iphlpapi
TARGET_OBJECTS = @C_SRCS@
TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__
TARGET_SDKLIBS = @IMPORTS@ libwine.a advapi32.a kernel32.a ws2_32.a wine_uuid.a ntdll.a
TARGET_BASE = 0x77300000
TARGET_RC_SRCS = @RC_SRCS@
TARGET_RC_BINSRC = @RC_BINSRC@
TARGET_RC_BINARIES = @RC_BINARIES@
default: all
DEP_OBJECTS = $(TARGET_OBJECTS)
include $(TOOLS_PATH)/depend.mk

400
reactos/lib/msacm/driver.c Normal file
View file

@ -0,0 +1,400 @@
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/*
* MSACM32 library
*
* Copyright 1998 Patrik Stridvall
* 1999 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "winreg.h"
#include "mmsystem.h"
#include "mmreg.h"
#include "msacm.h"
#include "msacmdrv.h"
#include "wineacm.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msacm);
/***********************************************************************
* acmDriverAddA (MSACM32.@)
*/
MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule,
LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
{
if (!phadid)
return MMSYSERR_INVALPARAM;
/* Check if any unknown flags */
if (fdwAdd &
~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND|
ACM_DRIVERADDF_GLOBAL))
return MMSYSERR_INVALFLAG;
/* Check if any incompatible flags */
if ((fdwAdd & ACM_DRIVERADDF_FUNCTION) &&
(fdwAdd & ACM_DRIVERADDF_NOTIFYHWND))
return MMSYSERR_INVALFLAG;
/* FIXME: in fact, should GetModuleFileName(hinstModule) and do a
* LoadDriver on it, to be sure we can call SendDriverMessage on the
* hDrvr handle.
*/
*phadid = (HACMDRIVERID) MSACM_RegisterDriver(NULL, NULL, hinstModule);
/* FIXME: lParam, dwPriority and fdwAdd ignored */
return MMSYSERR_NOERROR;
}
/***********************************************************************
* acmDriverAddW (MSACM32.@)
* FIXME
* Not implemented
*/
MMRESULT WINAPI acmDriverAddW(PHACMDRIVERID phadid, HINSTANCE hinstModule,
LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
{
FIXME("(%p, %p, %ld, %ld, %ld): stub\n",
phadid, hinstModule, lParam, dwPriority, fdwAdd);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmDriverClose (MSACM32.@)
*/
MMRESULT WINAPI acmDriverClose(HACMDRIVER had, DWORD fdwClose)
{
PWINE_ACMDRIVER pad;
PWINE_ACMDRIVERID padid;
PWINE_ACMDRIVER* tpad;
if (fdwClose)
return MMSYSERR_INVALFLAG;
pad = MSACM_GetDriver(had);
if (!pad)
return MMSYSERR_INVALHANDLE;
padid = pad->obj.pACMDriverID;
/* remove driver from list */
for (tpad = &(padid->pACMDriverList); *tpad; *tpad = (*tpad)->pNextACMDriver) {
if (*tpad == pad) {
*tpad = (*tpad)->pNextACMDriver;
break;
}
}
/* close driver if it has been opened */
if (pad->hDrvr && !padid->hInstModule)
CloseDriver(pad->hDrvr, 0, 0);
HeapFree(MSACM_hHeap, 0, pad);
return MMSYSERR_NOERROR;
}
/***********************************************************************
* acmDriverDetailsA (MSACM32.@)
*/
MMRESULT WINAPI acmDriverDetailsA(HACMDRIVERID hadid, PACMDRIVERDETAILSA padd, DWORD fdwDetails)
{
MMRESULT mmr;
ACMDRIVERDETAILSW addw;
addw.cbStruct = sizeof(addw);
mmr = acmDriverDetailsW(hadid, &addw, fdwDetails);
if (mmr == 0) {
padd->fccType = addw.fccType;
padd->fccComp = addw.fccComp;
padd->wMid = addw.wMid;
padd->wPid = addw.wPid;
padd->vdwACM = addw.vdwACM;
padd->vdwDriver = addw.vdwDriver;
padd->fdwSupport = addw.fdwSupport;
padd->cFormatTags = addw.cFormatTags;
padd->cFilterTags = addw.cFilterTags;
padd->hicon = addw.hicon;
WideCharToMultiByte( CP_ACP, 0, addw.szShortName, -1, padd->szShortName,
sizeof(padd->szShortName), NULL, NULL );
WideCharToMultiByte( CP_ACP, 0, addw.szLongName, -1, padd->szLongName,
sizeof(padd->szLongName), NULL, NULL );
WideCharToMultiByte( CP_ACP, 0, addw.szCopyright, -1, padd->szCopyright,
sizeof(padd->szCopyright), NULL, NULL );
WideCharToMultiByte( CP_ACP, 0, addw.szLicensing, -1, padd->szLicensing,
sizeof(padd->szLicensing), NULL, NULL );
WideCharToMultiByte( CP_ACP, 0, addw.szFeatures, -1, padd->szFeatures,
sizeof(padd->szFeatures), NULL, NULL );
}
return mmr;
}
/***********************************************************************
* acmDriverDetailsW (MSACM32.@)
*/
MMRESULT WINAPI acmDriverDetailsW(HACMDRIVERID hadid, PACMDRIVERDETAILSW padd, DWORD fdwDetails)
{
HACMDRIVER acmDrvr;
MMRESULT mmr;
if (fdwDetails)
return MMSYSERR_INVALFLAG;
mmr = acmDriverOpen(&acmDrvr, hadid, 0);
if (mmr == MMSYSERR_NOERROR) {
mmr = (MMRESULT)MSACM_Message(acmDrvr, ACMDM_DRIVER_DETAILS, (LPARAM)padd, 0);
acmDriverClose(acmDrvr, 0);
}
return mmr;
}
/***********************************************************************
* acmDriverEnum (MSACM32.@)
*/
MMRESULT WINAPI acmDriverEnum(ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum)
{
PWINE_ACMDRIVERID padid;
DWORD fdwSupport;
if (!fnCallback) return MMSYSERR_INVALPARAM;
if (fdwEnum & ~(ACM_DRIVERENUMF_NOLOCAL|ACM_DRIVERENUMF_DISABLED))
return MMSYSERR_INVALFLAG;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
fdwSupport = padid->fdwSupport;
if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) {
if (fdwEnum & ACM_DRIVERENUMF_DISABLED)
fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
else
continue;
}
if (!(*fnCallback)((HACMDRIVERID)padid, dwInstance, fdwSupport))
break;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* acmDriverID (MSACM32.@)
*/
MMRESULT WINAPI acmDriverID(HACMOBJ hao, PHACMDRIVERID phadid, DWORD fdwDriverID)
{
PWINE_ACMOBJ pao;
if (!phadid)
return MMSYSERR_INVALPARAM;
if (fdwDriverID)
return MMSYSERR_INVALFLAG;
pao = MSACM_GetObj(hao, WINE_ACMOBJ_DONTCARE);
if (!pao)
return MMSYSERR_INVALHANDLE;
*phadid = (HACMDRIVERID) pao->pACMDriverID;
return MMSYSERR_NOERROR;
}
/***********************************************************************
* acmDriverMessage (MSACM32.@)
*
*/
LRESULT WINAPI acmDriverMessage(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
{
if ((uMsg >= ACMDM_USER && uMsg < ACMDM_RESERVED_LOW) ||
uMsg == ACMDM_DRIVER_ABOUT ||
uMsg == DRV_QUERYCONFIGURE ||
uMsg == DRV_CONFIGURE)
return MSACM_Message(had, uMsg, lParam1, lParam2);
return MMSYSERR_INVALPARAM;
}
/***********************************************************************
* acmDriverOpen (MSACM32.@)
*/
MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen)
{
PWINE_ACMDRIVERID padid;
PWINE_ACMDRIVER pad = NULL;
MMRESULT ret;
TRACE("(%p, %p, %08lu)\n", phad, hadid, fdwOpen);
if (!phad)
return MMSYSERR_INVALPARAM;
if (fdwOpen)
return MMSYSERR_INVALFLAG;
padid = MSACM_GetDriverID(hadid);
if (!padid)
return MMSYSERR_INVALHANDLE;
pad = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER));
if (!pad)
return MMSYSERR_NOMEM;
pad->obj.dwType = WINE_ACMOBJ_DRIVER;
pad->obj.pACMDriverID = padid;
if (!(pad->hDrvr = (HDRVR)padid->hInstModule))
{
ACMDRVOPENDESCW adod;
int len;
/* this is not an externally added driver... need to actually load it */
if (!padid->pszDriverAlias)
{
ret = MMSYSERR_ERROR;
goto gotError;
}
adod.cbStruct = sizeof(adod);
adod.fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
adod.fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
adod.dwVersion = acmGetVersion();
adod.dwFlags = fdwOpen;
adod.dwError = 0;
len = strlen("Drivers32") + 1;
adod.pszSectionName = HeapAlloc(MSACM_hHeap, 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, "Drivers32", -1, (LPWSTR)adod.pszSectionName, len);
adod.pszAliasName = padid->pszDriverAlias;
adod.dnDevNode = 0;
pad->hDrvr = OpenDriver(padid->pszDriverAlias, NULL, (DWORD)&adod);
HeapFree(MSACM_hHeap, 0, (LPWSTR)adod.pszSectionName);
if (!pad->hDrvr)
{
ret = adod.dwError;
goto gotError;
}
}
/* insert new pad at beg of list */
pad->pNextACMDriver = padid->pACMDriverList;
padid->pACMDriverList = pad;
/* FIXME: Create a WINE_ACMDRIVER32 */
*phad = (HACMDRIVER)pad;
TRACE("'%s' => %08lx\n", debugstr_w(padid->pszDriverAlias), (DWORD)pad);
return MMSYSERR_NOERROR;
gotError:
if (pad && !pad->hDrvr)
HeapFree(MSACM_hHeap, 0, pad);
return ret;
}
/***********************************************************************
* acmDriverPriority (MSACM32.@)
*/
MMRESULT WINAPI acmDriverPriority(HACMDRIVERID hadid, DWORD dwPriority, DWORD fdwPriority)
{
PWINE_ACMDRIVERID padid;
CHAR szSubKey[17];
CHAR szBuffer[256];
LONG lBufferLength = sizeof(szBuffer);
LONG lError;
HKEY hPriorityKey;
DWORD dwPriorityCounter;
padid = MSACM_GetDriverID(hadid);
if (!padid)
return MMSYSERR_INVALHANDLE;
/* Check for unknown flags */
if (fdwPriority &
~(ACM_DRIVERPRIORITYF_ENABLE|ACM_DRIVERPRIORITYF_DISABLE|
ACM_DRIVERPRIORITYF_BEGIN|ACM_DRIVERPRIORITYF_END))
return MMSYSERR_INVALFLAG;
/* Check for incompatible flags */
if ((fdwPriority & ACM_DRIVERPRIORITYF_ENABLE) &&
(fdwPriority & ACM_DRIVERPRIORITYF_DISABLE))
return MMSYSERR_INVALFLAG;
/* Check for incompatible flags */
if ((fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) &&
(fdwPriority & ACM_DRIVERPRIORITYF_END))
return MMSYSERR_INVALFLAG;
lError = RegOpenKeyA(HKEY_CURRENT_USER,
"Software\\Microsoft\\Multimedia\\"
"Audio Compression Manager\\Priority v4.00",
&hPriorityKey
);
/* FIXME: Create key */
if (lError != ERROR_SUCCESS)
return MMSYSERR_ERROR;
for (dwPriorityCounter = 1; ; dwPriorityCounter++) {
snprintf(szSubKey, 17, "Priority%ld", dwPriorityCounter);
lError = RegQueryValueA(hPriorityKey, szSubKey, szBuffer, &lBufferLength);
if (lError != ERROR_SUCCESS)
break;
FIXME("(%p, %ld, %ld): stub (partial)\n",
hadid, dwPriority, fdwPriority);
break;
}
RegCloseKey(hPriorityKey);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmDriverRemove (MSACM32.@)
*/
MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove)
{
PWINE_ACMDRIVERID padid;
padid = MSACM_GetDriverID(hadid);
if (!padid)
return MMSYSERR_INVALHANDLE;
if (fdwRemove)
return MMSYSERR_INVALFLAG;
MSACM_UnregisterDriver(padid);
return MMSYSERR_NOERROR;
}

454
reactos/lib/msacm/filter.c Normal file
View file

@ -0,0 +1,454 @@
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/*
* MSACM32 library
*
* Copyright 1998 Patrik Stridvall
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winerror.h"
#include "mmsystem.h"
#include "mmreg.h"
#include "msacm.h"
#include "msacmdrv.h"
#include "wineacm.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msacm);
/***********************************************************************
* acmFilterChooseA (MSACM32.@)
*/
MMRESULT WINAPI acmFilterChooseA(PACMFILTERCHOOSEA pafltrc)
{
FIXME("(%p): stub\n", pafltrc);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFilterChooseW (MSACM32.@)
*/
MMRESULT WINAPI acmFilterChooseW(PACMFILTERCHOOSEW pafltrc)
{
FIXME("(%p): stub\n", pafltrc);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFilterDetailsA (MSACM32.@)
*/
MMRESULT WINAPI acmFilterDetailsA(HACMDRIVER had, PACMFILTERDETAILSA pafd,
DWORD fdwDetails)
{
ACMFILTERDETAILSW afdw;
MMRESULT mmr;
memset(&afdw, 0, sizeof(afdw));
afdw.cbStruct = sizeof(afdw);
afdw.dwFilterIndex = pafd->dwFilterIndex;
afdw.dwFilterTag = pafd->dwFilterTag;
afdw.pwfltr = pafd->pwfltr;
afdw.cbwfltr = pafd->cbwfltr;
mmr = acmFilterDetailsW(had, &afdw, fdwDetails);
if (mmr == MMSYSERR_NOERROR) {
pafd->dwFilterTag = afdw.dwFilterTag;
pafd->fdwSupport = afdw.fdwSupport;
WideCharToMultiByte( CP_ACP, 0, afdw.szFilter, -1, pafd->szFilter,
sizeof(pafd->szFilter), NULL, NULL );
}
return mmr;
}
/***********************************************************************
* acmFilterDetailsW (MSACM32.@)
*/
MMRESULT WINAPI acmFilterDetailsW(HACMDRIVER had, PACMFILTERDETAILSW pafd,
DWORD fdwDetails)
{
MMRESULT mmr;
ACMFILTERTAGDETAILSA aftd;
TRACE("(%p, %p, %ld)\n", had, pafd, fdwDetails);
memset(&aftd, 0, sizeof(aftd));
aftd.cbStruct = sizeof(aftd);
if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
switch (fdwDetails) {
case ACM_FILTERDETAILSF_FILTER:
if (pafd->dwFilterTag != pafd->pwfltr->dwFilterTag) {
mmr = MMSYSERR_INVALPARAM;
break;
}
if (had == NULL) {
PWINE_ACMDRIVERID padid;
mmr = ACMERR_NOTPOSSIBLE;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS,
(LPARAM)pafd, (LPARAM)fdwDetails);
acmDriverClose(had, 0);
if (mmr == MMSYSERR_NOERROR) break;
}
}
} else {
mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, (LPARAM)pafd, fdwDetails);
}
break;
case ACM_FILTERDETAILSF_INDEX:
/* should check pafd->dwFilterIndex < aftd->cStandardFilters */
mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, (LPARAM)pafd, fdwDetails);
break;
default:
WARN("Unknown fdwDetails %08lx\n", fdwDetails);
mmr = MMSYSERR_INVALFLAG;
break;
}
TRACE("=> %d\n", mmr);
return mmr;
}
struct MSACM_FilterEnumWtoA_Instance {
PACMFILTERDETAILSA pafda;
DWORD dwInstance;
ACMFILTERENUMCBA fnCallback;
};
static BOOL CALLBACK MSACM_FilterEnumCallbackWtoA(HACMDRIVERID hadid,
PACMFILTERDETAILSW pafdw,
DWORD dwInstance,
DWORD fdwSupport)
{
struct MSACM_FilterEnumWtoA_Instance* pafei;
pafei = (struct MSACM_FilterEnumWtoA_Instance*)dwInstance;
pafei->pafda->dwFilterIndex = pafdw->dwFilterIndex;
pafei->pafda->dwFilterTag = pafdw->dwFilterTag;
pafei->pafda->fdwSupport = pafdw->fdwSupport;
WideCharToMultiByte( CP_ACP, 0, pafdw->szFilter, -1, pafei->pafda->szFilter,
sizeof(pafei->pafda->szFilter), NULL, NULL );
return (pafei->fnCallback)(hadid, pafei->pafda,
pafei->dwInstance, fdwSupport);
}
/***********************************************************************
* acmFilterEnumA (MSACM32.@)
*/
MMRESULT WINAPI acmFilterEnumA(HACMDRIVER had, PACMFILTERDETAILSA pafda,
ACMFILTERENUMCBA fnCallback, DWORD dwInstance,
DWORD fdwEnum)
{
ACMFILTERDETAILSW afdw;
struct MSACM_FilterEnumWtoA_Instance afei;
memset(&afdw, 0, sizeof(afdw));
afdw.cbStruct = sizeof(afdw);
afdw.dwFilterIndex = pafda->dwFilterIndex;
afdw.dwFilterTag = pafda->dwFilterTag;
afdw.pwfltr = pafda->pwfltr;
afdw.cbwfltr = pafda->cbwfltr;
afei.pafda = pafda;
afei.dwInstance = dwInstance;
afei.fnCallback = fnCallback;
return acmFilterEnumW(had, &afdw, MSACM_FilterEnumCallbackWtoA,
(DWORD)&afei, fdwEnum);
}
static BOOL MSACM_FilterEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had,
PACMFILTERDETAILSW pafd,
ACMFILTERENUMCBW fnCallback, DWORD dwInstance,
DWORD fdwEnum)
{
ACMFILTERTAGDETAILSW aftd;
int i, j;
for (i = 0; i < padid->cFilterTags; i++) {
memset(&aftd, 0, sizeof(aftd));
aftd.cbStruct = sizeof(aftd);
aftd.dwFilterTagIndex = i;
if (acmFilterTagDetailsW(had, &aftd, ACM_FILTERTAGDETAILSF_INDEX) != MMSYSERR_NOERROR)
continue;
if ((fdwEnum & ACM_FILTERENUMF_DWFILTERTAG) &&
aftd.dwFilterTag != pafd->pwfltr->dwFilterTag)
continue;
for (j = 0; j < aftd.cStandardFilters; j++) {
pafd->dwFilterIndex = j;
pafd->dwFilterTag = aftd.dwFilterTag;
if (acmFilterDetailsW(had, pafd, ACM_FILTERDETAILSF_INDEX) != MMSYSERR_NOERROR)
continue;
if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
return FALSE;
}
}
return TRUE;
}
/***********************************************************************
* acmFilterEnumW (MSACM32.@)
*/
MMRESULT WINAPI acmFilterEnumW(HACMDRIVER had, PACMFILTERDETAILSW pafd,
ACMFILTERENUMCBW fnCallback, DWORD dwInstance,
DWORD fdwEnum)
{
PWINE_ACMDRIVERID padid;
BOOL ret;
TRACE("(%p, %p, %p, %ld, %ld)\n",
had, pafd, fnCallback, dwInstance, fdwEnum);
if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
if (fdwEnum & ~(ACM_FILTERENUMF_DWFILTERTAG))
FIXME("Unsupported fdwEnum values\n");
if (had) {
HACMDRIVERID hadid;
if (acmDriverID((HACMOBJ)had, &hadid, 0) != MMSYSERR_NOERROR)
return MMSYSERR_INVALHANDLE;
MSACM_FilterEnumHelper(MSACM_GetDriverID(hadid), had, pafd,
fnCallback, dwInstance, fdwEnum);
return MMSYSERR_NOERROR;
}
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ||
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
continue;
ret = MSACM_FilterEnumHelper(padid, had, pafd,
fnCallback, dwInstance, fdwEnum);
acmDriverClose(had, 0);
if (!ret) break;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* acmFilterTagDetailsA (MSACM32.@)
*/
MMRESULT WINAPI acmFilterTagDetailsA(HACMDRIVER had, PACMFILTERTAGDETAILSA paftda,
DWORD fdwDetails)
{
ACMFILTERTAGDETAILSW aftdw;
MMRESULT mmr;
memset(&aftdw, 0, sizeof(aftdw));
aftdw.cbStruct = sizeof(aftdw);
aftdw.dwFilterTagIndex = paftda->dwFilterTagIndex;
aftdw.dwFilterTag = paftda->dwFilterTag;
mmr = acmFilterTagDetailsW(had, &aftdw, fdwDetails);
if (mmr == MMSYSERR_NOERROR) {
paftda->dwFilterTag = aftdw.dwFilterTag;
paftda->dwFilterTagIndex = aftdw.dwFilterTagIndex;
paftda->cbFilterSize = aftdw.cbFilterSize;
paftda->fdwSupport = aftdw.fdwSupport;
paftda->cStandardFilters = aftdw.cStandardFilters;
WideCharToMultiByte( CP_ACP, 0, aftdw.szFilterTag, -1, paftda->szFilterTag,
sizeof(paftda->szFilterTag), NULL, NULL );
}
return mmr;
}
/***********************************************************************
* acmFilterTagDetailsW (MSACM32.@)
*/
MMRESULT WINAPI acmFilterTagDetailsW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd,
DWORD fdwDetails)
{
PWINE_ACMDRIVERID padid;
MMRESULT mmr;
TRACE("(%p, %p, %ld)\n", had, paftd, fdwDetails);
if (fdwDetails & ~(ACM_FILTERTAGDETAILSF_FILTERTAG|ACM_FILTERTAGDETAILSF_INDEX|
ACM_FILTERTAGDETAILSF_LARGESTSIZE))
return MMSYSERR_INVALFLAG;
switch (fdwDetails) {
case ACM_FILTERTAGDETAILSF_FILTERTAG:
if (had == NULL) {
mmr = ACMERR_NOTPOSSIBLE;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails);
acmDriverClose(had, 0);
if (mmr == MMSYSERR_NOERROR) break;
}
}
} else {
mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails);
}
break;
case ACM_FILTERTAGDETAILSF_INDEX:
/* FIXME should check paftd->dwFilterTagIndex < add.cFilterTags */
mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails);
break;
case ACM_FILTERTAGDETAILSF_LARGESTSIZE:
if (had == NULL) {
ACMFILTERTAGDETAILSW tmp;
DWORD ft = paftd->dwFilterTag;
mmr = ACMERR_NOTPOSSIBLE;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
memset(&tmp, 0, sizeof(tmp));
tmp.cbStruct = sizeof(tmp);
tmp.dwFilterTag = ft;
if (MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
(LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) {
if (mmr == ACMERR_NOTPOSSIBLE ||
paftd->cbFilterSize < tmp.cbFilterSize) {
*paftd = tmp;
mmr = MMSYSERR_NOERROR;
}
}
acmDriverClose(had, 0);
}
}
} else {
mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails);
}
break;
default:
WARN("Unsupported fdwDetails=%08lx\n", fdwDetails);
mmr = MMSYSERR_ERROR;
}
if (mmr == MMSYSERR_NOERROR &&
paftd->dwFilterTag == WAVE_FORMAT_PCM && paftd->szFilterTag[0] == 0)
MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFilterTag,
sizeof(paftd->szFilterTag)/sizeof(WCHAR) );
return mmr;
}
struct MSACM_FilterTagEnumWtoA_Instance {
PACMFILTERTAGDETAILSA paftda;
DWORD dwInstance;
ACMFILTERTAGENUMCBA fnCallback;
};
static BOOL CALLBACK MSACM_FilterTagEnumCallbackWtoA(HACMDRIVERID hadid,
PACMFILTERTAGDETAILSW paftdw,
DWORD dwInstance,
DWORD fdwSupport)
{
struct MSACM_FilterTagEnumWtoA_Instance* paftei;
paftei = (struct MSACM_FilterTagEnumWtoA_Instance*)dwInstance;
paftei->paftda->dwFilterTagIndex = paftdw->dwFilterTagIndex;
paftei->paftda->dwFilterTag = paftdw->dwFilterTag;
paftei->paftda->cbFilterSize = paftdw->cbFilterSize;
paftei->paftda->fdwSupport = paftdw->fdwSupport;
paftei->paftda->cStandardFilters = paftdw->cStandardFilters;
WideCharToMultiByte( CP_ACP, 0, paftdw->szFilterTag, -1, paftei->paftda->szFilterTag,
sizeof(paftei->paftda->szFilterTag), NULL, NULL );
return (paftei->fnCallback)(hadid, paftei->paftda,
paftei->dwInstance, fdwSupport);
}
/***********************************************************************
* acmFilterTagEnumA (MSACM32.@)
*/
MMRESULT WINAPI acmFilterTagEnumA(HACMDRIVER had, PACMFILTERTAGDETAILSA paftda,
ACMFILTERTAGENUMCBA fnCallback, DWORD dwInstance,
DWORD fdwEnum)
{
ACMFILTERTAGDETAILSW aftdw;
struct MSACM_FilterTagEnumWtoA_Instance aftei;
memset(&aftdw, 0, sizeof(aftdw));
aftdw.cbStruct = sizeof(aftdw);
aftdw.dwFilterTagIndex = paftda->dwFilterTagIndex;
aftdw.dwFilterTag = paftda->dwFilterTag;
aftei.paftda = paftda;
aftei.dwInstance = dwInstance;
aftei.fnCallback = fnCallback;
return acmFilterTagEnumW(had, &aftdw, MSACM_FilterTagEnumCallbackWtoA,
(DWORD)&aftei, fdwEnum);
}
/***********************************************************************
* acmFilterTagEnumW (MSACM32.@)
*/
MMRESULT WINAPI acmFilterTagEnumW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd,
ACMFILTERTAGENUMCBW fnCallback, DWORD dwInstance,
DWORD fdwEnum)
{
PWINE_ACMDRIVERID padid;
int i;
TRACE("(%p, %p, %p, %ld, %ld)\n",
had, paftd, fnCallback, dwInstance, fdwEnum);
if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM;
if (had) FIXME("had != NULL, not supported\n");
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
for (i = 0; i < padid->cFilterTags; i++) {
paftd->dwFilterTagIndex = i;
if (acmFilterTagDetailsW(had, paftd, ACM_FILTERTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) {
padid = NULL;
break;
}
}
}
}
acmDriverClose(had, 0);
}
return MMSYSERR_NOERROR;
}

832
reactos/lib/msacm/format.c Normal file
View file

@ -0,0 +1,832 @@
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/*
* MSACM32 library
*
* Copyright 1998 Patrik Stridvall
* 2000 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winerror.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "mmsystem.h"
#include "mmreg.h"
#include "msacm.h"
#include "msacmdrv.h"
#include "wineacm.h"
WINE_DEFAULT_DEBUG_CHANNEL(msacm);
static PACMFORMATCHOOSEA afc;
struct MSACM_FillFormatData {
HWND hWnd;
#define WINE_ACMFF_TAG 0
#define WINE_ACMFF_FORMAT 1
#define WINE_ACMFF_WFX 2
int mode;
char szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
PACMFORMATCHOOSEA afc;
DWORD ret;
};
static BOOL CALLBACK MSACM_FillFormatTagsCB(HACMDRIVERID hadid,
PACMFORMATTAGDETAILSA paftd,
DWORD dwInstance, DWORD fdwSupport)
{
struct MSACM_FillFormatData* affd = (struct MSACM_FillFormatData*)dwInstance;
switch (affd->mode) {
case WINE_ACMFF_TAG:
if (SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
CB_FINDSTRINGEXACT,
(WPARAM)-1, (LPARAM)paftd->szFormatTag) == CB_ERR)
SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
CB_ADDSTRING, 0, (DWORD)paftd->szFormatTag);
break;
case WINE_ACMFF_FORMAT:
if (strcmp(affd->szFormatTag, paftd->szFormatTag) == 0) {
HACMDRIVER had;
if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
ACMFORMATDETAILSA afd;
int i, idx;
MMRESULT mmr;
char buffer[ACMFORMATDETAILS_FORMAT_CHARS+16];
afd.cbStruct = sizeof(afd);
afd.dwFormatTag = paftd->dwFormatTag;
afd.pwfx = HeapAlloc(MSACM_hHeap, 0, paftd->cbFormatSize);
if (!afd.pwfx) return FALSE;
afd.pwfx->wFormatTag = paftd->dwFormatTag;
afd.pwfx->cbSize = paftd->cbFormatSize;
afd.cbwfx = paftd->cbFormatSize;
for (i = 0; i < paftd->cStandardFormats; i++) {
afd.dwFormatIndex = i;
mmr = acmFormatDetailsA(had, &afd, ACM_FORMATDETAILSF_INDEX);
if (mmr == MMSYSERR_NOERROR) {
strncpy(buffer, afd.szFormat, ACMFORMATTAGDETAILS_FORMATTAG_CHARS);
for (idx = strlen(buffer);
idx < ACMFORMATTAGDETAILS_FORMATTAG_CHARS; idx++)
buffer[idx] = ' ';
wsprintfA(buffer + ACMFORMATTAGDETAILS_FORMATTAG_CHARS,
"%d Ko/s",
(afd.pwfx->nAvgBytesPerSec + 512) / 1024);
SendDlgItemMessageA(affd->hWnd,
IDD_ACMFORMATCHOOSE_CMB_FORMAT,
CB_ADDSTRING, 0, (DWORD)buffer);
}
}
acmDriverClose(had, 0);
SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT,
CB_SETCURSEL, 0, 0);
HeapFree(MSACM_hHeap, 0, afd.pwfx);
}
}
break;
case WINE_ACMFF_WFX:
if (strcmp(affd->szFormatTag, paftd->szFormatTag) == 0) {
HACMDRIVER had;
if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
ACMFORMATDETAILSA afd;
afd.cbStruct = sizeof(afd);
afd.dwFormatTag = paftd->dwFormatTag;
afd.pwfx = affd->afc->pwfx;
afd.cbwfx = affd->afc->cbwfx;
afd.dwFormatIndex = SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT,
CB_GETCURSEL, 0, 0);
affd->ret = acmFormatDetailsA(had, &afd, ACM_FORMATDETAILSF_INDEX);
acmDriverClose(had, 0);
return TRUE;
}
}
break;
default:
FIXME("Unknown mode (%d)\n", affd->mode);
break;
}
return TRUE;
}
static BOOL MSACM_FillFormatTags(HWND hWnd)
{
ACMFORMATTAGDETAILSA aftd;
struct MSACM_FillFormatData affd;
memset(&aftd, 0, sizeof(aftd));
aftd.cbStruct = sizeof(aftd);
affd.hWnd = hWnd;
affd.mode = WINE_ACMFF_TAG;
acmFormatTagEnumA(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD)&affd, 0);
SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_SETCURSEL, 0, 0);
return TRUE;
}
static BOOL MSACM_FillFormat(HWND hWnd)
{
ACMFORMATTAGDETAILSA aftd;
struct MSACM_FillFormatData affd;
SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_RESETCONTENT, 0, 0);
memset(&aftd, 0, sizeof(aftd));
aftd.cbStruct = sizeof(aftd);
affd.hWnd = hWnd;
affd.mode = WINE_ACMFF_FORMAT;
SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
CB_GETLBTEXT,
SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
CB_GETCURSEL, 0, 0),
(DWORD)affd.szFormatTag);
acmFormatTagEnumA(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD)&affd, 0);
SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_SETCURSEL, 0, 0);
return TRUE;
}
static MMRESULT MSACM_GetWFX(HWND hWnd, PACMFORMATCHOOSEA afc)
{
ACMFORMATTAGDETAILSA aftd;
struct MSACM_FillFormatData affd;
memset(&aftd, 0, sizeof(aftd));
aftd.cbStruct = sizeof(aftd);
affd.hWnd = hWnd;
affd.mode = WINE_ACMFF_WFX;
affd.afc = afc;
affd.ret = MMSYSERR_NOERROR;
SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
CB_GETLBTEXT,
SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
CB_GETCURSEL, 0, 0),
(DWORD)affd.szFormatTag);
acmFormatTagEnumA(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD)&affd, 0);
return affd.ret;
}
static INT_PTR CALLBACK FormatChooseDlgProc(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
TRACE("hwnd=%p msg=%i 0x%08x 0x%08lx\n", hWnd, msg, wParam, lParam );
switch (msg) {
case WM_INITDIALOG:
afc = (PACMFORMATCHOOSEA)lParam;
MSACM_FillFormatTags(hWnd);
MSACM_FillFormat(hWnd);
if ((afc->fdwStyle & ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP|
ACMFORMATCHOOSE_STYLEF_SHOWHELP)) != 0)
FIXME("Unsupported style %08lx\n", ((PACMFORMATCHOOSEA)lParam)->fdwStyle);
if (!(afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP))
ShowWindow(GetDlgItem(hWnd, IDD_ACMFORMATCHOOSE_BTN_HELP), SW_HIDE);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
EndDialog(hWnd, MSACM_GetWFX(hWnd, afc));
return TRUE;
case IDCANCEL:
EndDialog(hWnd, ACMERR_CANCELED);
return TRUE;
case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
MSACM_FillFormat(hWnd);
break;
default:
TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
HIWORD(wParam), lParam);
break;
}
break;
case IDD_ACMFORMATCHOOSE_BTN_HELP:
if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP)
SendMessageA(afc->hwndOwner,
RegisterWindowMessageA(ACMHELPMSGSTRINGA), 0L, 0L);
break;
default:
TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
LOWORD(wParam), HIWORD(wParam), lParam);
break;
}
break;
case WM_CONTEXTMENU:
if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
SendMessageA(afc->hwndOwner,
RegisterWindowMessageA(ACMHELPMSGCONTEXTMENUA),
wParam, lParam);
break;
#if defined(WM_CONTEXTHELP)
case WM_CONTEXTHELP:
if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
SendMessageA(afc->hwndOwner,
RegisterWindowMessageA(ACMHELPMSGCONTEXTHELPA),
wParam, lParam);
break;
#endif
default:
TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08x 0x%08lx\n",
hWnd, msg, wParam, lParam );
break;
}
return FALSE;
}
/***********************************************************************
* acmFormatChooseA (MSACM32.@)
*/
MMRESULT WINAPI acmFormatChooseA(PACMFORMATCHOOSEA pafmtc)
{
return DialogBoxParamA(MSACM_hInstance32, MAKEINTRESOURCEA(DLG_ACMFORMATCHOOSE_ID),
pafmtc->hwndOwner, FormatChooseDlgProc, (INT)pafmtc);
}
/***********************************************************************
* acmFormatChooseW (MSACM32.@)
*/
MMRESULT WINAPI acmFormatChooseW(PACMFORMATCHOOSEW pafmtc)
{
FIXME("(%p): stub\n", pafmtc);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFormatDetailsA (MSACM32.@)
*/
MMRESULT WINAPI acmFormatDetailsA(HACMDRIVER had, PACMFORMATDETAILSA pafd,
DWORD fdwDetails)
{
ACMFORMATDETAILSW afdw;
MMRESULT mmr;
memset(&afdw, 0, sizeof(afdw));
afdw.cbStruct = sizeof(afdw);
afdw.dwFormatIndex = pafd->dwFormatIndex;
afdw.dwFormatTag = pafd->dwFormatTag;
afdw.pwfx = pafd->pwfx;
afdw.cbwfx = pafd->cbwfx;
mmr = acmFormatDetailsW(had, &afdw, fdwDetails);
if (mmr == MMSYSERR_NOERROR) {
pafd->dwFormatTag = afdw.dwFormatTag;
pafd->fdwSupport = afdw.fdwSupport;
WideCharToMultiByte( CP_ACP, 0, afdw.szFormat, -1,
pafd->szFormat, sizeof(pafd->szFormat), NULL, NULL );
}
return mmr;
}
/***********************************************************************
* acmFormatDetailsW (MSACM32.@)
*/
MMRESULT WINAPI acmFormatDetailsW(HACMDRIVER had, PACMFORMATDETAILSW pafd, DWORD fdwDetails)
{
MMRESULT mmr;
static WCHAR fmt1[] = {'%','d',' ','H','z',0};
static WCHAR fmt2[] = {';',' ','%','d',' ','b','i','t','s',0};
ACMFORMATTAGDETAILSA aftd;
TRACE("(%p, %p, %ld)\n", had, pafd, fdwDetails);
memset(&aftd, 0, sizeof(aftd));
aftd.cbStruct = sizeof(aftd);
if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
switch (fdwDetails) {
case ACM_FORMATDETAILSF_FORMAT:
if (pafd->dwFormatTag != pafd->pwfx->wFormatTag) {
mmr = MMSYSERR_INVALPARAM;
break;
}
if (had == NULL) {
PWINE_ACMDRIVERID padid;
mmr = ACMERR_NOTPOSSIBLE;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
acmDriverClose(had, 0);
if (mmr == MMSYSERR_NOERROR) break;
}
}
} else {
mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
}
break;
case ACM_FORMATDETAILSF_INDEX:
/* should check pafd->dwFormatIndex < aftd->cStandardFormats */
mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
break;
default:
WARN("Unknown fdwDetails %08lx\n", fdwDetails);
mmr = MMSYSERR_INVALFLAG;
break;
}
if (mmr == MMSYSERR_NOERROR && pafd->szFormat[0] == (WCHAR)0) {
wsprintfW(pafd->szFormat, fmt1, pafd->pwfx->nSamplesPerSec);
if (pafd->pwfx->wBitsPerSample) {
wsprintfW(pafd->szFormat + lstrlenW(pafd->szFormat), fmt2,
pafd->pwfx->wBitsPerSample);
}
MultiByteToWideChar( CP_ACP, 0, (pafd->pwfx->nChannels == 1) ? "; Mono" : "; Stereo", -1,
pafd->szFormat + strlenW(pafd->szFormat),
sizeof(pafd->szFormat)/sizeof(WCHAR) - strlenW(pafd->szFormat) );
}
TRACE("=> %d\n", mmr);
return mmr;
}
struct MSACM_FormatEnumWtoA_Instance {
PACMFORMATDETAILSA pafda;
DWORD dwInstance;
ACMFORMATENUMCBA fnCallback;
};
static BOOL CALLBACK MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid,
PACMFORMATDETAILSW pafdw,
DWORD dwInstance,
DWORD fdwSupport)
{
struct MSACM_FormatEnumWtoA_Instance* pafei;
pafei = (struct MSACM_FormatEnumWtoA_Instance*)dwInstance;
pafei->pafda->dwFormatIndex = pafdw->dwFormatIndex;
pafei->pafda->dwFormatTag = pafdw->dwFormatTag;
pafei->pafda->fdwSupport = pafdw->fdwSupport;
WideCharToMultiByte( CP_ACP, 0, pafdw->szFormat, -1,
pafei->pafda->szFormat, sizeof(pafei->pafda->szFormat), NULL, NULL );
return (pafei->fnCallback)(hadid, pafei->pafda,
pafei->dwInstance, fdwSupport);
}
/***********************************************************************
* acmFormatEnumA (MSACM32.@)
*/
MMRESULT WINAPI acmFormatEnumA(HACMDRIVER had, PACMFORMATDETAILSA pafda,
ACMFORMATENUMCBA fnCallback, DWORD dwInstance,
DWORD fdwEnum)
{
ACMFORMATDETAILSW afdw;
struct MSACM_FormatEnumWtoA_Instance afei;
memset(&afdw, 0, sizeof(afdw));
afdw.cbStruct = sizeof(afdw);
afdw.dwFormatIndex = pafda->dwFormatIndex;
afdw.dwFormatTag = pafda->dwFormatTag;
afdw.pwfx = pafda->pwfx;
afdw.cbwfx = pafda->cbwfx;
afei.pafda = pafda;
afei.dwInstance = dwInstance;
afei.fnCallback = fnCallback;
return acmFormatEnumW(had, &afdw, MSACM_FormatEnumCallbackWtoA,
(DWORD)&afei, fdwEnum);
}
/***********************************************************************
* acmFormatEnumW (MSACM32.@)
*/
static BOOL MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had,
PACMFORMATDETAILSW pafd, PWAVEFORMATEX pwfxRef,
ACMFORMATENUMCBW fnCallback, DWORD dwInstance,
DWORD fdwEnum)
{
ACMFORMATTAGDETAILSW aftd;
int i, j;
for (i = 0; i < padid->cFormatTags; i++) {
memset(&aftd, 0, sizeof(aftd));
aftd.cbStruct = sizeof(aftd);
aftd.dwFormatTagIndex = i;
if (acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_INDEX) != MMSYSERR_NOERROR)
continue;
if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) && aftd.dwFormatTag != pwfxRef->wFormatTag)
continue;
for (j = 0; j < aftd.cStandardFormats; j++) {
pafd->dwFormatIndex = j;
pafd->dwFormatTag = aftd.dwFormatTag;
if (acmFormatDetailsW(had, pafd, ACM_FORMATDETAILSF_INDEX) != MMSYSERR_NOERROR)
continue;
if ((fdwEnum & ACM_FORMATENUMF_NCHANNELS) &&
pafd->pwfx->nChannels != pwfxRef->nChannels)
continue;
if ((fdwEnum & ACM_FORMATENUMF_NSAMPLESPERSEC) &&
pafd->pwfx->nSamplesPerSec != pwfxRef->nSamplesPerSec)
continue;
if ((fdwEnum & ACM_FORMATENUMF_WBITSPERSAMPLE) &&
pafd->pwfx->wBitsPerSample != pwfxRef->wBitsPerSample)
continue;
if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
!(pafd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_HARDWARE))
continue;
/* more checks to be done on fdwEnum */
if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
return FALSE;
}
/* the "formats" used by the filters are also reported */
}
return TRUE;
}
/**********************************************************************/
MMRESULT WINAPI acmFormatEnumW(HACMDRIVER had, PACMFORMATDETAILSW pafd,
ACMFORMATENUMCBW fnCallback, DWORD dwInstance,
DWORD fdwEnum)
{
PWINE_ACMDRIVERID padid;
WAVEFORMATEX wfxRef;
BOOL ret;
TRACE("(%p, %p, %p, %ld, %ld)\n",
had, pafd, fnCallback, dwInstance, fdwEnum);
if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
if (fdwEnum & (ACM_FORMATENUMF_WFORMATTAG|ACM_FORMATENUMF_NCHANNELS|
ACM_FORMATENUMF_NSAMPLESPERSEC|ACM_FORMATENUMF_WBITSPERSAMPLE|
ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST))
wfxRef = *pafd->pwfx;
if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
!(fdwEnum & (ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT)))
return MMSYSERR_INVALPARAM;
if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) &&
(pafd->dwFormatTag != pafd->pwfx->wFormatTag))
return MMSYSERR_INVALPARAM;
if (fdwEnum & (ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST|
ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT))
FIXME("Unsupported fdwEnum values %08lx\n", fdwEnum);
if (had) {
HACMDRIVERID hadid;
if (acmDriverID((HACMOBJ)had, &hadid, 0) != MMSYSERR_NOERROR)
return MMSYSERR_INVALHANDLE;
MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid), had, pafd, &wfxRef,
fnCallback, dwInstance, fdwEnum);
return MMSYSERR_NOERROR;
}
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ||
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
continue;
ret = MSACM_FormatEnumHelper(padid, had, pafd, &wfxRef,
fnCallback, dwInstance, fdwEnum);
acmDriverClose(had, 0);
if (!ret) break;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* acmFormatSuggest (MSACM32.@)
*/
MMRESULT WINAPI acmFormatSuggest(HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
PWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest)
{
ACMDRVFORMATSUGGEST adfg;
MMRESULT mmr;
TRACE("(%p, %p, %p, %ld, %ld)\n",
had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest);
if (fdwSuggest & ~(ACM_FORMATSUGGESTF_NCHANNELS|ACM_FORMATSUGGESTF_NSAMPLESPERSEC|
ACM_FORMATSUGGESTF_WBITSPERSAMPLE|ACM_FORMATSUGGESTF_WFORMATTAG))
return MMSYSERR_INVALFLAG;
adfg.cbStruct = sizeof(adfg);
adfg.fdwSuggest = fdwSuggest;
adfg.pwfxSrc = pwfxSrc;
adfg.cbwfxSrc = (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) ?
sizeof(WAVEFORMATEX) : (sizeof(WAVEFORMATEX) + pwfxSrc->cbSize);
adfg.pwfxDst = pwfxDst;
adfg.cbwfxDst = cbwfxDst;
if (had == NULL) {
PWINE_ACMDRIVERID padid;
/* MS doc says: ACM finds the best suggestion.
* Well, first found will be the "best"
*/
mmr = ACMERR_NOTPOSSIBLE;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ||
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
continue;
if (MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L) == MMSYSERR_NOERROR) {
mmr = MMSYSERR_NOERROR;
break;
}
acmDriverClose(had, 0);
}
} else {
mmr = MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L);
}
return mmr;
}
/***********************************************************************
* acmFormatTagDetailsA (MSACM32.@)
*/
MMRESULT WINAPI acmFormatTagDetailsA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
DWORD fdwDetails)
{
ACMFORMATTAGDETAILSW aftdw;
MMRESULT mmr;
memset(&aftdw, 0, sizeof(aftdw));
aftdw.cbStruct = sizeof(aftdw);
aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
aftdw.dwFormatTag = paftda->dwFormatTag;
mmr = acmFormatTagDetailsW(had, &aftdw, fdwDetails);
if (mmr == MMSYSERR_NOERROR) {
paftda->dwFormatTag = aftdw.dwFormatTag;
paftda->dwFormatTagIndex = aftdw.dwFormatTagIndex;
paftda->cbFormatSize = aftdw.cbFormatSize;
paftda->fdwSupport = aftdw.fdwSupport;
paftda->cStandardFormats = aftdw.cStandardFormats;
WideCharToMultiByte( CP_ACP, 0, aftdw.szFormatTag, -1, paftda->szFormatTag,
sizeof(paftda->szFormatTag), NULL, NULL );
}
return mmr;
}
/***********************************************************************
* acmFormatTagDetailsW (MSACM32.@)
*/
MMRESULT WINAPI acmFormatTagDetailsW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
DWORD fdwDetails)
{
PWINE_ACMDRIVERID padid;
MMRESULT mmr = ACMERR_NOTPOSSIBLE;
TRACE("(%p, %p, %ld)\n", had, paftd, fdwDetails);
if (fdwDetails & ~(ACM_FORMATTAGDETAILSF_FORMATTAG|ACM_FORMATTAGDETAILSF_INDEX|
ACM_FORMATTAGDETAILSF_LARGESTSIZE))
return MMSYSERR_INVALFLAG;
switch (fdwDetails) {
case ACM_FORMATTAGDETAILSF_FORMATTAG:
if (had == NULL) {
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
MSACM_FindFormatTagInCache(padid, paftd->dwFormatTag, NULL) &&
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
acmDriverClose(had, 0);
if (mmr == MMSYSERR_NOERROR) break;
}
}
} else {
PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
if (pad && MSACM_FindFormatTagInCache(pad->obj.pACMDriverID, paftd->dwFormatTag, NULL))
mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
}
break;
case ACM_FORMATTAGDETAILSF_INDEX:
if (had != NULL) {
PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
if (pad && paftd->dwFormatTagIndex < pad->obj.pACMDriverID->cFormatTags)
mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
}
break;
case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
if (had == NULL) {
ACMFORMATTAGDETAILSW tmp;
DWORD ft = paftd->dwFormatTag;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
memset(&tmp, 0, sizeof(tmp));
tmp.cbStruct = sizeof(tmp);
tmp.dwFormatTag = ft;
if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
(LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) {
if (mmr == ACMERR_NOTPOSSIBLE ||
paftd->cbFormatSize < tmp.cbFormatSize) {
*paftd = tmp;
mmr = MMSYSERR_NOERROR;
}
}
acmDriverClose(had, 0);
}
}
} else {
mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
}
break;
default:
WARN("Unsupported fdwDetails=%08lx\n", fdwDetails);
mmr = MMSYSERR_ERROR;
}
if (mmr == MMSYSERR_NOERROR &&
paftd->dwFormatTag == WAVE_FORMAT_PCM && paftd->szFormatTag[0] == 0)
MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
return mmr;
}
struct MSACM_FormatTagEnumWtoA_Instance {
PACMFORMATTAGDETAILSA paftda;
DWORD dwInstance;
ACMFORMATTAGENUMCBA fnCallback;
};
static BOOL CALLBACK MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid,
PACMFORMATTAGDETAILSW paftdw,
DWORD dwInstance,
DWORD fdwSupport)
{
struct MSACM_FormatTagEnumWtoA_Instance* paftei;
paftei = (struct MSACM_FormatTagEnumWtoA_Instance*)dwInstance;
paftei->paftda->dwFormatTagIndex = paftdw->dwFormatTagIndex;
paftei->paftda->dwFormatTag = paftdw->dwFormatTag;
paftei->paftda->cbFormatSize = paftdw->cbFormatSize;
paftei->paftda->fdwSupport = paftdw->fdwSupport;
paftei->paftda->cStandardFormats = paftdw->cStandardFormats;
WideCharToMultiByte( CP_ACP, 0, paftdw->szFormatTag, -1, paftei->paftda->szFormatTag,
sizeof(paftei->paftda->szFormatTag), NULL, NULL );
return (paftei->fnCallback)(hadid, paftei->paftda,
paftei->dwInstance, fdwSupport);
}
/***********************************************************************
* acmFormatTagEnumA (MSACM32.@)
*/
MMRESULT WINAPI acmFormatTagEnumA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
ACMFORMATTAGENUMCBA fnCallback, DWORD dwInstance,
DWORD fdwEnum)
{
ACMFORMATTAGDETAILSW aftdw;
struct MSACM_FormatTagEnumWtoA_Instance aftei;
memset(&aftdw, 0, sizeof(aftdw));
aftdw.cbStruct = sizeof(aftdw);
aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
aftdw.dwFormatTag = paftda->dwFormatTag;
aftei.paftda = paftda;
aftei.dwInstance = dwInstance;
aftei.fnCallback = fnCallback;
return acmFormatTagEnumW(had, &aftdw, MSACM_FormatTagEnumCallbackWtoA,
(DWORD)&aftei, fdwEnum);
}
/***********************************************************************
* acmFormatTagEnumW (MSACM32.@)
*/
MMRESULT WINAPI acmFormatTagEnumW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
ACMFORMATTAGENUMCBW fnCallback, DWORD dwInstance,
DWORD fdwEnum)
{
PWINE_ACMDRIVERID padid;
int i;
BOOL bPcmDone = FALSE;
TRACE("(%p, %p, %p, %ld, %ld)\n",
had, paftd, fnCallback, dwInstance, fdwEnum);
if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM;
/* (WS) MSDN info page says that if had != 0, then we should find
* the specific driver to get its tags from. Therefore I'm removing
* the FIXME call and adding a search block below. It also seems
* that the lack of this functionality was the responsible for
* codecs to be multiply and incorrectly listed.
*/
/* if (had) FIXME("had != NULL, not supported\n"); */
if (had) {
if (acmDriverID((HACMOBJ)had, (HACMDRIVERID *)&padid, 0) != MMSYSERR_NOERROR)
return MMSYSERR_INVALHANDLE;
for (i = 0; i < padid->cFormatTags; i++) {
paftd->dwFormatTagIndex = i;
if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
(LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
if (paftd->szFormatTag[0] == 0)
MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
/* (WS) I'm preserving this PCM hack since it seems to be
* correct. Please notice this block was borrowed from
* below.
*/
if (bPcmDone) continue;
bPcmDone = TRUE;
}
if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport))
return MMSYSERR_NOERROR;
}
}
}
/* if had==0 then search for the first suitable driver */
else {
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
/* should check for codec only */
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
for (i = 0; i < padid->cFormatTags; i++) {
paftd->dwFormatTagIndex = i;
if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
(LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
if (paftd->szFormatTag[0] == 0)
MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
/* FIXME (EPP): I'm not sure this is the correct
* algorithm (should make more sense to apply the same
* for all already loaded formats, but this will do
* for now
*/
if (bPcmDone) continue;
bPcmDone = TRUE;
}
if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) {
acmDriverClose(had, 0);
return MMSYSERR_NOERROR;
}
}
}
}
acmDriverClose(had, 0);
}
}
return MMSYSERR_NOERROR;
}

View file

@ -0,0 +1,3 @@
Makefile
imaadp32.acm.dbg.c
imaadp32.acm.spec.c

View file

@ -0,0 +1,12 @@
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = imaadp32.acm
IMPORTS = winmm user32 kernel32
C_SRCS = imaadp32.c
@MAKE_DLL_RULES@
### Dependencies:

View file

@ -0,0 +1 @@
@ stdcall DriverProc (long long long long long) ADPCM_DriverProc

View file

@ -0,0 +1,938 @@
/*
* IMA ADPCM handling
*
* Copyright (C) 2001,2002 Eric Pouech
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "mmsystem.h"
#include "mmreg.h"
#include "msacm.h"
#include "msacmdrv.h"
#include "wine/debug.h"
/* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */
WINE_DEFAULT_DEBUG_CHANNEL(adpcm);
/***********************************************************************
* ADPCM_drvOpen
*/
static DWORD ADPCM_drvOpen(LPCSTR str)
{
return 1;
}
/***********************************************************************
* ADPCM_drvClose
*/
static DWORD ADPCM_drvClose(DWORD dwDevID)
{
return 1;
}
typedef struct tagAcmAdpcmData
{
void (*convert)(PACMDRVSTREAMINSTANCE adsi,
const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
/* IMA encoding only */
BYTE stepIndexL;
BYTE stepIndexR;
/* short sample; */
} AcmAdpcmData;
/* table to list all supported formats... those are the basic ones. this
* also helps given a unique index to each of the supported formats
*/
typedef struct
{
int nChannels;
int nBits;
int rate;
} Format;
static Format PCM_Formats[] =
{
{1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
{1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
{1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
{1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
};
static Format ADPCM_Formats[] =
{
{1, 4, 8000}, {2, 4, 8000}, {1, 4, 11025}, {2, 4, 11025},
{1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100},
};
#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
#define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0]))
/***********************************************************************
* ADPCM_GetFormatIndex
*/
static DWORD ADPCM_GetFormatIndex(LPWAVEFORMATEX wfx)
{
int i, hi;
Format* fmts;
switch (wfx->wFormatTag)
{
case WAVE_FORMAT_PCM:
hi = NUM_PCM_FORMATS;
fmts = PCM_Formats;
break;
case WAVE_FORMAT_IMA_ADPCM:
hi = NUM_ADPCM_FORMATS;
fmts = ADPCM_Formats;
break;
default:
return 0xFFFFFFFF;
}
for (i = 0; i < hi; i++)
{
if (wfx->nChannels == fmts[i].nChannels &&
wfx->nSamplesPerSec == fmts[i].rate &&
wfx->wBitsPerSample == fmts[i].nBits)
return i;
}
return 0xFFFFFFFF;
}
/***********************************************************************
* R16
*
* Read a 16 bit sample (correctly handles endianess)
*/
static inline short R16(const unsigned char* src)
{
return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
}
/***********************************************************************
* W16
*
* Write a 16 bit sample (correctly handles endianess)
*/
static inline void W16(unsigned char* dst, short s)
{
dst[0] = LOBYTE(s);
dst[1] = HIBYTE(s);
}
/* IMA (or DVI) APDCM codec routines */
static const unsigned IMA_StepTable[89] =
{
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66,
73, 80, 88, 97, 107, 118, 130, 143,
157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658,
724, 796, 876, 963, 1060, 1166, 1282, 1411,
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
32767
};
static const int IMA_IndexTable[16] =
{
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
static inline void clamp_step_index(int* stepIndex)
{
if (*stepIndex < 0 ) *stepIndex = 0;
if (*stepIndex > 88) *stepIndex = 88;
}
static inline void clamp_sample(int* sample)
{
if (*sample < -32768) *sample = -32768;
if (*sample > 32767) *sample = 32767;
}
static inline void process_nibble(unsigned char code, int* stepIndex, int* sample)
{
unsigned step;
int diff;
code &= 0x0F;
step = IMA_StepTable[*stepIndex];
diff = step >> 3;
if (code & 1) diff += step >> 2;
if (code & 2) diff += step >> 1;
if (code & 4) diff += step;
if (code & 8) *sample -= diff;
else *sample += diff;
clamp_sample(sample);
*stepIndex += IMA_IndexTable[code];
clamp_step_index(stepIndex);
}
static inline unsigned char generate_nibble(int in, int* stepIndex, int* sample)
{
int effdiff, diff = in - *sample;
unsigned step;
unsigned char code;
if (diff < 0)
{
diff = -diff;
code = 8;
}
else
{
code = 0;
}
step = IMA_StepTable[*stepIndex];
effdiff = (step >> 3);
if (diff >= step)
{
code |= 4;
diff -= step;
effdiff += step;
}
step >>= 1;
if (diff >= step)
{
code |= 2;
diff -= step;
effdiff += step;
}
step >>= 1;
if (diff >= step)
{
code |= 1;
effdiff += step;
}
if (code & 8) *sample -= effdiff;
else *sample += effdiff;
clamp_sample(sample);
*stepIndex += IMA_IndexTable[code];
clamp_step_index(stepIndex);
return code;
}
static void cvtSSima16K(PACMDRVSTREAMINSTANCE adsi,
const unsigned char* src, LPDWORD nsrc,
unsigned char* dst, LPDWORD ndst)
{
int i;
int sampleL, sampleR;
int stepIndexL, stepIndexR;
int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
int nsamp;
/* compute the number of entire blocks we can decode...
* it's the min of the number of entire blocks in source buffer and the number
* of entire blocks in destination buffer
*/
DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
*ndst / (nsamp_blk * 2 * 2));
*nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
*ndst = nblock * (nsamp_blk * 2 * 2);
nsamp_blk--; /* remove the sample in block header */
for (; nblock > 0; nblock--)
{
const unsigned char* in_src = src;
/* handle headers first */
sampleL = R16(src);
stepIndexL = (unsigned)*(src + 2);
clamp_step_index(&stepIndexL);
src += 4;
W16(dst, sampleL); dst += 2;
sampleR = R16(src);
stepIndexR = (unsigned)*(src + 2);
clamp_step_index(&stepIndexR);
src += 4;
W16(dst, sampleR); dst += 2;
for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
{
for (i = 0; i < 4; i++)
{
process_nibble(*src, &stepIndexL, &sampleL);
W16(dst + (2 * i + 0) * 4 + 0, sampleL);
process_nibble(*src++ >> 4, &stepIndexL, &sampleL);
W16(dst + (2 * i + 1) * 4 + 0, sampleL);
}
for (i = 0; i < 4; i++)
{
process_nibble(*src , &stepIndexR, &sampleR);
W16(dst + (2 * i + 0) * 4 + 2, sampleR);
process_nibble(*src++ >>4, &stepIndexR, &sampleR);
W16(dst + (2 * i + 1) * 4 + 2, sampleR);
}
dst += 32;
}
/* we have now to realign the source pointer on block */
src = in_src + adsi->pwfxSrc->nBlockAlign;
}
}
static void cvtMMima16K(PACMDRVSTREAMINSTANCE adsi,
const unsigned char* src, LPDWORD nsrc,
unsigned char* dst, LPDWORD ndst)
{
int sample;
int stepIndex;
int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
int nsamp;
/* compute the number of entire blocks we can decode...
* it's the min of the number of entire blocks in source buffer and the number
* of entire blocks in destination buffer
*/
DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
*ndst / (nsamp_blk * 2));
*nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
*ndst = nblock * nsamp_blk * 2;
nsamp_blk--; /* remove the sample in block header */
for (; nblock > 0; nblock--)
{
const unsigned char* in_src = src;
/* handle header first */
sample = R16(src);
stepIndex = (unsigned)*(src + 2);
clamp_step_index(&stepIndex);
src += 4;
W16(dst, sample); dst += 2;
for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
{
process_nibble(*src, &stepIndex, &sample);
W16(dst, sample); dst += 2;
process_nibble(*src++ >> 4, &stepIndex, &sample);
W16(dst, sample); dst += 2;
}
/* we have now to realign the source pointer on block */
src = in_src + adsi->pwfxSrc->nBlockAlign;
}
}
static void cvtSS16imaK(PACMDRVSTREAMINSTANCE adsi,
const unsigned char* src, LPDWORD nsrc,
unsigned char* dst, LPDWORD ndst)
{
int stepIndexL, stepIndexR;
int sampleL, sampleR;
BYTE code1, code2;
int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
int i, nsamp;
/* compute the number of entire blocks we can decode...
* it's the min of the number of entire blocks in source buffer and the number
* of entire blocks in destination buffer
*/
DWORD nblock = min(*nsrc / (nsamp_blk * 2 * 2),
*ndst / adsi->pwfxDst->nBlockAlign);
*nsrc = nblock * (nsamp_blk * 2 * 2);
*ndst = nblock * adsi->pwfxDst->nBlockAlign;
stepIndexL = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL;
stepIndexR = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR;
nsamp_blk--; /* so that we won't count the sample in header while filling the block */
for (; nblock > 0; nblock--)
{
char* in_dst = dst;
/* generate header */
sampleL = R16(src); src += 2;
W16(dst, sampleL); dst += 2;
*dst = (unsigned char)(unsigned)stepIndexL;
dst += 2;
sampleR = R16(src); src += 2;
W16(dst, sampleR); dst += 2;
*dst = (unsigned char)(unsigned)stepIndexR;
dst += 2;
for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
{
for (i = 0; i < 4; i++)
{
code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 0),
&stepIndexL, &sampleL);
code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 0),
&stepIndexL, &sampleL);
*dst++ = (code1 << 4) | code2;
}
for (i = 0; i < 4; i++)
{
code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 1),
&stepIndexR, &sampleR);
code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 1),
&stepIndexR, &sampleR);
*dst++ = (code1 << 4) | code2;
}
src += 32;
}
dst = in_dst + adsi->pwfxDst->nBlockAlign;
}
((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndexL;
((AcmAdpcmData*)adsi->dwDriver)->stepIndexR = stepIndexR;
}
static void cvtMM16imaK(PACMDRVSTREAMINSTANCE adsi,
const unsigned char* src, LPDWORD nsrc,
unsigned char* dst, LPDWORD ndst)
{
int stepIndex;
int sample;
BYTE code1, code2;
int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
int nsamp;
/* compute the number of entire blocks we can decode...
* it's the min of the number of entire blocks in source buffer and the number
* of entire blocks in destination buffer
*/
DWORD nblock = min(*nsrc / (nsamp_blk * 2),
*ndst / adsi->pwfxDst->nBlockAlign);
*nsrc = nblock * (nsamp_blk * 2);
*ndst = nblock * adsi->pwfxDst->nBlockAlign;
stepIndex = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL;
nsamp_blk--; /* so that we won't count the sample in header while filling the block */
for (; nblock > 0; nblock--)
{
char* in_dst = dst;
/* generate header */
/* FIXME: what about the last effective sample from previous block ??? */
/* perhaps something like:
* sample += R16(src);
* clamp_sample(sample);
* and with :
* + saving the sample in adsi->dwDriver when all blocks are done
+ + reset should set the field in adsi->dwDriver to 0 too
*/
sample = R16(src); src += 2;
W16(dst, sample); dst += 2;
*dst = (unsigned char)(unsigned)stepIndex;
dst += 2;
for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
{
code1 = generate_nibble(R16(src), &stepIndex, &sample);
src += 2;
code2 = generate_nibble(R16(src), &stepIndex, &sample);
src += 2;
*dst++ = (code1 << 4) | code2;
}
dst = in_dst + adsi->pwfxDst->nBlockAlign;
}
((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndex;
}
/***********************************************************************
* ADPCM_DriverDetails
*
*/
static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add)
{
add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
add->wMid = 0xFF;
add->wPid = 0x00;
add->vdwACM = 0x01000000;
add->vdwDriver = 0x01000000;
add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
add->cFormatTags = 2; /* PCM, IMA ADPCM */
add->cFilterTags = 0;
add->hicon = NULL;
MultiByteToWideChar( CP_ACP, 0, "WINE-ADPCM", -1,
add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, "Wine IMA ADPCM converter", -1,
add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
add->szFeatures[0] = 0;
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_FormatTagDetails
*
*/
static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
{
static WCHAR szPcm[]={'P','C','M',0};
static WCHAR szImaAdPcm[]={'I','M','A',' ','A','d','P','C','M',0};
switch (dwQuery)
{
case ACM_FORMATTAGDETAILSF_INDEX:
if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
break;
case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
{
aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_IMA_ADPCM is bigger than PCM */
break;
}
/* fall thru */
case ACM_FORMATTAGDETAILSF_FORMATTAG:
switch (aftd->dwFormatTag)
{
case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
case WAVE_FORMAT_IMA_ADPCM: aftd->dwFormatTagIndex = 1; break;
default: return ACMERR_NOTPOSSIBLE;
}
break;
default:
WARN("Unsupported query %08lx\n", dwQuery);
return MMSYSERR_NOTSUPPORTED;
}
aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
switch (aftd->dwFormatTagIndex)
{
case 0:
aftd->dwFormatTag = WAVE_FORMAT_PCM;
aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
aftd->cStandardFormats = NUM_PCM_FORMATS;
lstrcpyW(aftd->szFormatTag, szPcm);
break;
case 1:
aftd->dwFormatTag = WAVE_FORMAT_IMA_ADPCM;
aftd->cbFormatSize = sizeof(IMAADPCMWAVEFORMAT);
aftd->cStandardFormats = NUM_ADPCM_FORMATS;
lstrcpyW(aftd->szFormatTag, szImaAdPcm);
break;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_FormatDetails
*
*/
static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
{
switch (dwQuery)
{
case ACM_FORMATDETAILSF_FORMAT:
if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
break;
case ACM_FORMATDETAILSF_INDEX:
afd->pwfx->wFormatTag = afd->dwFormatTag;
switch (afd->dwFormatTag)
{
case WAVE_FORMAT_PCM:
if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
/* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
* afd->pwfx->cbSize = 0;
*/
afd->pwfx->nBlockAlign =
(afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
afd->pwfx->nAvgBytesPerSec =
afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
break;
case WAVE_FORMAT_IMA_ADPCM:
if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE;
afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels;
afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate;
afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits;
afd->pwfx->nBlockAlign = 1024;
/* we got 4 bits per sample */
afd->pwfx->nAvgBytesPerSec =
(afd->pwfx->nSamplesPerSec * 4) / 8;
if (afd->cbwfx >= sizeof(WAVEFORMATEX))
afd->pwfx->cbSize = sizeof(WORD);
if (afd->cbwfx >= sizeof(IMAADPCMWAVEFORMAT))
((IMAADPCMWAVEFORMAT*)afd->pwfx)->wSamplesPerBlock = (1024 - 4 * afd->pwfx->nChannels) * (2 / afd->pwfx->nChannels) + 1;
break;
default:
WARN("Unsupported tag %08lx\n", afd->dwFormatTag);
return MMSYSERR_INVALPARAM;
}
break;
default:
WARN("Unsupported query %08lx\n", dwQuery);
return MMSYSERR_NOTSUPPORTED;
}
afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
afd->szFormat[0] = 0; /* let MSACM format this for us... */
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_FormatSuggest
*
*/
static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
{
/* some tests ... */
if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
/* FIXME: should do those tests against the real size (according to format tag */
/* If no suggestion for destination, then copy source value */
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
{
if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
adfs->pwfxDst->wBitsPerSample = 4;
else
adfs->pwfxDst->wBitsPerSample = 16;
}
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
{
if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
adfs->pwfxDst->wFormatTag = WAVE_FORMAT_IMA_ADPCM;
else
adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
}
/* check if result is ok */
if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
/* recompute other values */
switch (adfs->pwfxDst->wFormatTag)
{
case WAVE_FORMAT_PCM:
adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
break;
case WAVE_FORMAT_IMA_ADPCM:
adfs->pwfxDst->nBlockAlign = 1024;
/* FIXME: not handling header overhead */
adfs->pwfxDst->nAvgBytesPerSec = ((adfs->pwfxDst->nSamplesPerSec * 4) / 8) * adfs->pwfxSrc->nChannels;
((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock = (1024 - 4 * adfs->pwfxSrc->nChannels) * (2 / adfs->pwfxSrc->nChannels) + 1;
TRACE("setting spb=%u\n", ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock);
break;
default:
FIXME("\n");
break;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_Reset
*
*/
static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad)
{
aad->stepIndexL = aad->stepIndexR = 0;
}
/***********************************************************************
* ADPCM_StreamOpen
*
*/
static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
{
AcmAdpcmData* aad;
unsigned nspb;
assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
return ACMERR_NOTPOSSIBLE;
aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData));
if (aad == 0) return MMSYSERR_NOMEM;
adsi->dwDriver = (DWORD)aad;
if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
goto theEnd;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
/* resampling or mono <=> stereo not available
* ADPCM algo only define 16 bit per sample output
*/
if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
adsi->pwfxDst->wBitsPerSample != 16)
goto theEnd;
nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
TRACE("spb=%u\n", nspb);
/* we check that in a block, after the header, samples are present on
* 4-sample packet pattern
* we also check that the block alignement is bigger than the expected size
*/
if (((nspb - 1) & 3) != 0) goto theEnd;
if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign)
goto theEnd;
/* adpcm decoding... */
if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2)
aad->convert = cvtSSima16K;
if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1)
aad->convert = cvtMMima16K;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
{
if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
adsi->pwfxSrc->wBitsPerSample != 16)
goto theEnd;
nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
TRACE("spb=%u\n", nspb);
/* we check that in a block, after the header, samples are present on
* 4-sample packet pattern
* we also check that the block alignement is bigger than the expected size
*/
if (((nspb - 1) & 3) != 0) goto theEnd;
if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign)
goto theEnd;
/* adpcm coding... */
if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2)
aad->convert = cvtSS16imaK;
if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1)
aad->convert = cvtMM16imaK;
}
else goto theEnd;
ADPCM_Reset(adsi, aad);
return MMSYSERR_NOERROR;
theEnd:
HeapFree(GetProcessHeap(), 0, aad);
adsi->dwDriver = 0L;
return MMSYSERR_NOTSUPPORTED;
}
/***********************************************************************
* ADPCM_StreamClose
*
*/
static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
{
HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_round
*
*/
static inline DWORD ADPCM_round(DWORD a, DWORD b, DWORD c)
{
assert(a && b && c);
/* to be sure, always return an entire number of c... */
return ((double)a * (double)b + (double)c - 1) / (double)c;
}
/***********************************************************************
* ADPCM_StreamSize
*
*/
static LRESULT ADPCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
{
switch (adss->fdwSize)
{
case ACM_STREAMSIZEF_DESTINATION:
/* cbDstLength => cbSrcLength */
if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
{
/* don't take block overhead into account, doesn't matter too much */
adss->cbSrcLength = adss->cbDstLength * 4;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
FIXME("misses the block header overhead\n");
adss->cbSrcLength = 256 + adss->cbDstLength / 4;
}
else
{
return MMSYSERR_NOTSUPPORTED;
}
break;
case ACM_STREAMSIZEF_SOURCE:
/* cbSrcLength => cbDstLength */
if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
{
FIXME("misses the block header overhead\n");
adss->cbDstLength = 256 + adss->cbSrcLength / 4;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
/* don't take block overhead into account, doesn't matter too much */
adss->cbDstLength = adss->cbSrcLength * 4;
}
else
{
return MMSYSERR_NOTSUPPORTED;
}
break;
default:
WARN("Unsupported query %08lx\n", adss->fdwSize);
return MMSYSERR_NOTSUPPORTED;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_StreamConvert
*
*/
static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
{
AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver;
DWORD nsrc = adsh->cbSrcLength;
DWORD ndst = adsh->cbDstLength;
if (adsh->fdwConvert &
~(ACM_STREAMCONVERTF_BLOCKALIGN|
ACM_STREAMCONVERTF_END|
ACM_STREAMCONVERTF_START))
{
FIXME("Unsupported fdwConvert (%08lx), ignoring it\n", adsh->fdwConvert);
}
/* ACM_STREAMCONVERTF_BLOCKALIGN
* currently all conversions are block aligned, so do nothing for this flag
* ACM_STREAMCONVERTF_END
* no pending data, so do nothing for this flag
*/
if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
{
ADPCM_Reset(adsi, aad);
}
aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
adsh->cbSrcLengthUsed = nsrc;
adsh->cbDstLengthUsed = ndst;
return MMSYSERR_NOERROR;
}
/**************************************************************************
* ADPCM_DriverProc [exported]
*/
LRESULT CALLBACK ADPCM_DriverProc(DWORD dwDevID, HDRVR hDriv, UINT wMsg,
LPARAM dwParam1, LPARAM dwParam2)
{
TRACE("(%08lx %08lx %04x %08lx %08lx);\n",
dwDevID, (DWORD)hDriv, wMsg, dwParam1, dwParam2);
switch (wMsg)
{
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1);
case DRV_CLOSE: return ADPCM_drvClose(dwDevID);
case DRV_ENABLE: return 1;
case DRV_DISABLE: return 1;
case DRV_QUERYCONFIGURE: return 1;
case DRV_CONFIGURE: MessageBoxA(0, "MSACM IMA ADPCM filter !", "Wine Driver", MB_OK); return 1;
case DRV_INSTALL: return DRVCNF_RESTART;
case DRV_REMOVE: return DRVCNF_RESTART;
case ACMDM_DRIVER_NOTIFY:
/* no caching from other ACM drivers is done so far */
return MMSYSERR_NOERROR;
case ACMDM_DRIVER_DETAILS:
return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
case ACMDM_FORMATTAG_DETAILS:
return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
case ACMDM_FORMAT_DETAILS:
return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
case ACMDM_FORMAT_SUGGEST:
return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
case ACMDM_STREAM_OPEN:
return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
case ACMDM_STREAM_CLOSE:
return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
case ACMDM_STREAM_SIZE:
return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
case ACMDM_STREAM_CONVERT:
return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
/* this converter is not a hardware driver */
case ACMDM_FILTERTAG_DETAILS:
case ACMDM_FILTER_DETAILS:
/* this converter is not a filter */
case ACMDM_STREAM_RESET:
/* only needed for asynchronous driver... we aren't, so just say it */
return MMSYSERR_NOTSUPPORTED;
case ACMDM_STREAM_PREPARE:
case ACMDM_STREAM_UNPREPARE:
/* nothing special to do here... so don't do anything */
return MMSYSERR_NOERROR;
default:
return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
}
return 0;
}

View file

@ -0,0 +1,415 @@
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/*
* MSACM32 library
*
* Copyright 1998 Patrik Stridvall
* 1999 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "winreg.h"
#include "mmsystem.h"
#include "mmreg.h"
#include "msacm.h"
#include "msacmdrv.h"
#include "wineacm.h"
#include "wine/debug.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msacm);
/**********************************************************************/
HANDLE MSACM_hHeap = NULL;
PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
#if 0
/***********************************************************************
* MSACM_DumpCache
*/
static void MSACM_DumpCache(PWINE_ACMDRIVERID padid)
{
unsigned i;
TRACE("cFilterTags=%lu cFormatTags=%lu fdwSupport=%08lx\n",
padid->cFilterTags, padid->cFormatTags, padid->fdwSupport);
for (i = 0; i < padid->cache->cFormatTags; i++) {
TRACE("\tdwFormatTag=%lu cbwfx=%lu\n",
padid->aFormatTag[i].dwFormatTag, padid->aFormatTag[i].cbwfx);
}
}
#endif
/***********************************************************************
* MSACM_FindFormatTagInCache [internal]
*
* Returns TRUE is the format tag fmtTag is present in the cache.
* If so, idx is set to its index.
*/
BOOL MSACM_FindFormatTagInCache(WINE_ACMDRIVERID* padid, DWORD fmtTag, LPDWORD idx)
{
unsigned i;
for (i = 0; i < padid->cFormatTags; i++) {
if (padid->aFormatTag[i].dwFormatTag == fmtTag) {
if (idx) *idx = i;
return TRUE;
}
}
return FALSE;
}
/***********************************************************************
* MSACM_FillCache
*/
static BOOL MSACM_FillCache(PWINE_ACMDRIVERID padid)
{
HACMDRIVER had = 0;
int ntag;
ACMDRIVERDETAILSW add;
ACMFORMATTAGDETAILSW aftd;
if (acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != 0)
return FALSE;
padid->aFormatTag = NULL;
add.cbStruct = sizeof(add);
if (MSACM_Message(had, ACMDM_DRIVER_DETAILS, (LPARAM)&add, 0))
goto errCleanUp;
if (add.cFormatTags > 0) {
padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY,
add.cFormatTags * sizeof(padid->aFormatTag[0]));
if (!padid->aFormatTag) goto errCleanUp;
}
padid->cFormatTags = add.cFormatTags;
padid->cFilterTags = add.cFilterTags;
padid->fdwSupport = add.fdwSupport;
aftd.cbStruct = sizeof(aftd);
for (ntag = 0; ntag < add.cFormatTags; ntag++) {
aftd.dwFormatTagIndex = ntag;
if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)&aftd, ACM_FORMATTAGDETAILSF_INDEX)) {
TRACE("IIOs (%s)\n", debugstr_w(padid->pszDriverAlias));
goto errCleanUp;
}
padid->aFormatTag[ntag].dwFormatTag = aftd.dwFormatTag;
padid->aFormatTag[ntag].cbwfx = aftd.cbFormatSize;
}
acmDriverClose(had, 0);
return TRUE;
errCleanUp:
if (had) acmDriverClose(had, 0);
HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
padid->aFormatTag = NULL;
return FALSE;
}
/***********************************************************************
* MSACM_GetRegistryKey
*/
static LPWSTR MSACM_GetRegistryKey(const WINE_ACMDRIVERID* padid)
{
static const WCHAR baseKey[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
'A','u','d','i','o','C','o','m','p','r','e','s','s','i','o','n','M','a','n','a','g','e','r','\\',
'D','r','i','v','e','r','C','a','c','h','e','\\','\0'};
LPWSTR ret;
int len;
if (!padid->pszDriverAlias) {
ERR("No alias needed for registry entry\n");
return NULL;
}
len = strlenW(baseKey);
ret = HeapAlloc(MSACM_hHeap, 0, (len + strlenW(padid->pszDriverAlias) + 1) * sizeof(WCHAR));
if (!ret) return NULL;
strcpyW(ret, baseKey);
strcpyW(ret + len, padid->pszDriverAlias);
CharLowerW(ret + len);
return ret;
}
/***********************************************************************
* MSACM_ReadCache
*/
static BOOL MSACM_ReadCache(PWINE_ACMDRIVERID padid)
{
LPWSTR key = MSACM_GetRegistryKey(padid);
HKEY hKey;
DWORD type, size;
if (!key) return FALSE;
padid->aFormatTag = NULL;
if (RegCreateKeyW(HKEY_LOCAL_MACHINE, key, &hKey))
goto errCleanUp;
size = sizeof(padid->cFormatTags);
if (RegQueryValueExA(hKey, "cFormatTags", 0, &type, (void*)&padid->cFormatTags, &size))
goto errCleanUp;
size = sizeof(padid->cFilterTags);
if (RegQueryValueExA(hKey, "cFilterTags", 0, &type, (void*)&padid->cFilterTags, &size))
goto errCleanUp;
size = sizeof(padid->fdwSupport);
if (RegQueryValueExA(hKey, "fdwSupport", 0, &type, (void*)&padid->fdwSupport, &size))
goto errCleanUp;
if (padid->cFormatTags > 0) {
size = padid->cFormatTags * sizeof(padid->aFormatTag[0]);
padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY, size);
if (!padid->aFormatTag) goto errCleanUp;
if (RegQueryValueExA(hKey, "aFormatTagCache", 0, &type, (void*)padid->aFormatTag, &size))
goto errCleanUp;
}
HeapFree(MSACM_hHeap, 0, key);
return TRUE;
errCleanUp:
HeapFree(MSACM_hHeap, 0, key);
HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
padid->aFormatTag = NULL;
RegCloseKey(hKey);
return FALSE;
}
/***********************************************************************
* MSACM_WriteCache
*/
static BOOL MSACM_WriteCache(PWINE_ACMDRIVERID padid)
{
LPWSTR key = MSACM_GetRegistryKey(padid);
HKEY hKey;
if (!key) return FALSE;
if (RegCreateKeyW(HKEY_LOCAL_MACHINE, key, &hKey))
goto errCleanUp;
if (RegSetValueExA(hKey, "cFormatTags", 0, REG_DWORD, (void*)&padid->cFormatTags, sizeof(DWORD)))
goto errCleanUp;
if (RegSetValueExA(hKey, "cFilterTags", 0, REG_DWORD, (void*)&padid->cFilterTags, sizeof(DWORD)))
goto errCleanUp;
if (RegSetValueExA(hKey, "fdwSupport", 0, REG_DWORD, (void*)&padid->fdwSupport, sizeof(DWORD)))
goto errCleanUp;
if (RegSetValueExA(hKey, "aFormatTagCache", 0, REG_BINARY,
(void*)padid->aFormatTag,
padid->cFormatTags * sizeof(padid->aFormatTag[0])))
goto errCleanUp;
HeapFree(MSACM_hHeap, 0, key);
return TRUE;
errCleanUp:
HeapFree(MSACM_hHeap, 0, key);
return FALSE;
}
/***********************************************************************
* MSACM_RegisterDriver()
*/
PWINE_ACMDRIVERID MSACM_RegisterDriver(LPWSTR pszDriverAlias, LPWSTR pszFileName,
HINSTANCE hinstModule)
{
PWINE_ACMDRIVERID padid;
TRACE("(%s, %s, %p)\n",
debugstr_w(pszDriverAlias), debugstr_w(pszFileName), hinstModule);
padid = (PWINE_ACMDRIVERID) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVERID));
padid->obj.dwType = WINE_ACMOBJ_DRIVERID;
padid->obj.pACMDriverID = padid;
padid->pszDriverAlias = NULL;
if (pszDriverAlias)
{
padid->pszDriverAlias = HeapAlloc( MSACM_hHeap, 0, (strlenW(pszDriverAlias)+1) * sizeof(WCHAR) );
strcpyW( padid->pszDriverAlias, pszDriverAlias );
}
padid->pszFileName = NULL;
if (pszFileName)
{
padid->pszFileName = HeapAlloc( MSACM_hHeap, 0, (strlenW(pszFileName)+1) * sizeof(WCHAR) );
strcpyW( padid->pszFileName, pszFileName );
}
padid->hInstModule = hinstModule;
padid->pACMDriverList = NULL;
padid->pNextACMDriverID = NULL;
padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
if (MSACM_pLastACMDriverID)
MSACM_pLastACMDriverID->pNextACMDriverID = padid;
MSACM_pLastACMDriverID = padid;
if (!MSACM_pFirstACMDriverID)
MSACM_pFirstACMDriverID = padid;
/* disable the driver if we cannot load the cache */
if (!MSACM_ReadCache(padid) && !MSACM_FillCache(padid)) {
WARN("Couldn't load cache for ACM driver (%s)\n", debugstr_w(pszFileName));
MSACM_UnregisterDriver(padid);
return NULL;
}
return padid;
}
/***********************************************************************
* MSACM_RegisterAllDrivers()
*/
void MSACM_RegisterAllDrivers(void)
{
LPWSTR pszBuffer;
DWORD dwBufferLength;
static WCHAR msacm32[] = {'m','s','a','c','m','3','2','.','d','l','l','\0'};
static WCHAR msacmW[] = {'M','S','A','C','M','.'};
static WCHAR drv32[] = {'d','r','i','v','e','r','s','3','2','\0'};
static WCHAR sys[] = {'s','y','s','t','e','m','.','i','n','i','\0'};
/* FIXME
* What if the user edits system.ini while the program is running?
* Does Windows handle that?
*/
if (MSACM_pFirstACMDriverID)
return;
/* FIXME: Does not work! How do I determine the section length? */
dwBufferLength = 1024;
/* EPP GetPrivateProfileSectionA("drivers32", NULL, 0, "system.ini"); */
pszBuffer = (LPWSTR) HeapAlloc(MSACM_hHeap, 0, dwBufferLength * sizeof(WCHAR));
if (GetPrivateProfileSectionW(drv32, pszBuffer, dwBufferLength, sys))
{
LPWSTR s = pszBuffer, s2;
while (*s)
{
CharUpperBuffW(s, 6);
if (memcmp(s, msacmW, 6 * sizeof(WCHAR)) == 0)
{
s2 = s;
while (*s2 != '\0' && *s2 != '=') s2++;
if (*s2)
{
*s2 = '\0';
MSACM_RegisterDriver(s, s2 + 1, 0);
*s2 = '=';
}
}
s += strlenW(s) + 1; /* Either next char or \0 */
}
}
HeapFree(MSACM_hHeap, 0, pszBuffer);
MSACM_RegisterDriver(msacm32, msacm32, 0);
}
/***********************************************************************
* MSACM_UnregisterDriver()
*/
PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)
{
PWINE_ACMDRIVERID pNextACMDriverID;
while (p->pACMDriverList)
acmDriverClose((HACMDRIVER) p->pACMDriverList, 0);
if (p->pszDriverAlias)
HeapFree(MSACM_hHeap, 0, p->pszDriverAlias);
if (p->pszFileName)
HeapFree(MSACM_hHeap, 0, p->pszFileName);
HeapFree(MSACM_hHeap, 0, p->aFormatTag);
if (p == MSACM_pFirstACMDriverID)
MSACM_pFirstACMDriverID = p->pNextACMDriverID;
if (p == MSACM_pLastACMDriverID)
MSACM_pLastACMDriverID = p->pPrevACMDriverID;
if (p->pPrevACMDriverID)
p->pPrevACMDriverID->pNextACMDriverID = p->pNextACMDriverID;
if (p->pNextACMDriverID)
p->pNextACMDriverID->pPrevACMDriverID = p->pPrevACMDriverID;
pNextACMDriverID = p->pNextACMDriverID;
HeapFree(MSACM_hHeap, 0, p);
return pNextACMDriverID;
}
/***********************************************************************
* MSACM_UnregisterAllDrivers()
*/
void MSACM_UnregisterAllDrivers(void)
{
PWINE_ACMDRIVERID p = MSACM_pFirstACMDriverID;
while (p) {
MSACM_WriteCache(p);
p = MSACM_UnregisterDriver(p);
}
}
/***********************************************************************
* MSACM_GetObj()
*/
PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj, DWORD type)
{
PWINE_ACMOBJ pao = (PWINE_ACMOBJ)hObj;
if (pao == NULL || IsBadReadPtr(pao, sizeof(WINE_ACMOBJ)) ||
((type != WINE_ACMOBJ_DONTCARE) && (type != pao->dwType)))
return NULL;
return pao;
}
/***********************************************************************
* MSACM_GetDriverID()
*/
PWINE_ACMDRIVERID MSACM_GetDriverID(HACMDRIVERID hDriverID)
{
return (PWINE_ACMDRIVERID)MSACM_GetObj((HACMOBJ)hDriverID, WINE_ACMOBJ_DRIVERID);
}
/***********************************************************************
* MSACM_GetDriver()
*/
PWINE_ACMDRIVER MSACM_GetDriver(HACMDRIVER hDriver)
{
return (PWINE_ACMDRIVER)MSACM_GetObj((HACMOBJ)hDriver, WINE_ACMOBJ_DRIVER);
}
/***********************************************************************
* MSACM_Message()
*/
MMRESULT MSACM_Message(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
{
PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
return pad ? SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2) : MMSYSERR_INVALHANDLE;
}

View file

@ -0,0 +1,23 @@
# $Id: makefile
PATH_TO_TOP = ../..
TARGET_TYPE = winedll
TARGET_NAME = msacm32
TARGET_BASE = 0x777c0000
TARGET_CFLAGS += -DYDEBUG -DUNICODE -D_UNICODE -D__USE_W32API -D__REACTOS__ -Wall -Werror
# -D_WIN32_WINNT=0x0500
TARGET_SDKLIBS = ntdll.a winmm.a
DEP_OBJECTS = $(TARGET_OBJECTS)
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk
include $(TOOLS_PATH)/depend.mk

View file

@ -0,0 +1,30 @@
/*
* Top level resource file for MS ACM
*
* Copyright 2000 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wineacm.h"
#include "msacm_En.rc"
#include "msacm_Fr.rc"
#include "msacm_It.rc"
#include "msacm_Nl.rc"
#include "msacm_Pt.rc"

View file

@ -0,0 +1,40 @@
1 stub WEP
2 stub DRIVERPROC
3 stub ___EXPORTEDSTUB
7 pascal acmGetVersion() acmGetVersion16
8 pascal -ret16 acmMetrics(word word ptr) acmMetrics16
10 pascal -ret16 acmDriverEnum(ptr long long) acmDriverEnum16
11 pascal -ret16 acmDriverDetails(word ptr long) acmDriverDetails16
12 pascal -ret16 acmDriverAdd(ptr word long long long) acmDriverAdd16
13 pascal -ret16 acmDriverRemove(word long) acmDriverRemove16
14 pascal -ret16 acmDriverOpen(ptr word long) acmDriverOpen16
15 pascal -ret16 acmDriverClose(word long) acmDriverClose16
16 pascal acmDriverMessage(word word long long) acmDriverMessage16
17 pascal -ret16 acmDriverID(word ptr long) acmDriverID16
18 pascal -ret16 acmDriverPriority(word long long) acmDriverPriority16
30 pascal -ret16 acmFormatTagDetails(word ptr long) acmFormatTagDetails16
31 pascal -ret16 acmFormatTagEnum(word ptr ptr long long) acmFormatTagEnum16
40 pascal -ret16 acmFormatChoose(ptr) acmFormatChoose16
41 pascal -ret16 acmFormatDetails(word ptr long) acmFormatDetails16
42 pascal -ret16 acmFormatEnum(word ptr ptr long long) acmFormatEnum16
45 pascal -ret16 acmFormatSuggest(word ptr ptr long long) acmFormatSuggest16
50 pascal -ret16 acmFilterTagDetails(word ptr long) acmFilterTagDetails16
51 pascal -ret16 acmFilterTagEnum(word ptr ptr long long) acmFilterTagEnum16
60 pascal -ret16 acmFilterChoose(ptr) acmFilterChoose16
61 pascal -ret16 acmFilterDetails(word ptr long) acmFilterDetails16
62 pascal -ret16 acmFilterEnum(word ptr ptr long long) acmFilterEnum16
70 pascal -ret16 acmStreamOpen(ptr word ptr ptr ptr long long long) acmStreamOpen16
71 pascal -ret16 acmStreamClose(word long) acmStreamClose16
72 pascal -ret16 acmStreamSize(word long ptr long) acmStreamSize16
75 pascal -ret16 acmStreamConvert(word ptr long) acmStreamConvert16
76 pascal -ret16 acmStreamReset(word long) acmStreamReset16
77 pascal -ret16 acmStreamPrepareHeader(word ptr long) acmStreamPrepareHeader16
78 pascal -ret16 acmStreamUnprepareHeader(word ptr long) acmStreamUnprepareHeader16
150 stub ACMAPPLICATIONEXIT
175 stub ACMHUGEPAGELOCK
176 stub ACMHUGEPAGEUNLOCK
200 stub ACMOPENCONVERSION
201 stub ACMCLOSECONVERSION
202 stub ACMCONVERT
203 stub ACMCHOOSEFORMAT
255 pascal DllEntryPoint(long word word word long word) MSACM_DllEntryPoint

View file

View file

@ -0,0 +1,46 @@
@ stdcall acmDriverAddA(ptr long long long long)
@ stdcall acmDriverAddW(ptr long long long long)
@ stdcall acmDriverClose(long long)
@ stdcall acmDriverDetailsA(long ptr long)
@ stdcall acmDriverDetailsW(long ptr long)
@ stdcall acmDriverEnum(ptr long long)
@ stdcall acmDriverID(long ptr long)
@ stdcall acmDriverMessage(long long long long)
@ stdcall acmDriverOpen(ptr long long)
@ stdcall acmDriverPriority(long long long)
@ stdcall acmDriverRemove(long long)
@ stdcall acmFilterChooseA(ptr)
@ stdcall acmFilterChooseW(ptr)
@ stdcall acmFilterDetailsA(long ptr long)
@ stdcall acmFilterDetailsW(long ptr long)
@ stdcall acmFilterEnumA(long ptr ptr long long)
@ stdcall acmFilterEnumW(long ptr ptr long long)
@ stdcall acmFilterTagDetailsA(long ptr long)
@ stdcall acmFilterTagDetailsW(long ptr long)
@ stdcall acmFilterTagEnumA(long ptr ptr long long)
@ stdcall acmFilterTagEnumW(long ptr ptr long long)
@ stdcall acmFormatChooseA(ptr)
@ stdcall acmFormatChooseW(ptr)
@ stdcall acmFormatDetailsA(long ptr long)
@ stdcall acmFormatDetailsW(long ptr long)
@ stdcall acmFormatEnumA(long ptr ptr long long)
@ stdcall acmFormatEnumW(long ptr ptr long long)
@ stdcall acmFormatSuggest(long ptr ptr long long)
@ stdcall acmFormatTagDetailsA(long ptr long)
@ stdcall acmFormatTagDetailsW(long ptr long)
@ stdcall acmFormatTagEnumA(long ptr ptr long long)
@ stdcall acmFormatTagEnumW(long ptr ptr long long)
@ stdcall acmGetVersion()
@ stub acmMessage32
@ stdcall acmMetrics(long long ptr)
@ stdcall acmStreamClose(long long)
@ stdcall acmStreamConvert(long ptr long)
@ stdcall acmStreamMessage(long long long long)
@ stdcall acmStreamOpen(ptr long ptr ptr ptr long long long)
@ stdcall acmStreamPrepareHeader(long ptr long)
@ stdcall acmStreamReset(long long)
@ stdcall acmStreamSize(long long ptr long)
@ stdcall acmStreamUnprepareHeader(long ptr long)
# this is wine only
@ stdcall DriverProc(long long long long long) PCM_DriverProc

View file

@ -0,0 +1,48 @@
; File generated automatically from msacm32.spec; do not edit!
LIBRARY msacm32.dll
EXPORTS
acmDriverAddA@20 @2
acmDriverAddW@20 @3
acmDriverClose@8 @4
acmDriverDetailsA@12 @5
acmDriverDetailsW@12 @6
acmDriverEnum@12 @7
acmDriverID@12 @8
acmDriverMessage@16 @9
acmDriverOpen@12 @10
acmDriverPriority@12 @11
acmDriverRemove@8 @12
acmFilterChooseA@4 @13
acmFilterChooseW@4 @14
acmFilterDetailsA@12 @15
acmFilterDetailsW@12 @16
acmFilterEnumA@20 @17
acmFilterEnumW@20 @18
acmFilterTagDetailsA@12 @19
acmFilterTagDetailsW@12 @20
acmFilterTagEnumA@20 @21
acmFilterTagEnumW@20 @22
acmFormatChooseA@4 @23
acmFormatChooseW@4 @24
acmFormatDetailsA@12 @25
acmFormatDetailsW@12 @26
acmFormatEnumA@20 @27
acmFormatEnumW@20 @28
acmFormatSuggest@20 @29
acmFormatTagDetailsA@12 @30
acmFormatTagDetailsW@12 @31
acmFormatTagEnumA@20 @32
acmFormatTagEnumW@20 @33
acmGetVersion@0 @34
acmMetrics@12 @36
acmStreamClose@8 @37
acmStreamConvert@12 @38
acmStreamMessage@16 @39
acmStreamOpen@32 @40
acmStreamPrepareHeader@12 @41
acmStreamReset@8 @42
acmStreamSize@16 @43
acmStreamUnprepareHeader@12 @44
DriverProc@20=PCM_DriverProc@20 @1

View file

@ -0,0 +1,221 @@
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/*
* MSACM32 library
*
* Copyright 1998 Patrik Stridvall
* 1999 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "mmsystem.h"
#include "mmreg.h"
#include "msacm.h"
#include "msacmdrv.h"
#include "wineacm.h"
WINE_DEFAULT_DEBUG_CHANNEL(msacm);
/**********************************************************************/
HINSTANCE MSACM_hInstance32 = 0;
/***********************************************************************
* DllMain (MSACM32.init)
*/
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, lpvReserved);
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInstDLL);
MSACM_hHeap = HeapCreate(0, 0x10000, 0);
MSACM_hInstance32 = hInstDLL;
MSACM_RegisterAllDrivers();
break;
case DLL_PROCESS_DETACH:
MSACM_UnregisterAllDrivers();
HeapDestroy(MSACM_hHeap);
MSACM_hHeap = NULL;
MSACM_hInstance32 = NULL;
break;
default:
break;
}
return TRUE;
}
/***********************************************************************
* XRegThunkEntry (MSACM32.1)
* FIXME
* No documentation found.
*/
/***********************************************************************
* acmGetVersion (MSACM32.@)
*/
DWORD WINAPI acmGetVersion(void)
{
OSVERSIONINFOA version;
version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
if (!GetVersionExA( &version ))
return 0x04030000;
switch (version.dwPlatformId) {
case VER_PLATFORM_WIN32_NT:
return 0x04000565; /* 4.0.1381 */
default:
FIXME("%lx not supported\n", version.dwPlatformId);
case VER_PLATFORM_WIN32_WINDOWS:
return 0x04030000; /* 4.3.0 */
}
}
/***********************************************************************
* acmMessage32 (MSACM32.35)
* FIXME
* No documentation found.
*/
/***********************************************************************
* acmMetrics (MSACM32.@)
*/
MMRESULT WINAPI acmMetrics(HACMOBJ hao, UINT uMetric, LPVOID pMetric)
{
PWINE_ACMOBJ pao = MSACM_GetObj(hao, WINE_ACMOBJ_DONTCARE);
BOOL bLocal = TRUE;
PWINE_ACMDRIVERID padid;
DWORD val = 0;
int i;
MMRESULT mmr = MMSYSERR_NOERROR;
TRACE("(%p, %d, %p);\n", hao, uMetric, pMetric);
#define CheckLocal(padid) (!bLocal || ((padid)->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL))
switch (uMetric) {
case ACM_METRIC_COUNT_DRIVERS:
bLocal = FALSE;
/* fall through */
case ACM_METRIC_COUNT_LOCAL_DRIVERS:
if (hao) return MMSYSERR_INVALHANDLE;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && CheckLocal(padid))
val++;
*(LPDWORD)pMetric = val;
break;
case ACM_METRIC_COUNT_CODECS:
bLocal = FALSE;
/* fall through */
case ACM_METRIC_COUNT_LOCAL_CODECS:
if (hao) return MMSYSERR_INVALHANDLE;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC) &&
CheckLocal(padid))
val++;
*(LPDWORD)pMetric = val;
break;
case ACM_METRIC_COUNT_CONVERTERS:
bLocal = FALSE;
/* fall through */
case ACM_METRIC_COUNT_LOCAL_CONVERTERS:
if (hao) return MMSYSERR_INVALHANDLE;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CONVERTER) &&
CheckLocal(padid))
val++;
*(LPDWORD)pMetric = val;
break;
case ACM_METRIC_COUNT_FILTERS:
bLocal = FALSE;
/* fall through */
case ACM_METRIC_COUNT_LOCAL_FILTERS:
if (hao) return MMSYSERR_INVALHANDLE;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_FILTER) &&
CheckLocal(padid))
val++;
*(LPDWORD)pMetric = val;
break;
case ACM_METRIC_COUNT_DISABLED:
bLocal = FALSE;
/* fall through */
case ACM_METRIC_COUNT_LOCAL_DISABLED:
if (hao) return MMSYSERR_INVALHANDLE;
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && CheckLocal(padid))
val++;
*(LPDWORD)pMetric = val;
break;
case ACM_METRIC_MAX_SIZE_FORMAT:
if (hao == NULL) {
for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED)) {
for (i = 0; i < padid->cFormatTags; i++) {
if (val < padid->aFormatTag[i].cbwfx)
val = padid->aFormatTag[i].cbwfx;
}
}
}
} else if (pao != NULL) {
switch (pao->dwType) {
case WINE_ACMOBJ_DRIVER:
case WINE_ACMOBJ_DRIVERID:
padid = pao->pACMDriverID;
break;
default:
return MMSYSERR_INVALHANDLE;
}
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED)) {
for (i = 0; i < padid->cFormatTags; i++) {
if (val < padid->aFormatTag[i].cbwfx)
val = padid->aFormatTag[i].cbwfx;
}
}
} else {
return MMSYSERR_INVALHANDLE;
}
*(LPDWORD)pMetric = val;
break;
case ACM_METRIC_COUNT_HARDWARE:
case ACM_METRIC_HARDWARE_WAVE_INPUT:
case ACM_METRIC_HARDWARE_WAVE_OUTPUT:
case ACM_METRIC_MAX_SIZE_FILTER:
case ACM_METRIC_DRIVER_SUPPORT:
case ACM_METRIC_DRIVER_PRIORITY:
default:
FIXME("(%p, %d, %p): stub\n", hao, uMetric, pMetric);
mmr = MMSYSERR_NOTSUPPORTED;
}
return mmr;
}

View file

@ -0,0 +1,56 @@
/*
* English resource file for MS ACM
*
* Copyright 2000 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
DLG_ACMFORMATCHOOSE_ID DIALOG DISCARDABLE 10, 20, 225, 100
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Sound Selection"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "&Name:", -1, 5, 5, 115, 8, NOT WS_GROUP
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_CUSTOM, 5, 15, 115, 60,
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "&Save As...", IDD_ACMFORMATCHOOSE_BTN_SETNAME, 125, 14, 45, 14
PUSHBUTTON "&Remove", IDD_ACMFORMATCHOOSE_BTN_DELNAME, 175, 14, 45, 14
LTEXT "&Format:", -1, 5, 41, 44, 8, NOT WS_GROUP
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 50, 39, 170, 60,
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "&Attributes:", -1, 5, 59, 44, 8, NOT WS_GROUP
#if 0
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMAT, 50, 57, 170, 60,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP |
CBS_OWNERDRAWFIXED | CBS_HASSTRINGS
#else
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMAT, 50, 57, 170, 60,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
#endif
DEFPUSHBUTTON "OK", IDOK, 48, 80, 40, 14
PUSHBUTTON "Cancel", IDCANCEL, 92, 80, 40, 14
PUSHBUTTON "&Help", IDD_ACMFORMATCHOOSE_BTN_HELP, 136, 80, 40, 14
END

View file

@ -0,0 +1,57 @@
/*
* French resource file for MS ACM
*
* Copyright 2000 Eric Pouech
* Copyright 2003 Vincent Béron
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
DLG_ACMFORMATCHOOSE_ID DIALOG DISCARDABLE 10, 20, 225, 100
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Sélection du son"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "&Nom :", -1, 5, 5, 115, 8, NOT WS_GROUP
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_CUSTOM, 5, 15, 115, 60,
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "&Enregistrer sous...", IDD_ACMFORMATCHOOSE_BTN_SETNAME, 125, 14, 45, 14
PUSHBUTTON "&Retirer", IDD_ACMFORMATCHOOSE_BTN_DELNAME, 175, 14, 45, 14
LTEXT "&Format :", -1, 5, 41, 44, 8, NOT WS_GROUP
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 50, 39, 170, 60,
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "&Attributs :", -1, 5, 59, 44, 8, NOT WS_GROUP
#if 0
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMAT, 50, 57, 170, 60,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP |
CBS_OWNERDRAWFIXED | CBS_HASSTRINGS
#else
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMAT, 50, 57, 170, 60,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
#endif
DEFPUSHBUTTON "OK", IDOK, 48, 80, 40, 14
PUSHBUTTON "Annuler", IDCANCEL, 92, 80, 40, 14
PUSHBUTTON "&Aide", IDD_ACMFORMATCHOOSE_BTN_HELP, 136, 80, 40, 14
END

View file

@ -0,0 +1,57 @@
/*
* Italian resource file for MS ACM
*
* Copyright 2000 Eric Pouech
* Copyright 2003 Ivan Leo Murray-Smith
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
LANGUAGE LANG_ITALIAN, SUBLANG_DEFAULT
DLG_ACMFORMATCHOOSE_ID DIALOG DISCARDABLE 10, 20, 225, 100
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Selezione dell'audio"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "&Nome:", -1, 5, 5, 115, 8, NOT WS_GROUP
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_CUSTOM, 5, 15, 115, 60,
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "&Salva con nome...", IDD_ACMFORMATCHOOSE_BTN_SETNAME, 125, 14, 45, 14
PUSHBUTTON "&Rimuovi", IDD_ACMFORMATCHOOSE_BTN_DELNAME, 175, 14, 45, 14
LTEXT "&Formato:", -1, 5, 41, 44, 8, NOT WS_GROUP
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 50, 39, 170, 60,
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "&Attributi:", -1, 5, 59, 44, 8, NOT WS_GROUP
#if 0
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMAT, 50, 57, 170, 60,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP |
CBS_OWNERDRAWFIXED | CBS_HASSTRINGS
#else
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMAT, 50, 57, 170, 60,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
#endif
DEFPUSHBUTTON "OK", IDOK, 48, 80, 40, 14
PUSHBUTTON "Anulla", IDCANCEL, 92, 80, 40, 14
PUSHBUTTON "&Aiuto", IDD_ACMFORMATCHOOSE_BTN_HELP, 136, 80, 40, 14
END

View file

@ -0,0 +1,56 @@
/*
* msacm (Dutch resources)
*
* Copyright 2003 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
LANGUAGE LANG_DUTCH, SUBLANG_DEFAULT
DLG_ACMFORMATCHOOSE_ID DIALOG DISCARDABLE 10, 20, 225, 100
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Geluidskeuze"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "&Naam:", -1, 5, 5, 115, 8, NOT WS_GROUP
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_CUSTOM, 5, 15, 115, 60,
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "&Opslaan als...", IDD_ACMFORMATCHOOSE_BTN_SETNAME, 125, 14, 45, 14
PUSHBUTTON "&Verwijderen", IDD_ACMFORMATCHOOSE_BTN_DELNAME, 175, 14, 45, 14
LTEXT "&Formaat:", -1, 5, 41, 44, 8, NOT WS_GROUP
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 50, 39, 170, 60,
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "&Attributen:", -1, 5, 59, 44, 8, NOT WS_GROUP
#if 0
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMAT, 50, 57, 170, 60,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP |
CBS_OWNERDRAWFIXED | CBS_HASSTRINGS
#else
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMAT, 50, 57, 170, 60,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
#endif
DEFPUSHBUTTON "OK", IDOK, 48, 80, 40, 14
PUSHBUTTON "Annuleren", IDCANCEL, 92, 80, 40, 14
PUSHBUTTON "&Help", IDD_ACMFORMATCHOOSE_BTN_HELP, 136, 80, 40, 14
END

View file

@ -0,0 +1,56 @@
/*
* Portuguese resource file for MS ACM
*
* Copyright 2003 Marcelo Duarte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
LANGUAGE LANG_PORTUGUESE, SUBLANG_DEFAULT
DLG_ACMFORMATCHOOSE_ID DIALOG DISCARDABLE 10, 20, 225, 100
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Seleção de som"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "&Nome:", -1, 5, 5, 115, 8, NOT WS_GROUP
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_CUSTOM, 5, 15, 115, 60,
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "&Salvar como...", IDD_ACMFORMATCHOOSE_BTN_SETNAME, 125, 14, 45, 14
PUSHBUTTON "&Remover", IDD_ACMFORMATCHOOSE_BTN_DELNAME, 175, 14, 45, 14
LTEXT "&Formato:", -1, 5, 41, 44, 8, NOT WS_GROUP
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 50, 39, 170, 60,
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "&Atributos:", -1, 5, 59, 44, 8, NOT WS_GROUP
#if 0
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMAT, 50, 57, 170, 60,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP |
CBS_OWNERDRAWFIXED | CBS_HASSTRINGS
#else
COMBOBOX IDD_ACMFORMATCHOOSE_CMB_FORMAT, 50, 57, 170, 60,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
#endif
DEFPUSHBUTTON "OK", IDOK, 48, 80, 40, 14
PUSHBUTTON "Cancelar", IDCANCEL, 92, 80, 40, 14
PUSHBUTTON "Aj&uda", IDD_ACMFORMATCHOOSE_BTN_HELP, 136, 80, 40, 14
END

View file

@ -0,0 +1,463 @@
/*
* MSACM library
*
* Copyright 1998 Patrik Stridvall
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "mmsystem.h"
#include "mmreg.h"
#include "msacm.h"
#include "msacmdrv.h"
#include "wineacm.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msacm);
/**************************************************************************
* DllEntryPoint (MSACM.255)
*
* MSACM DLL entry point
*
*/
BOOL WINAPI MSACM_DllEntryPoint(DWORD fdwReason, HINSTANCE16 hinstDLL, WORD ds,
WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
{
static HANDLE hndl;
TRACE("0x%x 0x%lx\n", hinstDLL, fdwReason);
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
if (!hndl && !(hndl = LoadLibraryA("MSACM32.DLL"))) {
ERR("Could not load sibling MsAcm32.dll\n");
return FALSE;
}
break;
case DLL_PROCESS_DETACH:
FreeLibrary(hndl);
hndl = 0;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
/***********************************************************************
* acmGetVersion (MSACM.7)
*/
DWORD WINAPI acmGetVersion16(void)
{
return acmGetVersion();
}
/***********************************************************************
* acmMetrics (MSACM.8)
*/
MMRESULT16 WINAPI acmMetrics16(
HACMOBJ16 hao, UINT16 uMetric, LPVOID pMetric)
{
FIXME("(0x%04x, %d, %p): semi-stub\n", hao, uMetric, pMetric);
if(!hao) return acmMetrics(0, uMetric, pMetric);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmDriverEnum (MSACM.10)
*/
MMRESULT16 WINAPI acmDriverEnum16(
ACMDRIVERENUMCB16 fnCallback, DWORD dwInstance, DWORD fdwEnum)
{
FIXME("(%p, %ld, %ld): stub\n",
fnCallback, dwInstance, fdwEnum
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmDriverDetails (MSACM.11)
*/
MMRESULT16 WINAPI acmDriverDetails16(
HACMDRIVERID16 hadid, LPACMDRIVERDETAILS16 padd, DWORD fdwDetails)
{
FIXME("(0x%04x, %p, %ld): stub\n", hadid, padd, fdwDetails);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmDriverAdd (MSACM.12)
*/
MMRESULT16 WINAPI acmDriverAdd16(
LPHACMDRIVERID16 phadid, HINSTANCE16 hinstModule,
LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
{
FIXME("(%p, 0x%04x, %ld, %ld, %ld): stub\n",
phadid, hinstModule, lParam, dwPriority, fdwAdd
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmDriverRemove (MSACM.13)
*/
MMRESULT16 WINAPI acmDriverRemove16(
HACMDRIVERID16 hadid, DWORD fdwRemove)
{
FIXME("(0x%04x, %ld): stub\n", hadid, fdwRemove);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmDriverOpen (MSACM.14)
*/
MMRESULT16 WINAPI acmDriverOpen16(
LPHACMDRIVER16 phad, HACMDRIVERID16 hadid, DWORD fdwOpen)
{
FIXME("(%p, 0x%04x, %ld): stub\n", phad, hadid, fdwOpen);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmDriverClose (MSACM.15)
*/
MMRESULT16 WINAPI acmDriverClose16(
HACMDRIVER16 had, DWORD fdwClose)
{
FIXME("(0x%04x, %ld): stub\n", had, fdwClose);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmDriverMessage (MSACM.16)
*/
LRESULT WINAPI acmDriverMessage16(
HACMDRIVER16 had, UINT16 uMsg, LPARAM lParam1, LPARAM lParam2)
{
FIXME("(0x%04x, %d, %ld, %ld): stub\n",
had, uMsg, lParam1, lParam2
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/***********************************************************************
* acmDriverID (MSACM.17)
*/
MMRESULT16 WINAPI acmDriverID16(
HACMOBJ16 hao, LPHACMDRIVERID16 phadid, DWORD fdwDriverID)
{
FIXME("(0x%04x, %p, %ld): stub\n", hao, phadid, fdwDriverID);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmDriverPriority (MSACM.18)
*/
MMRESULT16 WINAPI acmDriverPriority16(
HACMDRIVERID16 hadid, DWORD dwPriority, DWORD fdwPriority)
{
FIXME("(0x%04x, %ld, %ld): stub\n",
hadid, dwPriority, fdwPriority
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFormatTagDetails (MSACM.30)
*/
MMRESULT16 WINAPI acmFormatTagDetails16(
HACMDRIVER16 had, LPACMFORMATTAGDETAILS16 paftd, DWORD fdwDetails)
{
FIXME("(0x%04x, %p, %ld): stub\n", had, paftd, fdwDetails);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFormatTagEnum (MSACM.31)
*/
MMRESULT16 WINAPI acmFormatTagEnum16(
HACMDRIVER16 had, LPACMFORMATTAGDETAILS16 paftd,
ACMFORMATTAGENUMCB16 fnCallback, DWORD dwInstance, DWORD fdwEnum)
{
FIXME("(0x%04x, %p, %p, %ld, %ld): stub\n",
had, paftd, fnCallback, dwInstance, fdwEnum
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFormatChoose (MSACM.40)
*/
MMRESULT16 WINAPI acmFormatChoose16(
LPACMFORMATCHOOSE16 pafmtc)
{
FIXME("(%p): stub\n", pafmtc);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFormatDetails (MSACM.41)
*/
MMRESULT16 WINAPI acmFormatDetails16(
HACMDRIVER16 had, LPACMFORMATDETAILS16 pafd, DWORD fdwDetails)
{
FIXME("(0x%04x, %p, %ld): stub\n", had, pafd, fdwDetails);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFormatEnum (MSACM.42)
*/
MMRESULT16 WINAPI acmFormatEnum16(
HACMDRIVER16 had, LPACMFORMATDETAILS16 pafd,
ACMFORMATENUMCB16 fnCallback, DWORD dwInstance, DWORD fdwEnum)
{
FIXME("(0x%04x, %p, %p, %ld, %ld): stub\n",
had, pafd, fnCallback, dwInstance, fdwEnum
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFormatSuggest (MSACM.45)
*/
MMRESULT16 WINAPI acmFormatSuggest16(
HACMDRIVER16 had, LPWAVEFORMATEX pwfxSrc,
LPWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest)
{
FIXME("(0x%04x, %p, %p, %ld, %ld): stub\n",
had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFilterTagDetails (MSACM.50)
*/
MMRESULT16 WINAPI acmFilterTagDetails16(
HACMDRIVER16 had, LPACMFILTERTAGDETAILS16 paftd, DWORD fdwDetails)
{
FIXME("(0x%04x, %p, %ld): stub\n", had, paftd, fdwDetails);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFilterTagEnum (MSACM.51)
*/
MMRESULT16 WINAPI acmFilterTagEnum16(
HACMDRIVER16 had, LPACMFILTERTAGDETAILS16 paftd,
ACMFILTERTAGENUMCB16 fnCallback, DWORD dwInstance, DWORD fdwEnum)
{
FIXME("(0x%04x, %p, %p, %ld, %ld): stub\n",
had, paftd, fnCallback, dwInstance, fdwEnum
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFilterChoose (MSACM.60)
*/
MMRESULT16 WINAPI acmFilterChoose16(
LPACMFILTERCHOOSE16 pafltrc)
{
FIXME("(%p): stub\n", pafltrc);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFilterDetails (MSACM.61)
*/
MMRESULT16 WINAPI acmFilterDetails16(
HACMDRIVER16 had, LPACMFILTERDETAILS16 pafd, DWORD fdwDetails)
{
FIXME("(0x%04x, %p, %ld): stub\n", had, pafd, fdwDetails);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmFilterEnum (MSACM.62)
*/
MMRESULT16 WINAPI acmFilterEnum16(
HACMDRIVER16 had, LPACMFILTERDETAILS16 pafd,
ACMFILTERENUMCB16 fnCallback, DWORD dwInstance, DWORD fdwEnum)
{
FIXME("(0x%04x, %p, %p, %ld, %ld): stub\n",
had, pafd, fnCallback, dwInstance, fdwEnum
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmStreamOpen (MSACM.70)
*/
MMRESULT16 WINAPI acmStreamOpen16(
LPHACMSTREAM16 phas, HACMDRIVER16 had,
LPWAVEFORMATEX pwfxSrc, LPWAVEFORMATEX pwfxDst,
LPWAVEFILTER pwfltr, DWORD dwCallback,
DWORD dwInstance, DWORD fdwOpen)
{
FIXME("(%p, 0x%04x, %p, %p, %p, %ld, %ld, %ld): stub\n",
phas, had, pwfxSrc, pwfxDst, pwfltr,
dwCallback, dwInstance, fdwOpen
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmStreamClose (MSACM.71)
*/
MMRESULT16 WINAPI acmStreamClose16(
HACMSTREAM16 has, DWORD fdwClose)
{
FIXME("(0x%04x, %ld): stub\n", has, fdwClose);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmStreamSize (MSACM.72)
*/
MMRESULT16 WINAPI acmStreamSize16(
HACMSTREAM16 has, DWORD cbInput,
LPDWORD pdwOutputBytes, DWORD fdwSize)
{
FIXME("(0x%04x, %ld, %p, %ld): stub\n",
has, cbInput, pdwOutputBytes, fdwSize
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmStreamConvert (MSACM.75)
*/
MMRESULT16 WINAPI acmStreamConvert16(
HACMSTREAM16 has, LPACMSTREAMHEADER16 pash, DWORD fdwConvert)
{
FIXME("(0x%04x, %p, %ld): stub\n", has, pash, fdwConvert);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmStreamReset (MSACM.76)
*/
MMRESULT16 WINAPI acmStreamReset16(
HACMSTREAM16 has, DWORD fdwReset)
{
FIXME("(0x%04x, %ld): stub\n", has, fdwReset);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmStreamPrepareHeader (MSACM.77)
*/
MMRESULT16 WINAPI acmStreamPrepareHeader16(
HACMSTREAM16 has, LPACMSTREAMHEADER16 pash, DWORD fdwPrepare)
{
FIXME("(0x%04x, %p, %ld): stub\n", has, pash, fdwPrepare);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* acmStreamUnprepareHeader (MSACM.78)
*/
MMRESULT16 WINAPI acmStreamUnprepareHeader16(
HACMSTREAM16 has, LPACMSTREAMHEADER16 pash, DWORD fdwUnprepare)
{
FIXME("(0x%04x, %p, %ld): stub\n",
has, pash, fdwUnprepare
);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return MMSYSERR_ERROR;
}
/***********************************************************************
* ACMAPPLICATIONEXIT (MSACM.150)
* FIXME
* No documentation found.
*/
/***********************************************************************
* ACMHUGEPAGELOCK (MSACM.175)
*FIXME
* No documentation found.
*/
/***********************************************************************
* ACMHUGEPAGEUNLOCK (MSACM.176)
* FIXME
* No documentation found.
*/
/***********************************************************************
* ACMOPENCONVERSION (MSACM.200)
* FIXME
* No documentation found.
*/
/***********************************************************************
* ACMCLOSECONVERSION (MSACM.201)
* FIXME
* No documentation found.
*/
/***********************************************************************
* ACMCONVERT (MSACM.202)
* FIXME
* No documentation found.
*/
/***********************************************************************
* ACMCHOOSEFORMAT (MSACM.203)
* FIXME
* No documentation found.
*/

View file

@ -0,0 +1,3 @@
Makefile
msadp32.acm.dbg.c
msadp32.acm.spec.c

View file

@ -0,0 +1,12 @@
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = msadp32.acm
IMPORTS = winmm user32 kernel32
C_SRCS = msadp32.c
@MAKE_DLL_RULES@
### Dependencies:

View file

@ -0,0 +1 @@
@ stdcall DriverProc (long long long long long) ADPCM_DriverProc

View file

@ -0,0 +1,781 @@
/*
* MS ADPCM handling
*
* Copyright (C) 2002 Eric Pouech
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "mmsystem.h"
#include "mmreg.h"
#include "msacm.h"
#include "msacmdrv.h"
#include "wine/debug.h"
/* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */
WINE_DEFAULT_DEBUG_CHANNEL(adpcm);
/***********************************************************************
* ADPCM_drvOpen
*/
static DWORD ADPCM_drvOpen(LPCSTR str)
{
return 1;
}
/***********************************************************************
* ADPCM_drvClose
*/
static DWORD ADPCM_drvClose(DWORD dwDevID)
{
return 1;
}
typedef struct tagAcmAdpcmData
{
void (*convert)(PACMDRVSTREAMINSTANCE adsi,
const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
} AcmAdpcmData;
/* table to list all supported formats... those are the basic ones. this
* also helps given a unique index to each of the supported formats
*/
typedef struct
{
int nChannels;
int nBits;
int rate;
} Format;
static Format PCM_Formats[] =
{
{1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
{1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
{1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
{1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
};
static Format ADPCM_Formats[] =
{
{1, 4, 8000}, {2, 4, 8000}, {1, 4, 11025}, {2, 4, 11025},
{1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100},
};
#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
#define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0]))
static int MS_Delta[] =
{
230, 230, 230, 230, 307, 409, 512, 614,
768, 614, 512, 409, 307, 230, 230, 230
};
static ADPCMCOEFSET MSADPCM_CoeffSet[] =
{
{256, 0}, {512, -256}, {0, 0}, {192, 64}, {240, 0}, {460, -208}, {392, -232}
};
/***********************************************************************
* ADPCM_GetFormatIndex
*/
static DWORD ADPCM_GetFormatIndex(WAVEFORMATEX* wfx)
{
int i, hi;
Format* fmts;
switch (wfx->wFormatTag)
{
case WAVE_FORMAT_PCM:
hi = NUM_PCM_FORMATS;
fmts = PCM_Formats;
break;
case WAVE_FORMAT_ADPCM:
hi = NUM_ADPCM_FORMATS;
fmts = ADPCM_Formats;
break;
default:
return 0xFFFFFFFF;
}
for (i = 0; i < hi; i++)
{
if (wfx->nChannels == fmts[i].nChannels &&
wfx->nSamplesPerSec == fmts[i].rate &&
wfx->wBitsPerSample == fmts[i].nBits)
return i;
}
return 0xFFFFFFFF;
}
static void init_wfx_adpcm(ADPCMWAVEFORMAT* awfx)
{
register WAVEFORMATEX* pwfx = &awfx->wfx;
/* we assume wFormatTag, nChannels, nSamplesPerSec and wBitsPerSample
* have been initialized... */
if (pwfx->wFormatTag != WAVE_FORMAT_ADPCM) {FIXME("wrong FT\n"); return;}
if (ADPCM_GetFormatIndex(pwfx) == 0xFFFFFFFF) {FIXME("wrong fmt\n"); return;}
switch (pwfx->nSamplesPerSec)
{
case 8000: pwfx->nBlockAlign = 256; break;
case 11025: pwfx->nBlockAlign = 256; break;
case 22050: pwfx->nBlockAlign = 512; break;
default:
case 44100: pwfx->nBlockAlign = 1024; break;
}
pwfx->cbSize = 2 * sizeof(WORD) + 7 * sizeof(ADPCMCOEFSET);
/* 7 is the size of the block head (which contains two samples) */
awfx->wSamplesPerBlock = (pwfx->nBlockAlign - (7 * pwfx->nChannels)) * (2 / pwfx->nChannels) + 2;
pwfx->nAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) / awfx->wSamplesPerBlock;
awfx->wNumCoef = 7;
memcpy(awfx->aCoef, MSADPCM_CoeffSet, 7 * sizeof(ADPCMCOEFSET));
}
/***********************************************************************
* R16
*
* Read a 16 bit sample (correctly handles endianess)
*/
static inline short R16(const unsigned char* src)
{
return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
}
/***********************************************************************
* W16
*
* Write a 16 bit sample (correctly handles endianess)
*/
static inline void W16(unsigned char* dst, short s)
{
dst[0] = LOBYTE(s);
dst[1] = HIBYTE(s);
}
static inline void clamp_sample(int* sample)
{
if (*sample < -32768) *sample = -32768;
if (*sample > 32767) *sample = 32767;
}
static inline void process_nibble(unsigned nibble, int* idelta,
int* sample1, int* sample2,
const ADPCMCOEFSET* coeff)
{
int sample;
int snibble;
/* nibble is in fact a signed 4 bit integer => propagate sign if needed */
snibble = (nibble & 0x08) ? (nibble - 16) : nibble;
sample = ((*sample1 * coeff->iCoef1) + (*sample2 * coeff->iCoef2)) / 256 +
snibble * *idelta;
clamp_sample(&sample);
*sample2 = *sample1;
*sample1 = sample;
*idelta = ((MS_Delta[nibble] * *idelta) / 256);
if (*idelta < 16) *idelta = 16;
}
static void cvtSSms16K(PACMDRVSTREAMINSTANCE adsi,
const unsigned char* src, LPDWORD nsrc,
unsigned char* dst, LPDWORD ndst)
{
int ideltaL, ideltaR;
int sample1L, sample2L;
int sample1R, sample2R;
ADPCMCOEFSET coeffL, coeffR;
int nsamp;
int nsamp_blk = ((ADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
*ndst / (nsamp_blk * 2 * 2));
*nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
*ndst = nblock * nsamp_blk * 2 * 2;
nsamp_blk -= 2; /* see below for samples from block head */
for (; nblock > 0; nblock--)
{
const unsigned char* in_src = src;
assert(*src <= 6);
coeffL = MSADPCM_CoeffSet[*src++];
assert(*src <= 6);
coeffR = MSADPCM_CoeffSet[*src++];
ideltaL = R16(src); src += 2;
ideltaR = R16(src); src += 2;
sample1L = R16(src); src += 2;
sample1R = R16(src); src += 2;
sample2L = R16(src); src += 2;
sample2R = R16(src); src += 2;
/* store samples from block head */
W16(dst, sample2L); dst += 2;
W16(dst, sample2R); dst += 2;
W16(dst, sample1L); dst += 2;
W16(dst, sample1R); dst += 2;
for (nsamp = nsamp_blk; nsamp > 0; nsamp--)
{
process_nibble(*src >> 4, &ideltaL, &sample1L, &sample2L, &coeffL);
W16(dst, sample1L); dst += 2;
process_nibble(*src++ & 0x0F, &ideltaR, &sample1R, &sample2R, &coeffR);
W16(dst, sample1R); dst += 2;
}
src = in_src + adsi->pwfxSrc->nBlockAlign;
}
}
static void cvtMMms16K(PACMDRVSTREAMINSTANCE adsi,
const unsigned char* src, LPDWORD nsrc,
unsigned char* dst, LPDWORD ndst)
{
int idelta;
int sample1, sample2;
ADPCMCOEFSET coeff;
int nsamp;
int nsamp_blk = ((ADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
*ndst / (nsamp_blk * 2));
*nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
*ndst = nblock * nsamp_blk * 2;
nsamp_blk -= 2; /* see below for samples from block head */
for (; nblock > 0; nblock--)
{
const unsigned char* in_src = src;
assert(*src <= 6);
coeff = MSADPCM_CoeffSet[*src++];
idelta = R16(src); src += 2;
sample1 = R16(src); src += 2;
sample2 = R16(src); src += 2;
/* store samples from block head */
W16(dst, sample2); dst += 2;
W16(dst, sample1); dst += 2;
for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
{
process_nibble(*src >> 4, &idelta, &sample1, &sample2, &coeff);
W16(dst, sample1); dst += 2;
process_nibble(*src++ & 0x0F, &idelta, &sample1, &sample2, &coeff);
W16(dst, sample1); dst += 2;
}
src = in_src + adsi->pwfxSrc->nBlockAlign;
}
}
#if 0
static void cvtSS16msK(PACMDRVSTREAMINSTANCE adsi,
const unsigned char* src, LPDWORD nsrc,
unsigned char* dst, LPDWORD ndst)
{
}
static void cvtMM16msK(PACMDRVSTREAMINSTANCE adsi,
const unsigned char* src, LPDWORD nsrc,
unsigned char* dst, LPDWORD ndst)
{
}
#endif
/***********************************************************************
* ADPCM_DriverDetails
*
*/
static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add)
{
add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
add->wMid = 0xFF;
add->wPid = 0x00;
add->vdwACM = 0x01000000;
add->vdwDriver = 0x01000000;
add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
add->cFormatTags = 2; /* PCM, MS ADPCM */
add->cFilterTags = 0;
add->hicon = NULL;
MultiByteToWideChar( CP_ACP, 0, "WINE-MS ADPCM", -1,
add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, "Wine MS ADPCM converter", -1,
add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
add->szFeatures[0] = 0;
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_FormatTagDetails
*
*/
static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
{
static WCHAR szPcm[]={'P','C','M',0};
static WCHAR szMsAdPcm[]={'M','S',' ','A','d','P','C','M',0};
switch (dwQuery)
{
case ACM_FORMATTAGDETAILSF_INDEX:
if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
break;
case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
{
aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_ADPCM is bigger than PCM */
break;
}
/* fall thru */
case ACM_FORMATTAGDETAILSF_FORMATTAG:
switch (aftd->dwFormatTag)
{
case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
case WAVE_FORMAT_ADPCM: aftd->dwFormatTagIndex = 1; break;
default: return ACMERR_NOTPOSSIBLE;
}
break;
default:
WARN("Unsupported query %08lx\n", dwQuery);
return MMSYSERR_NOTSUPPORTED;
}
aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
switch (aftd->dwFormatTagIndex)
{
case 0:
aftd->dwFormatTag = WAVE_FORMAT_PCM;
aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
aftd->cStandardFormats = NUM_PCM_FORMATS;
lstrcpyW(aftd->szFormatTag, szPcm);
break;
case 1:
aftd->dwFormatTag = WAVE_FORMAT_ADPCM;
aftd->cbFormatSize = sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET);
aftd->cStandardFormats = NUM_ADPCM_FORMATS;
lstrcpyW(aftd->szFormatTag, szMsAdPcm);
break;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_FormatDetails
*
*/
static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
{
switch (dwQuery)
{
case ACM_FORMATDETAILSF_FORMAT:
if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
break;
case ACM_FORMATDETAILSF_INDEX:
afd->pwfx->wFormatTag = afd->dwFormatTag;
switch (afd->dwFormatTag)
{
case WAVE_FORMAT_PCM:
if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
/* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
* afd->pwfx->cbSize = 0;
*/
afd->pwfx->nBlockAlign =
(afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
afd->pwfx->nAvgBytesPerSec =
afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
break;
case WAVE_FORMAT_ADPCM:
if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE;
if (afd->cbwfx < sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET))
return ACMERR_NOTPOSSIBLE;
afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels;
afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate;
afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits;
init_wfx_adpcm((ADPCMWAVEFORMAT*)afd->pwfx);
break;
default:
WARN("Unsupported tag %08lx\n", afd->dwFormatTag);
return MMSYSERR_INVALPARAM;
}
break;
default:
WARN("Unsupported query %08lx\n", dwQuery);
return MMSYSERR_NOTSUPPORTED;
}
afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
afd->szFormat[0] = 0; /* let MSACM format this for us... */
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_FormatSuggest
*
*/
static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
{
/* some tests ... */
if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
/* FIXME: should do those tests against the real size (according to format tag */
/* If no suggestion for destination, then copy source value */
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
{
if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
adfs->pwfxDst->wBitsPerSample = 4;
else
adfs->pwfxDst->wBitsPerSample = 16;
}
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
{
if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
adfs->pwfxDst->wFormatTag = WAVE_FORMAT_ADPCM;
else
adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
}
/* check if result is ok */
if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
/* recompute other values */
switch (adfs->pwfxDst->wFormatTag)
{
case WAVE_FORMAT_PCM:
adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
break;
case WAVE_FORMAT_ADPCM:
init_wfx_adpcm((ADPCMWAVEFORMAT*)adfs->pwfxDst);
break;
default:
FIXME("\n");
break;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_Reset
*
*/
static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad)
{
}
/***********************************************************************
* ADPCM_StreamOpen
*
*/
static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
{
AcmAdpcmData* aad;
assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
return ACMERR_NOTPOSSIBLE;
aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData));
if (aad == 0) return MMSYSERR_NOMEM;
adsi->dwDriver = (DWORD)aad;
if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
goto theEnd;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
/* resampling or mono <=> stereo not available
* ADPCM algo only define 16 bit per sample output
*/
if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
adsi->pwfxDst->wBitsPerSample != 16)
goto theEnd;
#if 0
{
unsigned int nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
FIXME("spb=%u\n", nspb);
/* we check that in a block, after the header, samples are present on
* 4-sample packet pattern
* we also check that the block alignement is bigger than the expected size
*/
if (((nspb - 1) & 3) != 0) goto theEnd;
if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign)
goto theEnd;
}
#endif
/* adpcm decoding... */
if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2)
aad->convert = cvtSSms16K;
if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1)
aad->convert = cvtMMms16K;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM)
{
if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
adsi->pwfxSrc->wBitsPerSample != 16)
goto theEnd;
#if 0
nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock;
FIXME("spb=%u\n", nspb);
/* we check that in a block, after the header, samples are present on
* 4-sample packet pattern
* we also check that the block alignement is bigger than the expected size
*/
if (((nspb - 1) & 3) != 0) goto theEnd;
if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign)
goto theEnd;
#endif
#if 0
/* adpcm coding... */
if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2)
aad->convert = cvtSS16msK;
if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1)
aad->convert = cvtMM16msK;
#endif
FIXME("We don't support encoding yet\n");
goto theEnd;
}
else goto theEnd;
ADPCM_Reset(adsi, aad);
return MMSYSERR_NOERROR;
theEnd:
HeapFree(GetProcessHeap(), 0, aad);
adsi->dwDriver = 0L;
return MMSYSERR_NOTSUPPORTED;
}
/***********************************************************************
* ADPCM_StreamClose
*
*/
static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
{
HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_round
*
*/
static inline DWORD ADPCM_round(DWORD a, DWORD b, DWORD c)
{
assert(a && b && c);
/* to be sure, always return an entire number of c... */
return ((double)a * (double)b + (double)c - 1) / (double)c;
}
/***********************************************************************
* ADPCM_StreamSize
*
*/
static LRESULT ADPCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
{
switch (adss->fdwSize)
{
case ACM_STREAMSIZEF_DESTINATION:
/* cbDstLength => cbSrcLength */
if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM)
{
/* don't take block overhead into account, doesn't matter too much */
adss->cbSrcLength = adss->cbDstLength * 4;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
FIXME("misses the block header overhead\n");
adss->cbSrcLength = 256 + adss->cbDstLength / 4;
}
else
{
return MMSYSERR_NOTSUPPORTED;
}
break;
case ACM_STREAMSIZEF_SOURCE:
/* cbSrcLength => cbDstLength */
if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM)
{
FIXME("misses the block header overhead\n");
adss->cbDstLength = 256 + adss->cbSrcLength / 4;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
/* don't take block overhead into account, doesn't matter too much */
adss->cbDstLength = adss->cbSrcLength * 4;
}
else
{
return MMSYSERR_NOTSUPPORTED;
}
break;
default:
WARN("Unsupported query %08lx\n", adss->fdwSize);
return MMSYSERR_NOTSUPPORTED;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_StreamConvert
*
*/
static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
{
AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver;
DWORD nsrc = adsh->cbSrcLength;
DWORD ndst = adsh->cbDstLength;
if (adsh->fdwConvert &
~(ACM_STREAMCONVERTF_BLOCKALIGN|
ACM_STREAMCONVERTF_END|
ACM_STREAMCONVERTF_START))
{
FIXME("Unsupported fdwConvert (%08lx), ignoring it\n", adsh->fdwConvert);
}
/* ACM_STREAMCONVERTF_BLOCKALIGN
* currently all conversions are block aligned, so do nothing for this flag
* ACM_STREAMCONVERTF_END
* no pending data, so do nothing for this flag
*/
if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
{
ADPCM_Reset(adsi, aad);
}
aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
adsh->cbSrcLengthUsed = nsrc;
adsh->cbDstLengthUsed = ndst;
return MMSYSERR_NOERROR;
}
/**************************************************************************
* ADPCM_DriverProc [exported]
*/
LRESULT CALLBACK ADPCM_DriverProc(DWORD dwDevID, HDRVR hDriv, UINT wMsg,
LPARAM dwParam1, LPARAM dwParam2)
{
TRACE("(%08lx %08lx %04x %08lx %08lx);\n",
dwDevID, (DWORD)hDriv, wMsg, dwParam1, dwParam2);
switch (wMsg)
{
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1);
case DRV_CLOSE: return ADPCM_drvClose(dwDevID);
case DRV_ENABLE: return 1;
case DRV_DISABLE: return 1;
case DRV_QUERYCONFIGURE: return 1;
case DRV_CONFIGURE: MessageBoxA(0, "MSACM MS ADPCM filter !", "Wine Driver", MB_OK); return 1;
case DRV_INSTALL: return DRVCNF_RESTART;
case DRV_REMOVE: return DRVCNF_RESTART;
case ACMDM_DRIVER_NOTIFY:
/* no caching from other ACM drivers is done so far */
return MMSYSERR_NOERROR;
case ACMDM_DRIVER_DETAILS:
return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
case ACMDM_FORMATTAG_DETAILS:
return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
case ACMDM_FORMAT_DETAILS:
return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
case ACMDM_FORMAT_SUGGEST:
return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
case ACMDM_STREAM_OPEN:
return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
case ACMDM_STREAM_CLOSE:
return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
case ACMDM_STREAM_SIZE:
return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
case ACMDM_STREAM_CONVERT:
return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
/* this converter is not a hardware driver */
case ACMDM_FILTERTAG_DETAILS:
case ACMDM_FILTER_DETAILS:
/* this converter is not a filter */
case ACMDM_STREAM_RESET:
/* only needed for asynchronous driver... we aren't, so just say it */
return MMSYSERR_NOTSUPPORTED;
case ACMDM_STREAM_PREPARE:
case ACMDM_STREAM_UNPREPARE:
/* nothing special to do here... so don't do anything */
return MMSYSERR_NOERROR;
default:
return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
}
return 0;
}

View file

@ -746,9 +746,15 @@ static BOOL MMDRV_InitHardcoded(void)
#ifndef __REACTOS__
MMDRV_Install("wineoss.drv", "wineoss.drv", FALSE);
#endif /* __REACTOS__ */
#ifdef __REACTOS__
// AG: TESTING:
MMDRV_Install("mmdrv.dll", "mmdrv.dll", FALSE);
#endif
/* finish with mappers */
MMDRV_Install("wavemapper", "msacm.drv", TRUE);
MMDRV_Install("midimapper", "midimap.drv", TRUE);
MMDRV_Install("wavemapper", "msacm32.dll", TRUE);
MMDRV_Install("midimapper", "midimap.dll", TRUE);
return TRUE;
}

View file

@ -0,0 +1,9 @@
*.a
*.d
*.o
*.dll
*.coff
*.sym
*.map
*.tmp
temp.exp

View file

@ -0,0 +1,13 @@
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = midimap.drv
IMPORTS = winmm user32 advapi32 kernel32
C_SRCS = \
midimap.c
@MAKE_DLL_RULES@
### Dependencies:

View file

@ -0,0 +1,21 @@
# $Id: Makefile.ros,v 1.1 2004/03/10 15:22:44 silverblade Exp $
TARGET_NAME = midimap
TARGET_OBJECTS = midimap.o
TARGET_CFLAGS = -D__REACTOS__
TARGET_SDKLIBS = winmm.a libwine.a ws2_32.a wine_uuid.a ntdll.a
TARGET_BASE = 0x77300000
TARGET_RC_SRCS = midimap.rc
TARGET_RC_BINSRC = midimap.rc
TARGET_RC_BINARIES =
default: all
DEP_OBJECTS = $(TARGET_OBJECTS)
include $(TOOLS_PATH)/depend.mk

View file

@ -0,0 +1,21 @@
# $Id: Makefile.ros-template,v 1.1 2004/03/10 15:22:44 silverblade Exp $
TARGET_NAME = midimap
TARGET_OBJECTS = @C_SRCS@
TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__
TARGET_SDKLIBS = @IMPORTS@ winmm.a libwine.a wine_uuid.a ntdll.a
TARGET_BASE = 0x76160000
TARGET_RC_SRCS = @RC_SRCS@
TARGET_RC_BINSRC = @RC_BINSRC@
TARGET_RC_BINARIES = @RC_BINARIES@
default: all
DEP_OBJECTS = $(TARGET_OBJECTS)
include $(TOOLS_PATH)/depend.mk

View file

@ -0,0 +1,9 @@
# $Id: makefile,v 1.1 2004/03/10 15:22:44 silverblade Exp $
PATH_TO_TOP = ../../..
TARGET_TYPE = winedll
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk

View file

@ -0,0 +1,555 @@
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/*
* Wine MIDI mapper driver
*
* Copyright 1999, 2000, 2001 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* TODO:
* notification has to be implemented
* IDF file loading
*/
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmddk.h"
#include "winreg.h"
#include "wine/debug.h"
/*
* Here's how Windows stores the midiOut mapping information.
*
* Full form (in HKU) is:
*
* [Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap] 988836060
* "AutoScheme"=dword:00000000
* "ConfigureCount"=dword:00000004
* "CurrentInstrument"="Wine OSS midi"
* "CurrentScheme"="epp"
* "DriverList"=""
* "UseScheme"=dword:00000000
*
* AutoScheme: ?
* CurrentInstrument: name of midiOut device to use when UseScheme is 0. Wine uses an extension
* of the form #n to link to n'th midiOut device of the system
* CurrentScheme: when UseScheme is non null, it's the scheme to use (see below)
* DriverList: ?
* UseScheme: trigger for simple/complex mapping
*
* A scheme is defined (in HKLM) as:
*
* [System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Midi\\Schemes\\<nameScheme>]
* <nameScheme>: one key for each defined scheme (system wide)
* under each one of these <nameScheme> keys, there's:
* [...\\<nameScheme>\\<idxDevice>]
* "Channels"="<bitMask>"
* (the default value of this key also refers to the name of the device).
*
* this defines, for each midiOut device (identified by its index in <idxDevice>), which
* channels have to be mapped onto it. The <bitMask> defines the channels (from 0 to 15)
* will be mapped (mapping occurs for channel <ch> if bit <ch> is set in <bitMask>
*
* Further mapping information can also be defined in:
* [System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Midi\\Ports\\<nameDevice>\\Instruments\\<idx>]
* "Definition"="<.idf file>"
* "FriendlyName"="#for .idx file#"
* "Port"="<idxPort>"
*
* This last part isn't implemented (.idf file support).
*/
WINE_DEFAULT_DEBUG_CHANNEL(msacm);
typedef struct tagMIDIOUTPORT
{
char name[MAXPNAMELEN];
int loaded;
HMIDIOUT hMidi;
unsigned short uDevID;
LPBYTE lpbPatch;
unsigned int aChn[16];
} MIDIOUTPORT;
typedef struct tagMIDIMAPDATA
{
struct tagMIDIMAPDATA* self;
MIDIOUTPORT* ChannelMap[16];
} MIDIMAPDATA;
static MIDIOUTPORT* midiOutPorts;
static unsigned numMidiOutPorts;
static BOOL MIDIMAP_IsBadData(MIDIMAPDATA* mm)
{
if (!IsBadReadPtr(mm, sizeof(MIDIMAPDATA)) && mm->self == mm)
return FALSE;
TRACE("Bad midimap data (%p)\n", mm);
return TRUE;
}
static BOOL MIDIMAP_FindPort(const char* name, unsigned* dev)
{
for (*dev = 0; *dev < numMidiOutPorts; (*dev)++)
{
TRACE("%s\n", midiOutPorts[*dev].name);
if (strcmp(midiOutPorts[*dev].name, name) == 0)
return TRUE;
}
/* try the form #nnn */
if (*name == '#' && isdigit(name[1]))
{
*dev = atoi(name + 1);
if (*dev < numMidiOutPorts)
return TRUE;
}
return FALSE;
}
static BOOL MIDIMAP_LoadSettingsDefault(MIDIMAPDATA* mom, const char* port)
{
unsigned i, dev = 0;
if (port != NULL && !MIDIMAP_FindPort(port, &dev))
{
ERR("Registry glitch: couldn't find midi out (%s)\n", port);
dev = 0;
}
/* this is necessary when no midi out ports are present */
if (dev >= numMidiOutPorts)
return FALSE;
/* sets default */
for (i = 0; i < 16; i++) mom->ChannelMap[i] = &midiOutPorts[dev];
return TRUE;
}
static BOOL MIDIMAP_LoadSettingsScheme(MIDIMAPDATA* mom, const char* scheme)
{
HKEY hSchemesKey, hKey, hPortKey;
unsigned i, idx, dev;
char buffer[256], port[256];
DWORD type, size, mask;
for (i = 0; i < 16; i++) mom->ChannelMap[i] = NULL;
if (RegOpenKeyA(HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Midi\\Schemes",
&hSchemesKey))
{
return FALSE;
}
if (RegOpenKeyA(hSchemesKey, scheme, &hKey))
{
RegCloseKey(hSchemesKey);
return FALSE;
}
for (idx = 0; !RegEnumKeyA(hKey, idx, buffer, sizeof(buffer)); idx++)
{
if (RegOpenKeyA(hKey, buffer, &hPortKey)) continue;
size = sizeof(port);
if (RegQueryValueExA(hPortKey, NULL, 0, &type, port, &size)) continue;
if (!MIDIMAP_FindPort(port, &dev)) continue;
size = sizeof(mask);
if (RegQueryValueExA(hPortKey, "Channels", 0, &type, (void*)&mask, &size))
continue;
for (i = 0; i < 16; i++)
{
if (mask & (1 << i))
{
if (mom->ChannelMap[i])
ERR("Quirks in registry, channel %u is mapped twice\n", i);
mom->ChannelMap[i] = &midiOutPorts[dev];
}
}
}
RegCloseKey(hSchemesKey);
RegCloseKey(hKey);
return TRUE;
}
static BOOL MIDIMAP_LoadSettings(MIDIMAPDATA* mom)
{
HKEY hKey;
BOOL ret;
if (RegOpenKeyA(HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap", &hKey))
{
ret = MIDIMAP_LoadSettingsDefault(mom, NULL);
}
else
{
DWORD type, size, out;
char buffer[256];
ret = 2;
size = sizeof(out);
if (!RegQueryValueExA(hKey, "UseScheme", 0, &type, (void*)&out, &size) && out)
{
size = sizeof(buffer);
if (!RegQueryValueExA(hKey, "CurrentScheme", 0, &type, buffer, &size))
{
if (!(ret = MIDIMAP_LoadSettingsScheme(mom, buffer)))
ret = MIDIMAP_LoadSettingsDefault(mom, NULL);
}
else
{
ERR("Wrong registry: UseScheme is active, but no CurrentScheme found\n");
}
}
if (ret == 2)
{
size = sizeof(buffer);
if (!RegQueryValueExA(hKey, "CurrentInstrument", 0, &type, buffer, &size) && *buffer)
{
ret = MIDIMAP_LoadSettingsDefault(mom, buffer);
}
else
{
ret = MIDIMAP_LoadSettingsDefault(mom, NULL);
}
}
}
RegCloseKey(hKey);
if (ret && TRACE_ON(msacm))
{
unsigned i;
for (i = 0; i < 16; i++)
{
TRACE("chnMap[%2d] => %d\n",
i, mom->ChannelMap[i] ? mom->ChannelMap[i]->uDevID : -1);
}
}
return ret;
}
static DWORD modOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
{
MIDIMAPDATA* mom = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIMAPDATA));
TRACE("(%p %p %08lx)\n", lpdwUser, lpDesc, dwFlags);
if (!mom) return MMSYSERR_NOMEM;
if (MIDIMAP_LoadSettings(mom))
{
*lpdwUser = (DWORD)mom;
mom->self = mom;
return MMSYSERR_NOERROR;
}
HeapFree(GetProcessHeap(), 0, mom);
return MIDIERR_INVALIDSETUP;
}
static DWORD modClose(MIDIMAPDATA* mom)
{
UINT i;
DWORD ret = MMSYSERR_NOERROR;
if (MIDIMAP_IsBadData(mom)) return MMSYSERR_ERROR;
for (i = 0; i < 16; i++)
{
DWORD t;
if (mom->ChannelMap[i] && mom->ChannelMap[i]->loaded > 0)
{
t = midiOutClose(mom->ChannelMap[i]->hMidi);
if (t == MMSYSERR_NOERROR)
{
mom->ChannelMap[i]->loaded = 0;
mom->ChannelMap[i]->hMidi = 0;
}
else if (ret == MMSYSERR_NOERROR)
ret = t;
}
}
if (ret == MMSYSERR_NOERROR)
HeapFree(GetProcessHeap(), 0, mom);
return ret;
}
static DWORD modLongData(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
{
WORD chn;
DWORD ret = MMSYSERR_NOERROR;
MIDIHDR mh;
if (MIDIMAP_IsBadData(mom))
return MMSYSERR_ERROR;
mh = *lpMidiHdr;
for (chn = 0; chn < 16; chn++)
{
if (mom->ChannelMap[chn] && mom->ChannelMap[chn]->loaded > 0)
{
mh.dwFlags = 0;
midiOutPrepareHeader(mom->ChannelMap[chn]->hMidi, &mh, sizeof(mh));
ret = midiOutLongMsg(mom->ChannelMap[chn]->hMidi, &mh, sizeof(mh));
midiOutUnprepareHeader(mom->ChannelMap[chn]->hMidi, &mh, sizeof(mh));
if (ret != MMSYSERR_NOERROR) break;
}
}
return ret;
}
static DWORD modData(MIDIMAPDATA* mom, DWORD dwParam)
{
BYTE lb = LOBYTE(LOWORD(dwParam));
WORD chn = lb & 0x0F;
DWORD ret = MMSYSERR_NOERROR;
if (MIDIMAP_IsBadData(mom))
return MMSYSERR_ERROR;
if (!mom->ChannelMap[chn]) return MMSYSERR_NOERROR;
switch (lb & 0xF0)
{
case 0x80:
case 0x90:
case 0xA0:
case 0xB0:
case 0xC0:
case 0xD0:
case 0xE0:
if (mom->ChannelMap[chn]->loaded == 0)
{
if (midiOutOpen(&mom->ChannelMap[chn]->hMidi, mom->ChannelMap[chn]->uDevID,
0L, 0L, CALLBACK_NULL) == MMSYSERR_NOERROR)
mom->ChannelMap[chn]->loaded = 1;
else
mom->ChannelMap[chn]->loaded = -1;
/* FIXME: should load here the IDF midi data... and allow channel and
* patch mappings
*/
}
if (mom->ChannelMap[chn]->loaded > 0)
{
/* change channel */
dwParam &= ~0x0F;
dwParam |= mom->ChannelMap[chn]->aChn[chn];
if ((LOBYTE(LOWORD(dwParam)) & 0xF0) == 0xC0 /* program change */ &&
mom->ChannelMap[chn]->lpbPatch)
{
BYTE patch = HIBYTE(LOWORD(dwParam));
/* change patch */
dwParam &= ~0x0000FF00;
dwParam |= mom->ChannelMap[chn]->lpbPatch[patch];
}
ret = midiOutShortMsg(mom->ChannelMap[chn]->hMidi, dwParam);
}
break;
case 0xF0:
for (chn = 0; chn < 16; chn++)
{
if (mom->ChannelMap[chn]->loaded > 0)
ret = midiOutShortMsg(mom->ChannelMap[chn]->hMidi, dwParam);
}
break;
default:
FIXME("ooch %lu\n", dwParam);
}
return ret;
}
static DWORD modPrepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
{
if (MIDIMAP_IsBadData(mom)) return MMSYSERR_ERROR;
if (lpMidiHdr->dwFlags & (MHDR_ISSTRM|MHDR_PREPARED))
return MMSYSERR_INVALPARAM;
lpMidiHdr->dwFlags |= MHDR_PREPARED;
return MMSYSERR_NOERROR;
}
static DWORD modUnprepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
{
if (MIDIMAP_IsBadData(mom)) return MMSYSERR_ERROR;
if ((lpMidiHdr->dwFlags & MHDR_ISSTRM) || !(lpMidiHdr->dwFlags & MHDR_PREPARED))
return MMSYSERR_INVALPARAM;
lpMidiHdr->dwFlags &= ~MHDR_PREPARED;
return MMSYSERR_NOERROR;
}
static DWORD modGetDevCaps(UINT wDevID, MIDIMAPDATA* mom, LPMIDIOUTCAPSA lpMidiCaps, DWORD size)
{
lpMidiCaps->wMid = 0x00FF;
lpMidiCaps->wPid = 0x0001;
lpMidiCaps->vDriverVersion = 0x0100;
strcpy(lpMidiCaps->szPname, "Wine midi out mapper");
lpMidiCaps->wTechnology = MOD_MAPPER;
lpMidiCaps->wVoices = 0;
lpMidiCaps->wNotes = 0;
lpMidiCaps->wChannelMask = 0xFFFF;
lpMidiCaps->dwSupport = 0L;
return MMSYSERR_NOERROR;
}
static DWORD modReset(MIDIMAPDATA* mom)
{
WORD chn;
DWORD ret = MMSYSERR_NOERROR;
if (MIDIMAP_IsBadData(mom))
return MMSYSERR_ERROR;
for (chn = 0; chn < 16; chn++)
{
if (mom->ChannelMap[chn] && mom->ChannelMap[chn]->loaded > 0)
{
ret = midiOutReset(mom->ChannelMap[chn]->hMidi);
if (ret != MMSYSERR_NOERROR) break;
}
}
return ret;
}
/**************************************************************************
* modMessage (MIDIMAP.@)
*/
DWORD WINAPI MIDIMAP_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
DWORD dwParam1, DWORD dwParam2)
{
TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
wDevID, wMsg, dwUser, dwParam1, dwParam2);
switch (wMsg)
{
case DRVM_INIT:
case DRVM_EXIT:
case DRVM_ENABLE:
case DRVM_DISABLE:
/* FIXME: Pretend this is supported */
return 0;
case MODM_OPEN: return modOpen ((LPDWORD)dwUser, (LPMIDIOPENDESC)dwParam1,dwParam2);
case MODM_CLOSE: return modClose ((MIDIMAPDATA*)dwUser);
case MODM_DATA: return modData ((MIDIMAPDATA*)dwUser, dwParam1);
case MODM_LONGDATA: return modLongData ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2);
case MODM_PREPARE: return modPrepare ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2);
case MODM_UNPREPARE: return modUnprepare ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2);
case MODM_RESET: return modReset ((MIDIMAPDATA*)dwUser);
case MODM_GETDEVCAPS: return modGetDevCaps (wDevID, (MIDIMAPDATA*)dwUser, (LPMIDIOUTCAPSA)dwParam1,dwParam2);
case MODM_GETNUMDEVS: return 1;
case MODM_GETVOLUME: return MMSYSERR_NOTSUPPORTED;
case MODM_SETVOLUME: return MMSYSERR_NOTSUPPORTED;
default:
FIXME("unknown message %d!\n", wMsg);
}
return MMSYSERR_NOTSUPPORTED;
}
/*======================================================================*
* Driver part *
*======================================================================*/
/**************************************************************************
* MIDIMAP_drvOpen [internal]
*/
static DWORD MIDIMAP_drvOpen(LPSTR str)
{
MIDIOUTCAPSA moc;
unsigned dev, i;
if (midiOutPorts)
return 0;
numMidiOutPorts = midiOutGetNumDevs();
midiOutPorts = HeapAlloc(GetProcessHeap(), 0,
numMidiOutPorts * sizeof(MIDIOUTPORT));
for (dev = 0; dev < numMidiOutPorts; dev++)
{
if (midiOutGetDevCapsA(dev, &moc, sizeof(moc)) == 0L)
{
strcpy(midiOutPorts[dev].name, moc.szPname);
midiOutPorts[dev].loaded = 0;
midiOutPorts[dev].hMidi = 0;
midiOutPorts[dev].uDevID = dev;
midiOutPorts[dev].lpbPatch = NULL;
for (i = 0; i < 16; i++)
midiOutPorts[dev].aChn[i] = i;
}
else
{
midiOutPorts[dev].loaded = -1;
}
}
return 1;
}
/**************************************************************************
* MIDIMAP_drvClose [internal]
*/
static DWORD MIDIMAP_drvClose(DWORD dwDevID)
{
if (midiOutPorts)
{
HeapFree(GetProcessHeap(), 0, midiOutPorts);
midiOutPorts = NULL;
return 1;
}
return 0;
}
/**************************************************************************
* DriverProc (MIDIMAP.@)
*/
LONG CALLBACK MIDIMAP_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2)
{
/* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */
/* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
switch (wMsg)
{
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return MIDIMAP_drvOpen((LPSTR)dwParam1);
case DRV_CLOSE: return MIDIMAP_drvClose(dwDevID);
case DRV_ENABLE: return 1;
case DRV_DISABLE: return 1;
case DRV_QUERYCONFIGURE: return 1;
case DRV_CONFIGURE: MessageBoxA(0, "MIDIMAP MultiMedia Driver !", "OSS Driver", MB_OK); return 1;
case DRV_INSTALL: return DRVCNF_RESTART;
case DRV_REMOVE: return DRVCNF_RESTART;
default:
return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
}
}

View file

@ -0,0 +1,39 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "ReactOS/WINE MIDI Mapper\0"
VALUE "FileVersion", RES_STR_FILE_VERSION
VALUE "InternalName", "midimap\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "midimap.drv\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View file

@ -0,0 +1,2 @@
@ stdcall DriverProc(long long long long long) MIDIMAP_DriverProc
@ stdcall modMessage(long long long long long) MIDIMAP_modMessage

View file

@ -0,0 +1,9 @@
*.a
*.d
*.o
*.dll
*.coff
*.sym
*.map
*.tmp
temp.exp

View file

@ -0,0 +1,13 @@
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = msacm.drv
IMPORTS = msacm32 winmm user32 kernel32
C_SRCS = \
wavemap.c
@MAKE_DLL_RULES@
### Dependencies:

View file

@ -0,0 +1,21 @@
# $Id: Makefile.ros,v 1.1 2004/03/10 15:22:45 silverblade Exp $
TARGET_NAME = wavemap
TARGET_OBJECTS = wavemap.o
TARGET_CFLAGS = -D__REACTOS__
TARGET_SDKLIBS = winmm.a libwine.a ws2_32.a wine_uuid.a ntdll.a msacm32.a
TARGET_BASE = 0x77300000
TARGET_RC_SRCS = wavemap.rc
TARGET_RC_BINSRC = wavemap.rc
TARGET_RC_BINARIES =
default: all
DEP_OBJECTS = $(TARGET_OBJECTS)
include $(TOOLS_PATH)/depend.mk

View file

@ -0,0 +1,21 @@
# $Id: Makefile.ros-template,v 1.1 2004/03/10 15:22:45 silverblade Exp $
TARGET_NAME = midimap
TARGET_OBJECTS = @C_SRCS@
TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__
TARGET_SDKLIBS = @IMPORTS@ winmm.a libwine.a wine_uuid.a ntdll.a
TARGET_BASE = 0x76160000
TARGET_RC_SRCS = @RC_SRCS@
TARGET_RC_BINSRC = @RC_BINSRC@
TARGET_RC_BINARIES = @RC_BINARIES@
default: all
DEP_OBJECTS = $(TARGET_OBJECTS)
include $(TOOLS_PATH)/depend.mk

View file

@ -0,0 +1,9 @@
# $Id: makefile,v 1.1 2004/03/10 15:22:45 silverblade Exp $
PATH_TO_TOP = ../../..
TARGET_TYPE = winedll
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk

View file

@ -0,0 +1,3 @@
@ stdcall DriverProc(long long long long long) WAVEMAP_DriverProc
@ stdcall widMessage(long long long long long) WAVEMAP_widMessage
@ stdcall wodMessage(long long long long long) WAVEMAP_wodMessage

View file

@ -0,0 +1,975 @@
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/*
* Wine Wave mapper driver
*
* Copyright 1999,2001 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* TODOs
* + better protection against evilish dwUser parameters
* + use asynchronous ACM conversion
* + don't use callback functions when none is required in open
* + the buffer sizes may not be accurate, so there may be some
* remaining bytes in src and dst buffers after ACM conversions...
* those should be taken care of...
*/
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmddk.h"
#include "mmreg.h"
#include "msacm.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msacm);
typedef struct tagWAVEMAPDATA {
struct tagWAVEMAPDATA* self;
union {
struct {
HWAVEOUT hOuterWave;
HWAVEOUT hInnerWave;
} out;
struct {
HWAVEIN hOuterWave;
HWAVEIN hInnerWave;
} in;
} u;
HACMSTREAM hAcmStream;
/* needed data to filter callbacks. Only needed when hAcmStream is not 0 */
DWORD dwCallback;
DWORD dwClientInstance;
DWORD dwFlags;
/* ratio to compute position from a PCM playback to any format */
DWORD avgSpeedOuter;
DWORD avgSpeedInner;
} WAVEMAPDATA;
static BOOL WAVEMAP_IsData(WAVEMAPDATA* wm)
{
return (!IsBadReadPtr(wm, sizeof(WAVEMAPDATA)) && wm->self == wm);
}
/*======================================================================*
* WAVE OUT part *
*======================================================================*/
static void CALLBACK wodCallback(HWAVEOUT hWave, UINT uMsg, DWORD dwInstance,
DWORD dwParam1, DWORD dwParam2)
{
WAVEMAPDATA* wom = (WAVEMAPDATA*)dwInstance;
TRACE("(%p %u %ld %lx %lx);\n", hWave, uMsg, dwInstance, dwParam1, dwParam2);
if (!WAVEMAP_IsData(wom)) {
ERR("Bad data\n");
return;
}
if (hWave != wom->u.out.hInnerWave && uMsg != WOM_OPEN)
ERR("Shouldn't happen (%p %p)\n", hWave, wom->u.out.hInnerWave);
switch (uMsg) {
case WOM_OPEN:
case WOM_CLOSE:
/* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
break;
case WOM_DONE:
if (wom->hAcmStream) {
LPWAVEHDR lpWaveHdrDst = (LPWAVEHDR)dwParam1;
PACMSTREAMHEADER ash = (PACMSTREAMHEADER)((LPSTR)lpWaveHdrDst - sizeof(ACMSTREAMHEADER));
LPWAVEHDR lpWaveHdrSrc = (LPWAVEHDR)ash->dwUser;
lpWaveHdrSrc->dwFlags &= ~WHDR_INQUEUE;
lpWaveHdrSrc->dwFlags |= WHDR_DONE;
dwParam1 = (DWORD)lpWaveHdrSrc;
}
break;
default:
ERR("Unknown msg %u\n", uMsg);
}
DriverCallback(wom->dwCallback, HIWORD(wom->dwFlags), (HDRVR)wom->u.out.hOuterWave,
uMsg, wom->dwClientInstance, dwParam1, dwParam2);
}
/******************************************************************
* wodOpenHelper
*
*
*/
static DWORD wodOpenHelper(WAVEMAPDATA* wom, UINT idx,
LPWAVEOPENDESC lpDesc, LPWAVEFORMATEX lpwfx,
DWORD dwFlags)
{
DWORD ret;
/* destination is always PCM, so the formulas below apply */
lpwfx->nBlockAlign = (lpwfx->nChannels * lpwfx->wBitsPerSample) / 8;
lpwfx->nAvgBytesPerSec = lpwfx->nSamplesPerSec * lpwfx->nBlockAlign;
if (dwFlags & WAVE_FORMAT_QUERY) {
ret = acmStreamOpen(NULL, 0, lpDesc->lpFormat, lpwfx, NULL, 0L, 0L, ACM_STREAMOPENF_QUERY);
} else {
ret = acmStreamOpen(&wom->hAcmStream, 0, lpDesc->lpFormat, lpwfx, NULL, 0L, 0L, 0L);
}
if (ret == MMSYSERR_NOERROR) {
ret = waveOutOpen(&wom->u.out.hInnerWave, idx, lpwfx, (DWORD)wodCallback,
(DWORD)wom, (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION);
if (ret != MMSYSERR_NOERROR && !(dwFlags & WAVE_FORMAT_QUERY)) {
acmStreamClose(wom->hAcmStream, 0);
wom->hAcmStream = 0;
}
}
return ret;
}
static DWORD wodOpen(LPDWORD lpdwUser, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
{
UINT ndlo, ndhi;
UINT i;
WAVEMAPDATA* wom = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEMAPDATA));
TRACE("(%p %p %08lx)\n", lpdwUser, lpDesc, dwFlags);
if (!wom)
return MMSYSERR_NOMEM;
ndhi = waveOutGetNumDevs();
if (dwFlags & WAVE_MAPPED) {
if (lpDesc->uMappedDeviceID >= ndhi) return MMSYSERR_INVALPARAM;
ndlo = lpDesc->uMappedDeviceID;
ndhi = ndlo + 1;
dwFlags &= ~WAVE_MAPPED;
} else {
ndlo = 0;
}
wom->self = wom;
wom->dwCallback = lpDesc->dwCallback;
wom->dwFlags = dwFlags;
wom->dwClientInstance = lpDesc->dwInstance;
wom->u.out.hOuterWave = (HWAVEOUT)lpDesc->hWave;
wom->avgSpeedOuter = wom->avgSpeedInner = lpDesc->lpFormat->nAvgBytesPerSec;
for (i = ndlo; i < ndhi; i++) {
/* if no ACM stuff is involved, no need to handle callbacks at this
* level, this will be done transparently
*/
if (waveOutOpen(&wom->u.out.hInnerWave, i, lpDesc->lpFormat, (DWORD)wodCallback,
(DWORD)wom, (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT) == MMSYSERR_NOERROR) {
wom->hAcmStream = 0;
goto found;
}
}
if ((dwFlags & WAVE_FORMAT_DIRECT) == 0) {
WAVEFORMATEX wfx;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.cbSize = 0; /* normally, this field is not used for PCM format, just in case */
/* try some ACM stuff */
#define TRY(sps,bps) wfx.nSamplesPerSec = (sps); wfx.wBitsPerSample = (bps); \
switch (wodOpenHelper(wom, i, lpDesc, &wfx, dwFlags | WAVE_FORMAT_DIRECT)) { \
case MMSYSERR_NOERROR: wom->avgSpeedInner = wfx.nAvgBytesPerSec; goto found; \
case WAVERR_BADFORMAT: break; \
default: goto error; \
}
/* Our resampling algorithm is quite primitive so first try
* to just change the bit depth and number of channels
*/
for (i = ndlo; i < ndhi; i++) {
wfx.nSamplesPerSec=lpDesc->lpFormat->nSamplesPerSec;
wfx.nChannels = lpDesc->lpFormat->nChannels;
TRY(wfx.nSamplesPerSec, 16);
TRY(wfx.nSamplesPerSec, 8);
wfx.nChannels ^= 3;
TRY(wfx.nSamplesPerSec, 16);
TRY(wfx.nSamplesPerSec, 8);
}
for (i = ndlo; i < ndhi; i++) {
/* first try with same stereo/mono option as source */
wfx.nChannels = lpDesc->lpFormat->nChannels;
TRY(96000, 16);
TRY(48000, 16);
TRY(44100, 16);
TRY(22050, 16);
TRY(11025, 16);
/* 2^3 => 1, 1^3 => 2, so if stereo, try mono (and the other way around) */
wfx.nChannels ^= 3;
TRY(96000, 16);
TRY(48000, 16);
TRY(44100, 16);
TRY(22050, 16);
TRY(11025, 16);
/* first try with same stereo/mono option as source */
wfx.nChannels = lpDesc->lpFormat->nChannels;
TRY(96000, 8);
TRY(48000, 8);
TRY(44100, 8);
TRY(22050, 8);
TRY(11025, 8);
/* 2^3 => 1, 1^3 => 2, so if stereo, try mono (and the other way around) */
wfx.nChannels ^= 3;
TRY(96000, 8);
TRY(48000, 8);
TRY(44100, 8);
TRY(22050, 8);
TRY(11025, 8);
}
#undef TRY
}
HeapFree(GetProcessHeap(), 0, wom);
return WAVERR_BADFORMAT;
found:
if (dwFlags & WAVE_FORMAT_QUERY) {
*lpdwUser = 0L;
HeapFree(GetProcessHeap(), 0, wom);
} else {
*lpdwUser = (DWORD)wom;
}
return MMSYSERR_NOERROR;
error:
HeapFree(GetProcessHeap(), 0, wom);
return MMSYSERR_ERROR;
}
static DWORD wodClose(WAVEMAPDATA* wom)
{
DWORD ret = waveOutClose(wom->u.out.hInnerWave);
if (ret == MMSYSERR_NOERROR) {
if (wom->hAcmStream) {
ret = acmStreamClose(wom->hAcmStream, 0);
}
if (ret == MMSYSERR_NOERROR) {
HeapFree(GetProcessHeap(), 0, wom);
}
}
return ret;
}
static DWORD wodWrite(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2)
{
PACMSTREAMHEADER ash;
LPWAVEHDR lpWaveHdrDst;
if (!wom->hAcmStream) {
return waveOutWrite(wom->u.out.hInnerWave, lpWaveHdrSrc, dwParam2);
}
lpWaveHdrSrc->dwFlags |= WHDR_INQUEUE;
ash = (PACMSTREAMHEADER)lpWaveHdrSrc->reserved;
/* acmStreamConvert will actually check that the new size is less than initial size */
ash->cbSrcLength = lpWaveHdrSrc->dwBufferLength;
if (acmStreamConvert(wom->hAcmStream, ash, 0L) != MMSYSERR_NOERROR)
return MMSYSERR_ERROR;
lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
if (ash->cbSrcLength > ash->cbSrcLengthUsed)
FIXME("Not all src buffer has been written, expect bogus sound\n");
else if (ash->cbSrcLength < ash->cbSrcLengthUsed)
ERR("CoDec has read more data than it is allowed to\n");
if (ash->cbDstLengthUsed == 0)
{
/* something went wrong in decoding */
FIXME("Got 0 length\n");
return MMSYSERR_ERROR;
}
lpWaveHdrDst->dwBufferLength = ash->cbDstLengthUsed;
return waveOutWrite(wom->u.out.hInnerWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst));
}
static DWORD wodPrepare(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2)
{
PACMSTREAMHEADER ash;
DWORD size;
DWORD dwRet;
LPWAVEHDR lpWaveHdrDst;
if (!wom->hAcmStream) {
return waveOutPrepareHeader(wom->u.out.hInnerWave, lpWaveHdrSrc, dwParam2);
}
if (acmStreamSize(wom->hAcmStream, lpWaveHdrSrc->dwBufferLength, &size, ACM_STREAMSIZEF_SOURCE) != MMSYSERR_NOERROR)
return MMSYSERR_ERROR;
ash = HeapAlloc(GetProcessHeap(), 0, sizeof(ACMSTREAMHEADER) + sizeof(WAVEHDR) + size);
if (ash == NULL)
return MMSYSERR_NOMEM;
ash->cbStruct = sizeof(*ash);
ash->fdwStatus = 0L;
ash->dwUser = (DWORD)lpWaveHdrSrc;
ash->pbSrc = lpWaveHdrSrc->lpData;
ash->cbSrcLength = lpWaveHdrSrc->dwBufferLength;
/* ash->cbSrcLengthUsed */
ash->dwSrcUser = lpWaveHdrSrc->dwUser; /* FIXME ? */
ash->pbDst = (LPSTR)ash + sizeof(ACMSTREAMHEADER) + sizeof(WAVEHDR);
ash->cbDstLength = size;
/* ash->cbDstLengthUsed */
ash->dwDstUser = 0; /* FIXME ? */
dwRet = acmStreamPrepareHeader(wom->hAcmStream, ash, 0L);
if (dwRet != MMSYSERR_NOERROR)
goto errCleanUp;
lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
lpWaveHdrDst->lpData = ash->pbDst;
lpWaveHdrDst->dwBufferLength = size; /* conversion is not done yet */
lpWaveHdrDst->dwFlags = 0;
lpWaveHdrDst->dwLoops = 0;
dwRet = waveOutPrepareHeader(wom->u.out.hInnerWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst));
if (dwRet != MMSYSERR_NOERROR)
goto errCleanUp;
lpWaveHdrSrc->reserved = (DWORD)ash;
lpWaveHdrSrc->dwFlags = WHDR_PREPARED;
TRACE("=> (0)\n");
return MMSYSERR_NOERROR;
errCleanUp:
TRACE("=> (%ld)\n", dwRet);
HeapFree(GetProcessHeap(), 0, ash);
return dwRet;
}
static DWORD wodUnprepare(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2)
{
PACMSTREAMHEADER ash;
LPWAVEHDR lpWaveHdrDst;
DWORD dwRet1, dwRet2;
if (!wom->hAcmStream) {
return waveOutUnprepareHeader(wom->u.out.hInnerWave, lpWaveHdrSrc, dwParam2);
}
ash = (PACMSTREAMHEADER)lpWaveHdrSrc->reserved;
dwRet1 = acmStreamUnprepareHeader(wom->hAcmStream, ash, 0L);
lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
dwRet2 = waveOutUnprepareHeader(wom->u.out.hInnerWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst));
HeapFree(GetProcessHeap(), 0, ash);
lpWaveHdrSrc->dwFlags &= ~WHDR_PREPARED;
return (dwRet1 == MMSYSERR_NOERROR) ? dwRet2 : dwRet1;
}
static DWORD wodGetPosition(WAVEMAPDATA* wom, LPMMTIME lpTime, DWORD dwParam2)
{
DWORD val = waveOutGetPosition(wom->u.out.hInnerWave, lpTime, dwParam2);
if (lpTime->wType == TIME_BYTES)
lpTime->u.cb = MulDiv(lpTime->u.cb, wom->avgSpeedOuter, wom->avgSpeedInner);
/* other time types don't require conversion */
return val;
}
static DWORD wodGetDevCaps(UINT wDevID, WAVEMAPDATA* wom, LPWAVEOUTCAPSA lpWaveCaps, DWORD dwParam2)
{
/* if opened low driver, forward message */
if (WAVEMAP_IsData(wom))
return waveOutGetDevCapsA((UINT)wom->u.out.hInnerWave, lpWaveCaps, dwParam2);
/* otherwise, return caps of mapper itself */
if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) {
lpWaveCaps->wMid = 0x00FF;
lpWaveCaps->wPid = 0x0001;
lpWaveCaps->vDriverVersion = 0x0100;
strcpy(lpWaveCaps->szPname, "Wine wave out mapper");
lpWaveCaps->dwFormats =
WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16 |
WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 | WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16;
lpWaveCaps->wChannels = 2;
lpWaveCaps->dwSupport = WAVECAPS_VOLUME | WAVECAPS_LRVOLUME;
return MMSYSERR_NOERROR;
}
ERR("This shouldn't happen\n");
return MMSYSERR_ERROR;
}
static DWORD wodGetVolume(UINT wDevID, WAVEMAPDATA* wom, LPDWORD lpVol)
{
if (WAVEMAP_IsData(wom))
return waveOutGetVolume(wom->u.out.hInnerWave, lpVol);
return MMSYSERR_NOERROR;
}
static DWORD wodSetVolume(UINT wDevID, WAVEMAPDATA* wom, DWORD vol)
{
if (WAVEMAP_IsData(wom))
return waveOutSetVolume(wom->u.out.hInnerWave, vol);
return MMSYSERR_NOERROR;
}
static DWORD wodPause(WAVEMAPDATA* wom)
{
return waveOutPause(wom->u.out.hInnerWave);
}
static DWORD wodRestart(WAVEMAPDATA* wom)
{
return waveOutRestart(wom->u.out.hInnerWave);
}
static DWORD wodReset(WAVEMAPDATA* wom)
{
return waveOutReset(wom->u.out.hInnerWave);
}
static DWORD wodBreakLoop(WAVEMAPDATA* wom)
{
return waveOutBreakLoop(wom->u.out.hInnerWave);
}
static DWORD wodMapperStatus(WAVEMAPDATA* wom, DWORD flags, LPVOID ptr)
{
UINT id;
DWORD ret = MMSYSERR_NOTSUPPORTED;
switch (flags) {
case WAVEOUT_MAPPER_STATUS_DEVICE:
ret = waveOutGetID(wom->u.out.hInnerWave, &id);
*(LPDWORD)ptr = id;
break;
case WAVEOUT_MAPPER_STATUS_MAPPED:
FIXME("Unsupported flag=%ld\n", flags);
*(LPDWORD)ptr = 0; /* FIXME ?? */
break;
case WAVEOUT_MAPPER_STATUS_FORMAT:
FIXME("Unsupported flag=%ld\n", flags);
/* ptr points to a WAVEFORMATEX struct - before or after streaming ? */
*(LPDWORD)ptr = 0;
break;
default:
FIXME("Unsupported flag=%ld\n", flags);
*(LPDWORD)ptr = 0;
break;
}
return ret;
}
/**************************************************************************
* wodMessage (MSACM.@)
*/
DWORD WINAPI WAVEMAP_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
DWORD dwParam1, DWORD dwParam2)
{
TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
wDevID, wMsg, dwUser, dwParam1, dwParam2);
switch (wMsg) {
case DRVM_INIT:
case DRVM_EXIT:
case DRVM_ENABLE:
case DRVM_DISABLE:
/* FIXME: Pretend this is supported */
return 0;
case WODM_OPEN: return wodOpen ((LPDWORD)dwUser, (LPWAVEOPENDESC)dwParam1,dwParam2);
case WODM_CLOSE: return wodClose ((WAVEMAPDATA*)dwUser);
case WODM_WRITE: return wodWrite ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2);
case WODM_PAUSE: return wodPause ((WAVEMAPDATA*)dwUser);
case WODM_GETPOS: return wodGetPosition ((WAVEMAPDATA*)dwUser, (LPMMTIME)dwParam1, dwParam2);
case WODM_BREAKLOOP: return wodBreakLoop ((WAVEMAPDATA*)dwUser);
case WODM_PREPARE: return wodPrepare ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2);
case WODM_UNPREPARE: return wodUnprepare ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2);
case WODM_GETDEVCAPS: return wodGetDevCaps (wDevID, (WAVEMAPDATA*)dwUser, (LPWAVEOUTCAPSA)dwParam1,dwParam2);
case WODM_GETNUMDEVS: return 1;
case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED;
case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED;
case WODM_GETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
case WODM_SETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
case WODM_GETVOLUME: return wodGetVolume (wDevID, (WAVEMAPDATA*)dwUser, (LPDWORD)dwParam1);
case WODM_SETVOLUME: return wodSetVolume (wDevID, (WAVEMAPDATA*)dwUser, dwParam1);
case WODM_RESTART: return wodRestart ((WAVEMAPDATA*)dwUser);
case WODM_RESET: return wodReset ((WAVEMAPDATA*)dwUser);
case WODM_MAPPER_STATUS: return wodMapperStatus ((WAVEMAPDATA*)dwUser, dwParam1, (LPVOID)dwParam2);
default:
FIXME("unknown message %d!\n", wMsg);
}
return MMSYSERR_NOTSUPPORTED;
}
/*======================================================================*
* WAVE IN part *
*======================================================================*/
static void CALLBACK widCallback(HWAVEIN hWave, UINT uMsg, DWORD dwInstance,
DWORD dwParam1, DWORD dwParam2)
{
WAVEMAPDATA* wim = (WAVEMAPDATA*)dwInstance;
TRACE("(%p %u %ld %lx %lx);\n", hWave, uMsg, dwInstance, dwParam1, dwParam2);
if (!WAVEMAP_IsData(wim)) {
ERR("Bad data\n");
return;
}
if (hWave != wim->u.in.hInnerWave && uMsg != WIM_OPEN)
ERR("Shouldn't happen (%p %p)\n", hWave, wim->u.in.hInnerWave);
switch (uMsg) {
case WIM_OPEN:
case WIM_CLOSE:
/* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
break;
case WIM_DATA:
if (wim->hAcmStream) {
LPWAVEHDR lpWaveHdrSrc = (LPWAVEHDR)dwParam1;
PACMSTREAMHEADER ash = (PACMSTREAMHEADER)((LPSTR)lpWaveHdrSrc - sizeof(ACMSTREAMHEADER));
LPWAVEHDR lpWaveHdrDst = (LPWAVEHDR)ash->dwUser;
/* convert data just gotten from waveIn into requested format */
if (acmStreamConvert(wim->hAcmStream, ash, 0L) != MMSYSERR_NOERROR) {
ERR("ACM conversion failed\n");
return;
} else {
TRACE("Converted %ld bytes into %ld\n", ash->cbSrcLengthUsed, ash->cbDstLengthUsed);
}
/* and setup the wavehdr to return accordingly */
lpWaveHdrDst->dwFlags &= ~WHDR_INQUEUE;
lpWaveHdrDst->dwFlags |= WHDR_DONE;
lpWaveHdrDst->dwBytesRecorded = ash->cbDstLengthUsed;
dwParam1 = (DWORD)lpWaveHdrDst;
}
break;
default:
ERR("Unknown msg %u\n", uMsg);
}
DriverCallback(wim->dwCallback, HIWORD(wim->dwFlags), (HDRVR)wim->u.in.hOuterWave,
uMsg, wim->dwClientInstance, dwParam1, dwParam2);
}
static DWORD widOpenHelper(WAVEMAPDATA* wim, UINT idx,
LPWAVEOPENDESC lpDesc, LPWAVEFORMATEX lpwfx,
DWORD dwFlags)
{
DWORD ret;
/* source is always PCM, so the formulas below apply */
lpwfx->nBlockAlign = (lpwfx->nChannels * lpwfx->wBitsPerSample) / 8;
lpwfx->nAvgBytesPerSec = lpwfx->nSamplesPerSec * lpwfx->nBlockAlign;
if (dwFlags & WAVE_FORMAT_QUERY) {
ret = acmStreamOpen(NULL, 0, lpwfx, lpDesc->lpFormat, NULL, 0L, 0L, ACM_STREAMOPENF_QUERY);
} else {
ret = acmStreamOpen(&wim->hAcmStream, 0, lpwfx, lpDesc->lpFormat, NULL, 0L, 0L, 0L);
}
if (ret == MMSYSERR_NOERROR) {
ret = waveInOpen(&wim->u.in.hInnerWave, idx, lpwfx, (DWORD)widCallback,
(DWORD)wim, (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION);
if (ret != MMSYSERR_NOERROR && !(dwFlags & WAVE_FORMAT_QUERY)) {
acmStreamClose(wim->hAcmStream, 0);
wim->hAcmStream = 0;
}
}
return ret;
}
static DWORD widOpen(LPDWORD lpdwUser, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
{
UINT ndlo, ndhi;
UINT i;
WAVEMAPDATA* wim = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEMAPDATA));
TRACE("(%p %p %08lx)\n", lpdwUser, lpDesc, dwFlags);
if (!wim)
return MMSYSERR_NOMEM;
wim->self = wim;
wim->dwCallback = lpDesc->dwCallback;
wim->dwFlags = dwFlags;
wim->dwClientInstance = lpDesc->dwInstance;
wim->u.in.hOuterWave = (HWAVEIN)lpDesc->hWave;
ndhi = waveInGetNumDevs();
if (dwFlags & WAVE_MAPPED) {
if (lpDesc->uMappedDeviceID >= ndhi) return MMSYSERR_INVALPARAM;
ndlo = lpDesc->uMappedDeviceID;
ndhi = ndlo + 1;
dwFlags &= ~WAVE_MAPPED;
} else {
ndlo = 0;
}
wim->avgSpeedOuter = wim->avgSpeedInner = lpDesc->lpFormat->nAvgBytesPerSec;
for (i = ndlo; i < ndhi; i++) {
if (waveInOpen(&wim->u.in.hInnerWave, i, lpDesc->lpFormat, (DWORD)widCallback,
(DWORD)wim, (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT) == MMSYSERR_NOERROR) {
wim->hAcmStream = 0;
goto found;
}
}
if ((dwFlags & WAVE_FORMAT_DIRECT) == 0)
{
WAVEFORMATEX wfx;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.cbSize = 0; /* normally, this field is not used for PCM format, just in case */
/* try some ACM stuff */
#define TRY(sps,bps) wfx.nSamplesPerSec = (sps); wfx.wBitsPerSample = (bps); \
switch (widOpenHelper(wim, i, lpDesc, &wfx, dwFlags | WAVE_FORMAT_DIRECT)) { \
case MMSYSERR_NOERROR: wim->avgSpeedInner = wfx.nAvgBytesPerSec; goto found; \
case WAVERR_BADFORMAT: break; \
default: goto error; \
}
for (i = ndlo; i < ndhi; i++) {
wfx.nSamplesPerSec=lpDesc->lpFormat->nSamplesPerSec;
/* first try with same stereo/mono option as source */
wfx.nChannels = lpDesc->lpFormat->nChannels;
TRY(wfx.nSamplesPerSec, 16);
TRY(wfx.nSamplesPerSec, 8);
wfx.nChannels ^= 3;
TRY(wfx.nSamplesPerSec, 16);
TRY(wfx.nSamplesPerSec, 8);
}
for (i = ndlo; i < ndhi; i++) {
wfx.nSamplesPerSec=lpDesc->lpFormat->nSamplesPerSec;
/* first try with same stereo/mono option as source */
wfx.nChannels = lpDesc->lpFormat->nChannels;
TRY(96000, 16);
TRY(48000, 16);
TRY(44100, 16);
TRY(22050, 16);
TRY(11025, 16);
/* 2^3 => 1, 1^3 => 2, so if stereo, try mono (and the other way around) */
wfx.nChannels ^= 3;
TRY(96000, 16);
TRY(48000, 16);
TRY(44100, 16);
TRY(22050, 16);
TRY(11025, 16);
/* first try with same stereo/mono option as source */
wfx.nChannels = lpDesc->lpFormat->nChannels;
TRY(96000, 8);
TRY(48000, 8);
TRY(44100, 8);
TRY(22050, 8);
TRY(11025, 8);
/* 2^3 => 1, 1^3 => 2, so if stereo, try mono (and the other way around) */
wfx.nChannels ^= 3;
TRY(96000, 8);
TRY(48000, 8);
TRY(44100, 8);
TRY(22050, 8);
TRY(11025, 8);
}
#undef TRY
}
HeapFree(GetProcessHeap(), 0, wim);
return WAVERR_BADFORMAT;
found:
if (dwFlags & WAVE_FORMAT_QUERY) {
*lpdwUser = 0L;
HeapFree(GetProcessHeap(), 0, wim);
} else {
*lpdwUser = (DWORD)wim;
}
TRACE("Ok (stream=%08lx)\n", (DWORD)wim->hAcmStream);
return MMSYSERR_NOERROR;
error:
HeapFree(GetProcessHeap(), 0, wim);
return MMSYSERR_ERROR;
}
static DWORD widClose(WAVEMAPDATA* wim)
{
DWORD ret = waveInClose(wim->u.in.hInnerWave);
if (ret == MMSYSERR_NOERROR) {
if (wim->hAcmStream) {
ret = acmStreamClose(wim->hAcmStream, 0);
}
if (ret == MMSYSERR_NOERROR) {
HeapFree(GetProcessHeap(), 0, wim);
}
}
return ret;
}
static DWORD widAddBuffer(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdrDst, DWORD dwParam2)
{
PACMSTREAMHEADER ash;
LPWAVEHDR lpWaveHdrSrc;
if (!wim->hAcmStream) {
return waveInAddBuffer(wim->u.in.hInnerWave, lpWaveHdrDst, dwParam2);
}
lpWaveHdrDst->dwFlags |= WHDR_INQUEUE;
ash = (PACMSTREAMHEADER)lpWaveHdrDst->reserved;
lpWaveHdrSrc = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
return waveInAddBuffer(wim->u.in.hInnerWave, lpWaveHdrSrc, sizeof(*lpWaveHdrSrc));
}
static DWORD widPrepare(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdrDst, DWORD dwParam2)
{
PACMSTREAMHEADER ash;
DWORD size;
DWORD dwRet;
LPWAVEHDR lpWaveHdrSrc;
if (!wim->hAcmStream) {
return waveInPrepareHeader(wim->u.in.hInnerWave, lpWaveHdrDst, dwParam2);
}
if (acmStreamSize(wim->hAcmStream, lpWaveHdrDst->dwBufferLength, &size,
ACM_STREAMSIZEF_DESTINATION) != MMSYSERR_NOERROR)
return MMSYSERR_ERROR;
ash = HeapAlloc(GetProcessHeap(), 0, sizeof(ACMSTREAMHEADER) + sizeof(WAVEHDR) + size);
if (ash == NULL)
return MMSYSERR_NOMEM;
ash->cbStruct = sizeof(*ash);
ash->fdwStatus = 0L;
ash->dwUser = (DWORD)lpWaveHdrDst;
ash->pbSrc = (LPSTR)ash + sizeof(ACMSTREAMHEADER) + sizeof(WAVEHDR);
ash->cbSrcLength = size;
/* ash->cbSrcLengthUsed */
ash->dwSrcUser = 0L; /* FIXME ? */
ash->pbDst = lpWaveHdrDst->lpData;
ash->cbDstLength = lpWaveHdrDst->dwBufferLength;
/* ash->cbDstLengthUsed */
ash->dwDstUser = lpWaveHdrDst->dwUser; /* FIXME ? */
dwRet = acmStreamPrepareHeader(wim->hAcmStream, ash, 0L);
if (dwRet != MMSYSERR_NOERROR)
goto errCleanUp;
lpWaveHdrSrc = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
lpWaveHdrSrc->lpData = ash->pbSrc;
lpWaveHdrSrc->dwBufferLength = size; /* conversion is not done yet */
lpWaveHdrSrc->dwFlags = 0;
lpWaveHdrSrc->dwLoops = 0;
dwRet = waveInPrepareHeader(wim->u.in.hInnerWave, lpWaveHdrSrc, sizeof(*lpWaveHdrSrc));
if (dwRet != MMSYSERR_NOERROR)
goto errCleanUp;
lpWaveHdrDst->reserved = (DWORD)ash;
lpWaveHdrDst->dwFlags = WHDR_PREPARED;
TRACE("=> (0)\n");
return MMSYSERR_NOERROR;
errCleanUp:
TRACE("=> (%ld)\n", dwRet);
HeapFree(GetProcessHeap(), 0, ash);
return dwRet;
}
static DWORD widUnprepare(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdrDst, DWORD dwParam2)
{
PACMSTREAMHEADER ash;
LPWAVEHDR lpWaveHdrSrc;
DWORD dwRet1, dwRet2;
if (!wim->hAcmStream) {
return waveInUnprepareHeader(wim->u.in.hInnerWave, lpWaveHdrDst, dwParam2);
}
ash = (PACMSTREAMHEADER)lpWaveHdrDst->reserved;
dwRet1 = acmStreamUnprepareHeader(wim->hAcmStream, ash, 0L);
lpWaveHdrSrc = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
dwRet2 = waveInUnprepareHeader(wim->u.in.hInnerWave, lpWaveHdrSrc, sizeof(*lpWaveHdrSrc));
HeapFree(GetProcessHeap(), 0, ash);
lpWaveHdrDst->dwFlags &= ~WHDR_PREPARED;
return (dwRet1 == MMSYSERR_NOERROR) ? dwRet2 : dwRet1;
}
static DWORD widGetPosition(WAVEMAPDATA* wim, LPMMTIME lpTime, DWORD dwParam2)
{
DWORD val = waveInGetPosition(wim->u.in.hInnerWave, lpTime, dwParam2);
if (lpTime->wType == TIME_BYTES)
lpTime->u.cb = MulDiv(lpTime->u.cb, wim->avgSpeedOuter, wim->avgSpeedInner);
/* other time types don't require conversion */
return val;
}
static DWORD widGetDevCaps(UINT wDevID, WAVEMAPDATA* wim, LPWAVEINCAPSA lpWaveCaps, DWORD dwParam2)
{
/* if opened low driver, forward message */
if (WAVEMAP_IsData(wim))
return waveInGetDevCapsA((UINT)wim->u.in.hInnerWave, lpWaveCaps, dwParam2);
/* otherwise, return caps of mapper itself */
if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) {
lpWaveCaps->wMid = 0x00FF;
lpWaveCaps->wPid = 0x0001;
lpWaveCaps->vDriverVersion = 0x0001;
strcpy(lpWaveCaps->szPname, "Wine wave in mapper");
lpWaveCaps->dwFormats =
WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16 |
WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 | WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16;
lpWaveCaps->wChannels = 2;
return MMSYSERR_NOERROR;
}
ERR("This shouldn't happen\n");
return MMSYSERR_ERROR;
}
static DWORD widStop(WAVEMAPDATA* wim)
{
return waveInStop(wim->u.in.hInnerWave);
}
static DWORD widStart(WAVEMAPDATA* wim)
{
return waveInStart(wim->u.in.hInnerWave);
}
static DWORD widReset(WAVEMAPDATA* wim)
{
return waveInReset(wim->u.in.hInnerWave);
}
static DWORD widMapperStatus(WAVEMAPDATA* wim, DWORD flags, LPVOID ptr)
{
UINT id;
DWORD ret = MMSYSERR_NOTSUPPORTED;
switch (flags) {
case WAVEIN_MAPPER_STATUS_DEVICE:
ret = waveInGetID(wim->u.in.hInnerWave, &id);
*(LPDWORD)ptr = id;
break;
case WAVEIN_MAPPER_STATUS_MAPPED:
FIXME("Unsupported yet flag=%ld\n", flags);
*(LPDWORD)ptr = 0; /* FIXME ?? */
break;
case WAVEIN_MAPPER_STATUS_FORMAT:
FIXME("Unsupported flag=%ld\n", flags);
/* ptr points to a WAVEFORMATEX struct - before or after streaming ? */
*(LPDWORD)ptr = 0; /* FIXME ?? */
break;
default:
FIXME("Unsupported flag=%ld\n", flags);
*(LPDWORD)ptr = 0;
break;
}
return ret;
}
/**************************************************************************
* widMessage (MSACM.@)
*/
DWORD WINAPI WAVEMAP_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
DWORD dwParam1, DWORD dwParam2)
{
TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
wDevID, wMsg, dwUser, dwParam1, dwParam2);
switch (wMsg) {
case DRVM_INIT:
case DRVM_EXIT:
case DRVM_ENABLE:
case DRVM_DISABLE:
/* FIXME: Pretend this is supported */
return 0;
case WIDM_OPEN: return widOpen ((LPDWORD)dwUser, (LPWAVEOPENDESC)dwParam1, dwParam2);
case WIDM_CLOSE: return widClose ((WAVEMAPDATA*)dwUser);
case WIDM_ADDBUFFER: return widAddBuffer ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2);
case WIDM_PREPARE: return widPrepare ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2);
case WIDM_UNPREPARE: return widUnprepare ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2);
case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (WAVEMAPDATA*)dwUser, (LPWAVEINCAPSA)dwParam1, dwParam2);
case WIDM_GETNUMDEVS: return 1;
case WIDM_GETPOS: return widGetPosition ((WAVEMAPDATA*)dwUser, (LPMMTIME)dwParam1, dwParam2);
case WIDM_RESET: return widReset ((WAVEMAPDATA*)dwUser);
case WIDM_START: return widStart ((WAVEMAPDATA*)dwUser);
case WIDM_STOP: return widStop ((WAVEMAPDATA*)dwUser);
case WIDM_MAPPER_STATUS: return widMapperStatus ((WAVEMAPDATA*)dwUser, dwParam1, (LPVOID)dwParam2);
default:
FIXME("unknown message %u!\n", wMsg);
}
return MMSYSERR_NOTSUPPORTED;
}
/*======================================================================*
* Driver part *
*======================================================================*/
static struct WINE_WAVEMAP* oss = NULL;
/**************************************************************************
* WAVEMAP_drvOpen [internal]
*/
static DWORD WAVEMAP_drvOpen(LPSTR str)
{
if (oss)
return 0;
/* I know, this is ugly, but who cares... */
oss = (struct WINE_WAVEMAP*)1;
return 1;
}
/**************************************************************************
* WAVEMAP_drvClose [internal]
*/
static DWORD WAVEMAP_drvClose(DWORD dwDevID)
{
if (oss) {
oss = NULL;
return 1;
}
return 0;
}
/**************************************************************************
* DriverProc (MSACM.@)
*/
LONG CALLBACK WAVEMAP_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
DWORD dwParam1, DWORD dwParam2)
{
TRACE("(%08lX, %p, %08lX, %08lX, %08lX)\n",
dwDevID, hDriv, wMsg, dwParam1, dwParam2);
switch(wMsg) {
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return WAVEMAP_drvOpen((LPSTR)dwParam1);
case DRV_CLOSE: return WAVEMAP_drvClose(dwDevID);
case DRV_ENABLE: return 1;
case DRV_DISABLE: return 1;
case DRV_QUERYCONFIGURE: return 1;
case DRV_CONFIGURE: MessageBoxA(0, "WAVEMAP MultiMedia Driver !", "Wave mapper Driver", MB_OK); return 1;
case DRV_INSTALL: return DRVCNF_RESTART;
case DRV_REMOVE: return DRVCNF_RESTART;
default:
return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
}
}

View file

@ -0,0 +1,39 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "ReactOS/WINE Wave Mapper\0"
VALUE "FileVersion", RES_STR_FILE_VERSION
VALUE "InternalName", "wavemap\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "wavemap.dll\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View file

@ -0,0 +1,2 @@
@ stdcall DriverProc(long long long long long) MIDIMAP_DriverProc
@ stdcall modMessage(long long long long long) MIDIMAP_modMessage

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: bitmaps.c,v 1.58 2004/02/25 01:25:51 sedwards Exp $ */
/* $Id: bitmaps.c,v 1.59 2004/03/10 15:22:43 silverblade Exp $ */
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
@ -268,6 +268,7 @@ HBITMAP STDCALL NtGdiCreateBitmap(INT Width,
{
PBITMAPOBJ bmp;
HBITMAP hBitmap;
int Pixel;
Planes = (BYTE) Planes;
BitsPerPel = (BYTE) BitsPerPel;
@ -321,6 +322,12 @@ HBITMAP STDCALL NtGdiCreateBitmap(INT Width,
bmp->bitmap.bmBits = ExAllocatePoolWithTag(PagedPool, bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight, TAG_BITMAP);
BITMAPOBJ_UnlockBitmap( hBitmap );
// Initialize the bitmap (fixes bug 244?)
for (Pixel = 0; Pixel < Height * bmp->bitmap.bmWidthBytes; Pixel ++)
{
((char*)Bits)[Pixel] = 0;
}
if (Bits) /* Set bitmap bits */
{

View file

@ -1,4 +1,4 @@
# $Id: helper.mk,v 1.59 2004/03/04 23:14:01 dwelch Exp $
# $Id: helper.mk,v 1.60 2004/03/10 15:22:44 silverblade Exp $
#
# Helper makefile for ReactOS modules
# Variables this makefile accepts:
@ -467,6 +467,38 @@ endif
MK_RC_BINARIES = $(TARGET_RC_BINARIES)
endif
ifeq ($(TARGET_TYPE),winedrv)
-include Makefile.ros
MK_GENERATED_MAKEFILE = Makefile.ros
MK_MODE := user
MK_EXETYPE := drv
MK_DEFEXT := .drv
# does this need changing?:
MK_DEFENTRY := _DllMain@12
MK_DDKLIBS :=
MK_SDKLIBS :=
MK_CFLAGS := -D__USE_W32API -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x501 -DWINVER=0x501 -D__need_offsetof -DCOBJMACROS -I$(PATH_TO_TOP)/include/wine
MK_CPPFLAGS := -D__USE_W32API -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x501 -DWINVER=0x501 -D__need_offsetof -DCOBJMACROS -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/include/wine
MK_RCFLAGS := --define __USE_W32API --include-dir $(PATH_TO_TOP)/include/wine
MK_IMPLIB := yes
MK_IMPLIBONLY := no
MK_IMPLIBDEFPATH := $(SDK_PATH_LIB)
MK_IMPLIB_EXT := .a
MK_INSTALLDIR := system32
MK_BOOTCDDIR := system32
MK_DISTDIR := dlls
MK_RES_BASE := $(TARGET_NAME)
ifeq ($(TARGET_DEFNAME),)
MK_DEFBASENAME := $(TARGET_NAME).spec
MK_SPECDEF := $(MK_DEFBASENAME).def
else
MK_DEFBASENAME := $(TARGET_DEFNAME)
endif
MK_KILLAT := --kill-at
TARGET_DEFONLY := yes
MK_RC_BINARIES = $(TARGET_RC_BINARIES)
endif
ifeq ($(TARGET_RC_SRCS),)
MK_RES_SRC := $(TARGET_PATH)/$(MK_RES_BASE).rc
MK_RESOURCE := $(MK_RES_BASE).coff
@ -1030,6 +1062,8 @@ endif # ROS_USE_PCH
$(RC) $(TARGET_RCFLAGS) $< -o $@
%.spec.def: %.spec
$(WINEBUILD) $(DEFS) -o $@ --def $<
%.drv.spec.def: %.spec
$(WINEBUILD) $(DEFS) -o $@ --def $<
# Kill implicit rule
.o:;