Author: nyadav Date: Fri Apr 22 07:55:04 2011 New Revision: 51420
URL: http://svn.reactos.org/svn/reactos?rev=51420&view=rev Log: New Audio Server
Added: branches/nyadav-audio-branch/base/services/audiosrv2/ (with props) branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/ (with props) branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.cpp (with props) branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.h (with props) branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/dllmain.cpp (with props) branches/nyadav-audio-branch/base/services/audiosrv2/audsrv.c (with props)
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/ ------------------------------------------------------------------------------ --- bugtraq:logregex (added) +++ bugtraq:logregex Fri Apr 22 07:55:04 2011 @@ -1,0 +1,2 @@ +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+)
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/ ------------------------------------------------------------------------------ bugtraq:message = See issue #%BUGID% for more details.
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/ ------------------------------------------------------------------------------ bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/ ------------------------------------------------------------------------------ tsvn:logminsize = 10
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/ ------------------------------------------------------------------------------ --- bugtraq:logregex (added) +++ bugtraq:logregex Fri Apr 22 07:55:04 2011 @@ -1,0 +1,2 @@ +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+)
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/ ------------------------------------------------------------------------------ bugtraq:message = See issue #%BUGID% for more details.
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/ ------------------------------------------------------------------------------ bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/ ------------------------------------------------------------------------------ tsvn:logminsize = 10
Added: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.cpp URL: http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/base/service... ============================================================================== --- branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.cpp (added) +++ branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.cpp [iso-8859-1] Fri Apr 22 07:55:04 2011 @@ -1,0 +1,14 @@ +// PortInterface.cpp : Defines the exported functions for the DLL application. +// + +#include "PortInterface.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef __cplusplus +} +#endif
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.cpp ------------------------------------------------------------------------------ svn:eol-style = native
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.cpp ------------------------------------------------------------------------------ svn:mime-type = text/plain
Added: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.h URL: http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/base/service... ============================================================================== --- branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.h (added) +++ branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.h [iso-8859-1] Fri Apr 22 07:55:04 2011 @@ -1,0 +1,47 @@ +#include <windows.h> +#include <memory.h> + +#ifndef _PORTINTERFACE_H +#define _PORTINTERFACE_H + +#define MIXER getmixerengine() + +typedef struct PortStream +{ + int volume; + double freq; + int channels; + int bitspersample; + DWORD channelmask; + HANDLE thread; + struct PortStream * next; +} PortStream; + +typedef struct MixerEngine +{ + int mastervolume; + int mute; + char dead; + double masterfreq; + int masterchannels; + DWORD masterchannelmask; + int masterbitspersample; + int workingbuffer; + PSHORT masterdoublebuf[2]; + HANDLE mixerthread; + HANDLE playerthread; + HANDLE EventPool[2];//0=Played,1=Ready + PortStream * portstream; +} MixerEngine; + +#ifdef __cplusplus +extern "C" { +#endif + +__declspec(dllexport) MixerEngine * getmixerengine(); + +#ifdef __cplusplus +} +#endif + +#endif
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.h ------------------------------------------------------------------------------ svn:eol-style = native
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/PortInterface.h ------------------------------------------------------------------------------ svn:mime-type = text/plain
Added: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/dllmain.cpp URL: http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/base/service... ============================================================================== --- branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/dllmain.cpp (added) +++ branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/dllmain.cpp [iso-8859-1] Fri Apr 22 07:55:04 2011 @@ -1,0 +1,68 @@ + +#include "PortInterface.h" + +static MixerEngine * lpvMem = NULL; +static HANDLE hMapObject = NULL; + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ +BOOL fInit, fIgnore; + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + hMapObject = CreateFileMapping( + INVALID_HANDLE_VALUE, // use paging file + NULL, // default security attributes + PAGE_READWRITE, // read/write access + 0, // size: high 32-bits + sizeof(MixerEngine),TEXT("MixerEngine")); // size: low 32-bits + if (hMapObject == NULL) + return FALSE; + + fInit = (GetLastError() != ERROR_ALREADY_EXISTS); + + lpvMem = (MixerEngine *)MapViewOfFile( + hMapObject, // object to map view of + FILE_MAP_WRITE, // read/write access + 0, // high offset: map from + 0, // low offset: beginning + 0); // default: map entire file + if (lpvMem == NULL) + return FALSE; + + if (fInit) + lpvMem->dead=0; + lpvMem->masterchannels=0; + lpvMem->masterbitspersample=0; + lpvMem->masterchannelmask=0; + lpvMem->masterdoublebuf[0]=NULL; + lpvMem->masterdoublebuf[1]=NULL; + lpvMem->masterfreq=0; + lpvMem->mastervolume=0; + lpvMem->mute=0; + lpvMem->portstream=NULL; + lpvMem->workingbuffer=0; + lpvMem->mixerthread=NULL; + lpvMem->playerthread=NULL; + lpvMem->EventPool[0]=CreateEvent(NULL,FALSE,FALSE,NULL); + lpvMem->EventPool[1]=CreateEvent(NULL,FALSE,FALSE,NULL); + + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + fIgnore = UnmapViewOfFile(lpvMem); + fIgnore = CloseHandle(hMapObject); + break; + } + return TRUE; +} + +__declspec(dllexport) MixerEngine * getmixerengine() +{ +return lpvMem; +}
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/dllmain.cpp ------------------------------------------------------------------------------ svn:eol-style = native
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/PortInterface/dllmain.cpp ------------------------------------------------------------------------------ svn:mime-type = text/plain
Added: branches/nyadav-audio-branch/base/services/audiosrv2/audsrv.c URL: http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/base/service... ============================================================================== --- branches/nyadav-audio-branch/base/services/audiosrv2/audsrv.c (added) +++ branches/nyadav-audio-branch/base/services/audiosrv2/audsrv.c [iso-8859-1] Fri Apr 22 07:55:04 2011 @@ -1,0 +1,302 @@ +#define _UNICODE +#define UNICODE +#define WIN32_NO_STATUS +#define _KSDDK_ + +#include <windows.h> +#include <mmsystem.h> +#include <stdio.h> +#include <math.h> +#include <setupapi.h> +#include <ndk/ntndk.h> +#include <ks.h> +#include <ksmedia.h> +#include "interface.h" +#include "PortInterface/PortInterface.h" +#define _2pi 6.283185307179586476925286766559 + + + +#include <ks.h> + + +GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO}; + + +const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}}; +const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; +const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}}; +const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; +const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; +const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; + +void fill(MixerEngine * mixer) +{ + DWORD Length = mixer->masterfreq * mixer->masterchannels * mixer->masterbitspersample / 8; + UINT i = 0; + mixer->masterchannels=2; + mixer->masterfreq=48000; + mixer->masterbitspersample=16; + mixer->masterchannelmask = KSAUDIO_SPEAKER_STEREO; + mixer->masterdoublebuf[0] = (PSHORT)HeapAlloc(GetProcessHeap(), 0, Length); + while (i < Length / 2) + { + mixer->masterdoublebuf[0][i] = 0x7FFF * sin(0.5 * (i - 1) * 500 * _2pi / 48000); + i++; + mixer->masterdoublebuf[0][i] = 0x7FFF * sin((0.5 * i - 2) * 500 * _2pi / 48000); + i++; + } +} + +void Playbuffer(MixerEngine * mixer) +{ + SP_DEVICE_INTERFACE_DATA InterfaceData; + SP_DEVINFO_DATA DeviceData; + PSP_DEVICE_INTERFACE_DETAIL_DATA DetailData; + HDEVINFO DeviceHandle; + PKSDATAFORMAT DataFormat; + PWAVEFORMATEXTENSIBLE WaveFormat; + PKSPIN_CONNECT PinConnect; + PKSSTREAM_HEADER Packet; + PKSPROPERTY Property; + KSSTATE State; + DWORD Length; + HANDLE FilterHandle; + HANDLE PinHandle; + PSHORT SoundBuffer; + BOOL Result; + NTSTATUS Status; + + + // + // Get a handle to KS Audio Interfaces + // + DeviceHandle = SetupDiGetClassDevs(&CategoryGuid, + NULL, + NULL, + DIGCF_DEVICEINTERFACE |DIGCF_PRESENT); + + printf("DeviceHandle %p\n", DeviceHandle); + + // + // Enumerate the first interface + // + InterfaceData.cbSize = sizeof(InterfaceData); + InterfaceData.Reserved = 0; + Result = SetupDiEnumDeviceInterfaces(DeviceHandle, + NULL, + &CategoryGuid, + 1, + &InterfaceData); + + printf("SetupDiEnumDeviceInterfaces %u Error %ld\n", Result, GetLastError()); + + // + // Get the interface details (namely the device path) + // + Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR); + DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + Length); + DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + DeviceData.cbSize = sizeof(DeviceData); + DeviceData.Reserved = 0; + Result = SetupDiGetDeviceInterfaceDetail(DeviceHandle, + &InterfaceData, + DetailData, + Length, + NULL, + &DeviceData); + + wprintf(L"SetupDiGetDeviceInterfaceDetail %u Path DetailData %s\n", Result, (LPWSTR)&DetailData->DevicePath[0]); + + // + // Open a handle to the device + // + FilterHandle = CreateFile(DetailData->DevicePath, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + printf("Handle %p\n", FilterHandle); + + // + // Close the interface handle and clean up + // + //SetupDiDestroyDeviceInfoList(DeviceHandle); + + // + // Allocate a KS Pin Connection Request Structure + // + Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); + PinConnect = (PKSPIN_CONNECT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length); + DataFormat = (PKSDATAFORMAT)(PinConnect + 1); + WaveFormat = (PWAVEFORMATEXTENSIBLE)(DataFormat + 1); + + // + // Setup the KS Pin Data + // + + PinConnect->Interface.Set = KSINTERFACESETID_Standard; + PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; + PinConnect->Interface.Flags = 0; + PinConnect->Medium.Set = KSMEDIUMSETID_Standard; + PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; + PinConnect->Medium.Flags = 0; + PinConnect->PinId = 0; + PinConnect->PinToHandle = NULL; + PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; + PinConnect->Priority.PrioritySubClass = 1; + + // + // Setup the KS Data Format Information + // + printf("DataFormat %p %p\n", DataFormat,(PVOID)((((ULONG_PTR)DataFormat + 7)) & ~7)); + + DataFormat->Flags = 0; + DataFormat->Reserved = 0; + DataFormat->MajorFormat = KSDATAFORMAT_TYPE_AUDIO; + DataFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + DataFormat->Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; + DataFormat->SampleSize = mixer->masterchannels * mixer->masterbitspersample / 8; + DataFormat->FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEXTENSIBLE); + + WaveFormat->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + WaveFormat->Format.nChannels = mixer->masterchannels; + WaveFormat->Format.nSamplesPerSec = mixer->masterfreq; + WaveFormat->Format.nBlockAlign = (mixer->masterchannels * mixer->masterbitspersample)/8;; + WaveFormat->Format.nAvgBytesPerSec = WaveFormat->Format.nSamplesPerSec * WaveFormat->Format.nBlockAlign; + WaveFormat->Format.wBitsPerSample = mixer->masterbitspersample; + WaveFormat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + WaveFormat->dwChannelMask = mixer->masterchannelmask; + WaveFormat->Samples.wValidBitsPerSample = mixer->masterbitspersample; + WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + + printf("Creating pin\n"); + + // + // Create the pin + // + Status = KsCreatePin(FilterHandle, PinConnect, GENERIC_READ|GENERIC_WRITE, &PinHandle); + + printf("PinHandle %p Status %lx\n", PinHandle, Status); + + + Length = mixer->masterfreq * mixer->masterchannels * mixer->masterbitspersample / 8; + // + // Create and fill out the KS Stream Packet + // + Packet = (PKSSTREAM_HEADER)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(KSSTREAM_HEADER)); + Packet->Data = mixer->masterdoublebuf[0]; + Packet->FrameExtent = Length; + Packet->DataUsed = Length; + Packet->Size = sizeof(KSSTREAM_HEADER); + Packet->PresentationTime.Numerator = 1; + Packet->PresentationTime.Denominator = 1; + + // + // Setup a KS Property to change the state + // + Property = (PKSPROPERTY)HeapAlloc(GetProcessHeap(), 0, sizeof(KSPROPERTY)); + Property->Set = KSPROPSETID_Connection; + Property->Id = KSPROPERTY_CONNECTION_STATE; + Property->Flags = KSPROPERTY_TYPE_SET; + + // + // Change the state to run + // + State = KSSTATE_RUN; + DeviceIoControl(PinHandle, + IOCTL_KS_PROPERTY, + Property, + sizeof(KSPROPERTY), + &State, + sizeof(State), + &Length, + NULL); + + // + // Play our 1-second buffer + // + DeviceIoControl(PinHandle, + IOCTL_KS_WRITE_STREAM, + NULL, + 0, + Packet, + Packet->Size, + &Length, + NULL); + + // + // Change the state to stop + // + State = KSSTATE_STOP; + DeviceIoControl(PinHandle, + IOCTL_KS_PROPERTY, + Property, + sizeof(KSPROPERTY), + &State, + sizeof(State), + &Length, + NULL); + + CloseHandle(PinHandle); + CloseHandle(FilterHandle); + +} +DWORD WINAPI RunMixerThread(LPVOID param) +{ + MixerEngine * mixer = (MixerEngine *) param; + SetEvent(mixer->EventPool[0]); + while(1) + { + while(WaitForSingleObject(mixer->EventPool[0],100)!=0){if(mixer->dead)goto DEAD;} + fill(mixer); + SetEvent(mixer->EventPool[1]); + } +DEAD: + printf("Mixer Thread Ended\n"); + return 0; +} +DWORD WINAPI RunPlayerThread(LPVOID param) +{ + MixerEngine * mixer = (MixerEngine *) param; + while(1) + { + while(WaitForSingleObject(mixer->EventPool[0],100)!=0){if(mixer->dead)goto DEAD;} + Playbuffer(mixer); + SetEvent(mixer->EventPool[0]); + } +DEAD: + printf("Player Thread Ended\n"); + return 0; +} +void SpawnMixerThread(MixerEngine * mixer) +{ + DWORD dwID; + mixer->mixerthread=CreateThread(NULL,0,RunMixerThread,MIXER,0,&dwID); +} +void SpawnPlayerThread(MixerEngine * mixer) +{ + DWORD dwID; + mixer->playerthread=CreateThread(NULL,0,RunPlayerThread,MIXER,0,&dwID); +} + +int +__cdecl +main(int argc, char* argv[]) +{ + SpawnMixerThread(MIXER); + SpawnPlayerThread(MIXER); + WaitForSingleObject(MIXER->mixerthread,INFINITE); + WaitForSingleObject(MIXER->playerthread,INFINITE); + return 0; +}
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/audsrv.c ------------------------------------------------------------------------------ svn:eol-style = native
Propchange: branches/nyadav-audio-branch/base/services/audiosrv2/audsrv.c ------------------------------------------------------------------------------ svn:mime-type = text/plain