Compare commits

...

40 Commits

Author SHA1 Message Date
Neeraj Yadav
44890cc54f [AUDSRV] Stop playback when client terminates/closes RPC connection
svn path=/branches/nyadav-audio-branch/; revision=52680
2011-07-14 14:25:44 +00:00
Neeraj Yadav
ed4ed6c5ab [AUDSRV] Finally a working audio mixer :)
svn path=/branches/nyadav-audio-branch/; revision=52657
2011-07-12 16:45:52 +00:00
Neeraj Yadav
a2d31f3759 [AUDSRV] server ready to accept actual buffer from client
svn path=/branches/nyadav-audio-branch/; revision=52653
2011-07-12 10:50:31 +00:00
Neeraj Yadav
548c4078d5 [AUDSRV] Fix some Thread Synchronization bugs and some style fixes
svn path=/branches/nyadav-audio-branch/; revision=52602
2011-07-10 12:55:38 +00:00
Neeraj Yadav
6e480ff031 [AUDSRV] fix mixer routine, working now
svn path=/branches/nyadav-audio-branch/; revision=52328
2011-06-18 10:37:54 +00:00
Neeraj Yadav
0fbb37be93 [AUDSRV] More Style Fixes
svn path=/branches/nyadav-audio-branch/; revision=52169
2011-06-10 07:00:52 +00:00
Neeraj Yadav
0039ae9f4d [AUDSRV] mixer routine for signed 16 bit data
svn path=/branches/nyadav-audio-branch/; revision=52167
2011-06-09 23:06:06 +00:00
Neeraj Yadav
4f2a3e8196 [AUDSRV] Fix Function Names to Conventions
svn path=/branches/nyadav-audio-branch/; revision=52162
2011-06-09 18:43:48 +00:00
Neeraj Yadav
1fd76abbae [AUDSRV] Following Naming Convention for Functions
svn path=/branches/nyadav-audio-branch/; revision=52161
2011-06-09 18:31:59 +00:00
Neeraj Yadav
e4ea774182 [AUDSRV] Add File Headers,some style fixes
svn path=/branches/nyadav-audio-branch/; revision=52160
2011-06-09 18:12:07 +00:00
Neeraj Yadav
3b4f5e313c [AUDSRV] Style Fixes,Warning Fixes,Documentation etc
svn path=/branches/nyadav-audio-branch/; revision=52115
2011-06-06 12:20:41 +00:00
Neeraj Yadav
de1bd0a605 [AUDSRV] Turn Off verbosity
svn path=/branches/nyadav-audio-branch/; revision=52081
2011-06-04 18:39:06 +00:00
Neeraj Yadav
608d51b7f1 [AUDSRV] finish upto actual mixing functions
svn path=/branches/nyadav-audio-branch/; revision=52076
2011-06-03 21:41:26 +00:00
Neeraj Yadav
56e0ac6ab6 [AUDSRV] Use Double Buffering to Improve latency
svn path=/branches/nyadav-audio-branch/; revision=52020
2011-05-31 16:30:46 +00:00
Neeraj Yadav
938eb58a2e [AUDSRV] Fix RPC Connection and Remove Test Apps
svn path=/branches/nyadav-audio-branch/; revision=52008
2011-05-30 13:20:20 +00:00
Neeraj Yadav
2d9aa9c767 [AUDSRV] Use Unicode versions of RPC functions
svn path=/branches/nyadav-audio-branch/; revision=52007
2011-05-30 12:37:20 +00:00
Neeraj Yadav
b162936df8 [AUDSRV] connect audio server and client
svn path=/branches/nyadav-audio-branch/; revision=52005
2011-05-30 11:32:19 +00:00
Neeraj Yadav
c86206d456 [AUDSRV] Add Playback of virtual buffer on virtual server to audio client
svn path=/branches/nyadav-audio-branch/; revision=51964
2011-05-27 21:11:53 +00:00
Neeraj Yadav
23859ae322 CMAKE: Show Extended Debug Messages while building
svn path=/branches/nyadav-audio-branch/; revision=51958
2011-05-27 14:35:50 +00:00
Neeraj Yadav
796708eaed [AUDSRV] Modify Architecture of server to use RPC
svn path=/branches/nyadav-audio-branch/; revision=51955
2011-05-27 09:48:26 +00:00
Neeraj Yadav
bda4efccd4 [AUDSRV] Add a client to test audio server
svn path=/branches/nyadav-audio-branch/; revision=51954
2011-05-27 09:40:19 +00:00
Neeraj Yadav
1853a835fc [AUDSRV] AUDIO server modified headers and new IDL files
svn path=/branches/nyadav-audio-branch/; revision=51953
2011-05-27 09:33:13 +00:00
Neeraj Yadav
4c970849fc [AUDSRV] Revamp Audio Server API with RPC
svn path=/branches/nyadav-audio-branch/; revision=51952
2011-05-27 09:20:19 +00:00
Neeraj Yadav
8200abb90e [AUDSRV] Revamp Audio Server Api with RPC
svn path=/branches/nyadav-audio-branch/; revision=51951
2011-05-27 09:05:47 +00:00
Neeraj Yadav
c046e1125a [AUDSRV] Revamp Audio Server Api with RPC
svn path=/branches/nyadav-audio-branch/; revision=51950
2011-05-27 09:00:12 +00:00
Neeraj Yadav
3cf76813a1 Audio Server API with RPC
svn path=/branches/nyadav-audio-branch/; revision=51949
2011-05-27 08:50:55 +00:00
Neeraj Yadav
3566e33421 Fix a Deadlock
svn path=/branches/nyadav-audio-branch/; revision=51882
2011-05-24 12:13:43 +00:00
Neeraj Yadav
e8ad899398 FIX IMPORTS
svn path=/branches/nyadav-audio-branch/; revision=51881
2011-05-24 11:45:20 +00:00
Neeraj Yadav
f65941c481 remove unused variable
svn path=/branches/nyadav-audio-branch/; revision=51880
2011-05-24 11:43:59 +00:00
Neeraj Yadav
e6598f4f34 fix audiosrv header
svn path=/branches/nyadav-audio-branch/; revision=51879
2011-05-24 11:40:08 +00:00
Neeraj Yadav
77b41ca6a0 add audiosrv2dll with c files
svn path=/branches/nyadav-audio-branch/; revision=51878
2011-05-24 10:52:20 +00:00
Neeraj Yadav
8065701376 Delete audiosrv2dll
svn path=/branches/nyadav-audio-branch/; revision=51877
2011-05-24 10:46:51 +00:00
Neeraj Yadav
51726a9785 Add Audio Server Headers
svn path=/branches/nyadav-audio-branch/; revision=51433
2011-04-22 17:27:40 +00:00
Neeraj Yadav
ee5931681b Add audiosrv2dll
svn path=/branches/nyadav-audio-branch/; revision=51432
2011-04-22 17:24:36 +00:00
Neeraj Yadav
4e4fee5c45 Add audiosrv2exe
svn path=/branches/nyadav-audio-branch/; revision=51431
2011-04-22 17:19:48 +00:00
Neeraj Yadav
c825b9f249 Rearranging
svn path=/branches/nyadav-audio-branch/; revision=51430
2011-04-22 17:10:38 +00:00
Neeraj Yadav
0fad2e4d67 Add to Build System
svn path=/branches/nyadav-audio-branch/; revision=51421
2011-04-22 08:02:58 +00:00
Neeraj Yadav
3f32f73948 New Audio Server
svn path=/branches/nyadav-audio-branch/; revision=51420
2011-04-22 07:55:04 +00:00
Neeraj Yadav
40b0390d6d Fix headers for audio_test
svn path=/branches/nyadav-audio-branch/; revision=51251
2011-04-04 13:21:25 +00:00
Neeraj Yadav
e78f8c2434 fix audio_test
svn path=/branches/nyadav-audio-branch/; revision=51250
2011-04-04 13:18:52 +00:00
24 changed files with 1919 additions and 23 deletions

View File

@@ -22,6 +22,9 @@ set(CMAKE_SKIP_ASSEMBLY_SOURCE_RULES TRUE)
set(CMAKE_COLOR_MAKEFILE OFF)
set_property(GLOBAL PROPERTY RULE_MESSAGES OFF)
#Show Debug Output while Building
#SET(CMAKE_VERBOSE_MAKEFILE ON)
if(NOT ARCH)
set(ARCH i386)
endif()

View File

@@ -1,5 +1,6 @@
add_subdirectory(audiosrv)
add_subdirectory(audsrv)
add_subdirectory(eventlog)
add_subdirectory(rpcss)
add_subdirectory(spoolsv)

View File

@@ -0,0 +1,21 @@
include_directories(${REACTOS_BINARY_DIR}/include/reactos/idl)
set_unicode()
list(APPEND SOURCE
audsrv.c
audsrv.rc
rpc.c
mixer.c
stream.c)
add_executable(audsrv ${SOURCE})
target_link_libraries(audsrv audsrvrpc ${PSEH_LIB})
add_pch(audsrv ${CMAKE_CURRENT_SOURCE_DIR}/audsrv.h ${SOURCE})
set_module_type(audsrv win32cui)
add_importlibs(audsrv advapi32 rpcrt4 msvcrt kernel32 ntdll user32 ksuser setupapi)
add_cab_target(audsrv 1)

View File

@@ -0,0 +1,635 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: services/audsrv.c
* PURPOSE: Audio Server
* COPYRIGHT: Copyright 2011 Neeraj Yadav
*/
#include "audsrv.h"
static VOID CALLBACK ServiceMain(DWORD,
LPWSTR *);
static DWORD ServiceInit(VOID);
static BOOL WINAPI Close (DWORD dwCtrlType);
static WCHAR ServiceName[] = L"AudSrv";
static SERVICE_TABLE_ENTRYW ServiceTable[2] =
{
{ ServiceName, ServiceMain },
{ NULL, NULL }
};
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE ServiceStatusHandle;
#define _2pi 6.283185307179586476925286766559
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_SUBTYPE_IEEE_FLOAT = {0x00000003L, 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}};
/*Global Pointer to MixerEngine Structure*/
MixerEngine engine,*pengine;
static
VOID
UpdateServiceStatus(DWORD dwState)
{
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState = dwState;
ServiceStatus.dwControlsAccepted = 0;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
if (dwState == SERVICE_START_PENDING ||
dwState == SERVICE_STOP_PENDING ||
dwState == SERVICE_PAUSE_PENDING ||
dwState == SERVICE_CONTINUE_PENDING)
ServiceStatus.dwWaitHint = 10000;
else
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(ServiceStatusHandle,
&ServiceStatus);
}
static DWORD WINAPI
ServiceControlHandler(DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext)
{
DPRINT("ServiceControlHandler() called\n");
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
DPRINT(" SERVICE_CONTROL_STOP received\n");
Close(CTRL_CLOSE_EVENT);
UpdateServiceStatus(SERVICE_STOPPED);
return ERROR_SUCCESS;
case SERVICE_CONTROL_PAUSE:
DPRINT(" SERVICE_CONTROL_PAUSE received\n");
UpdateServiceStatus(SERVICE_PAUSED);
return ERROR_SUCCESS;
case SERVICE_CONTROL_CONTINUE:
DPRINT(" SERVICE_CONTROL_CONTINUE received\n");
UpdateServiceStatus(SERVICE_RUNNING);
return ERROR_SUCCESS;
case SERVICE_CONTROL_INTERROGATE:
DPRINT(" SERVICE_CONTROL_INTERROGATE received\n");
SetServiceStatus(ServiceStatusHandle,
&ServiceStatus);
return ERROR_SUCCESS;
case SERVICE_CONTROL_SHUTDOWN:
DPRINT(" SERVICE_CONTROL_SHUTDOWN received\n");
Close(CTRL_CLOSE_EVENT);
UpdateServiceStatus(SERVICE_STOPPED);
return ERROR_SUCCESS;
default :
DPRINT1(" Control %lu received\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
}
static
VOID
CALLBACK
ServiceMain(DWORD argc,
LPWSTR *argv)
{
DWORD dwError;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
DPRINT("ServiceMain() called\n");
ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
ServiceControlHandler,
NULL);
if (!ServiceStatusHandle)
{
dwError = GetLastError();
DPRINT1("RegisterServiceCtrlHandlerW() failed! (Error %lu)\n", dwError);
return;
}
UpdateServiceStatus(SERVICE_START_PENDING);
dwError = ServiceInit();
if (dwError != ERROR_SUCCESS)
{
DPRINT("Service stopped (dwError: %lu\n", dwError);
UpdateServiceStatus(SERVICE_START_PENDING);
}
else
{
DPRINT("Service started\n");
UpdateServiceStatus(SERVICE_RUNNING);
}
DPRINT("ServiceMain() done\n");
}
/*This Function is called repeatedly by mixer thread.
*This functions fetches FilteredBuffer from Every ClientStream Stucture
*and mixes them in oder to feed player thread*/
void
MixAndFill(MixerEngine * mixer,
int buffer)
{
while(WaitForSingleObject(mixer->newStreamEvent,
100) != 0)
{
if(mixer->dead)
return;
}
/*Master Stream's Datatype is signed int,unsigned int or float when masterdatatype =0,1 and 2 respectively*/
if(mixer->masterdatatype == 0)
{
switch(mixer->masterbitspersample)
{
case 8:
MixS8(mixer,buffer);
break;
case 16:
MixS16(mixer,buffer);
break;
case 32:
MixS32(mixer,buffer);
break;
case 64:
MixS64(mixer,buffer);
break;
}
}
else if (mixer->masterdatatype == 1)
{
switch(mixer->masterbitspersample)
{
case 8:
MixU8(mixer,buffer);
break;
case 16:
MixU16(mixer,buffer);
break;
case 32:
MixU32(mixer,buffer);
break;
case 64:
MixU64(mixer,buffer);
break;
}
}
else if(mixer->masterdatatype == 2)
{
switch(mixer->masterbitspersample)
{
case 32:
MixFL32(mixer,buffer);
break;
case 64:
MixFL64(mixer,buffer);
break;
}
}
}
/*Frees the Buffer Created in mixer thread*/
void FreeBuffer()
{
HeapFree(GetProcessHeap(),
0,
pengine->masterbuf[pengine->playcurrent]);
pengine->masterbuf[pengine->playcurrent] = NULL;
}
/*Plays Master buffer pengine->masterbuf[pengine->playcurrent]*/
void PlayBuffer(MixerEngine * mixer,
int buffer)
{
SP_DEVICE_INTERFACE_DATA InterfaceData;
SP_DEVINFO_DATA DeviceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA DetailData;
HDEVINFO DeviceHandle;
PKSDATAFORMAT DataFormat;
PWAVEFORMATEXTENSIBLE WaveFormat;
PKSPIN_CONNECT PinConnect;
KSSTATE State;
DWORD Length;
BOOL Result;
NTSTATUS Status;
if(mixer->masterbuf[buffer])
{
//
// Get a handle to KS Audio Interfaces
//
DeviceHandle = SetupDiGetClassDevs(&CategoryGuid,
NULL,
NULL,
DIGCF_DEVICEINTERFACE |DIGCF_PRESENT);
//
// Enumerate the first interface
//
InterfaceData.cbSize = sizeof(InterfaceData);
InterfaceData.Reserved = 0;
Result = SetupDiEnumDeviceInterfaces(DeviceHandle,
NULL,
&CategoryGuid,
1,
&InterfaceData);
//
// 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);
//
// Open a handle to the device
//
mixer->FilterHandle = CreateFile(DetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
//
// 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
//
DataFormat->Flags = 0;
DataFormat->Reserved = 0;
DataFormat->MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
if(mixer->masterdatatype == 0 || mixer->masterdatatype == 1)
DataFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
else
DataFormat->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
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;
if(mixer->masterdatatype == 0 || mixer->masterdatatype == 1)
WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
else
WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
//
// Create the pin
//
Status = KsCreatePin(mixer->FilterHandle, PinConnect, GENERIC_READ|GENERIC_WRITE, &(mixer->PinHandle));
Length = mixer->masterfreq * mixer->masterchannels * mixer->masterbitspersample / 8;
//
// Create and fill out the KS Stream Packet
//
mixer->Packet = (PKSSTREAM_HEADER)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(KSSTREAM_HEADER));
mixer->Packet->Data = mixer->masterbuf[buffer];
mixer->Packet->FrameExtent = mixer->bytes_to_play;
mixer->Packet->DataUsed = mixer->bytes_to_play;
mixer->Packet->Size = sizeof(KSSTREAM_HEADER);
mixer->Packet->PresentationTime.Numerator = 1;
mixer->Packet->PresentationTime.Denominator = 1;
//
// Setup a KS Property to change the state
//
mixer->Property = (PKSPROPERTY)HeapAlloc(GetProcessHeap(), 0, sizeof(KSPROPERTY));
mixer->Property->Set = KSPROPSETID_Connection;
mixer->Property->Id = KSPROPERTY_CONNECTION_STATE;
mixer->Property->Flags = KSPROPERTY_TYPE_SET;
//
// Change the state to run
//
State = KSSTATE_RUN;
DeviceIoControl(mixer->PinHandle,
IOCTL_KS_PROPERTY,
mixer->Property,
sizeof(KSPROPERTY),
&State,
sizeof(State),
&Length,
NULL);
DeviceIoControl(mixer->PinHandle,
IOCTL_KS_WRITE_STREAM,
NULL,
0,
mixer->Packet,
mixer->Packet->Size,
&Length,
NULL);
State = KSSTATE_STOP;
DeviceIoControl(mixer->PinHandle,
IOCTL_KS_PROPERTY,
mixer->Property,
sizeof(KSPROPERTY),
&State,
sizeof(State),
&Length,
NULL);
CloseHandle(mixer->PinHandle);
CloseHandle(mixer->FilterHandle);
}
}
/*Thread Routine For Mixer Thread*/
DWORD WINAPI RunMixerThread(LPVOID param)
{
MixerEngine * mixer = (MixerEngine *) param;
SetEvent(mixer->played);
while(TRUE)
{
while(WaitForSingleObject(mixer->played,
100)!=0)
{
if(mixer->dead)
break;
}
if(mixer->dead)
break;
MixAndFill(mixer,
1-mixer->playcurrent);
SetEvent(mixer->filled);
}
return 0;
}
/*Thread Routine For Player Thread*/
DWORD WINAPI RunPlayerThread(LPVOID param)
{
MixerEngine * mixer = (MixerEngine *) param;
while(1)
{
while(WaitForSingleObject(mixer->filled,
100)!=0)
{
if(mixer->dead)
break;
}
if(mixer->dead)
break;
SetEvent(mixer->played);
PlayBuffer(mixer,
mixer->playcurrent);
FreeBuffer();
mixer->playcurrent=1-mixer->playcurrent;
}
return 0;
}
/*Create Mixer Thread*/
void SpawnMixerThread(MixerEngine * mixer)
{
DWORD dwID;
mixer->mixerthread=CreateThread(NULL,
0,
RunMixerThread,
pengine,
0,
&dwID);
}
/*Create Player Thread*/
void SpawnPlayerThread(MixerEngine * mixer)
{
DWORD dwID;
mixer->playerthread=CreateThread(NULL,
0,
RunPlayerThread,
pengine,
0,
&dwID);
}
/*Create RPC Thread*/
void SpawnRPCThread(MixerEngine * mixer)
{
DWORD dwID;
mixer->rpcthread=CreateThread(NULL,
0,
RunRPCThread,
pengine,
0,
&dwID);
}
void ShutdownRPC(void)
{
RPC_STATUS status;
status = RpcMgmtStopServerListening(NULL);
if (status)
{
exit(status);
}
status = RpcServerUnregisterIf(NULL, NULL, FALSE);
if (status)
{
exit(status);
}
}
/*This Functions Kills the application, in any condition*/
static BOOL WINAPI Close ( DWORD dwCtrlType )
{
pengine->dead=1;
WaitForSingleObject(pengine->mixerthread,
INFINITE);
WaitForSingleObject(pengine->playerthread,
INFINITE);
ShutdownRPC();
WaitForSingleObject(pengine->rpcthread,INFINITE);
CloseHandle(pengine->mixerthread);
CloseHandle(pengine->playerthread);
CloseHandle(pengine->rpcthread);
return TRUE;
}
INT wmain(int argc, char *argv[])
{
INT RetCode = 0;
/*For Temporary Debugging purpose, If there is any argument it acts as simple command line app,otherwise it is a NTSERVICE*/
if(argc==1)
{
StartServiceCtrlDispatcher(ServiceTable);
}
else
{
pengine=&engine;
/*Later these will be loaded from a Conf file*/
pengine->mastervolume=1000;
pengine->mute=FALSE;
pengine->dead=0;
pengine->streamidpool=0;
pengine->playcurrent=1;
pengine->masterbuf[0] = NULL;
pengine->masterbuf[1] = NULL;
pengine->played=CreateEvent(NULL,
FALSE,
FALSE,
NULL);
pengine->filled=CreateEvent(NULL,
FALSE,
FALSE,
NULL);
pengine->newStreamEvent=CreateEvent(NULL,
TRUE,
FALSE,
NULL);
SetConsoleCtrlHandler(Close,
TRUE);
SpawnMixerThread(pengine);
SpawnPlayerThread(pengine);
SpawnRPCThread(pengine);
WaitForSingleObject(pengine->mixerthread,
INFINITE);
WaitForSingleObject(pengine->playerthread,
INFINITE);
WaitForSingleObject(pengine->rpcthread,INFINITE);
}
CloseHandle(pengine->mixerthread);
CloseHandle(pengine->playerthread);
CloseHandle(pengine->rpcthread);
return RetCode;
}
static DWORD
ServiceInit(VOID)
{
pengine=&engine;
/*Later these will be loaded from a Conf file*/
pengine->mastervolume=1000;
pengine->mute=FALSE;
pengine->dead=0;
pengine->streamidpool=0;
pengine->playcurrent=1;
pengine->masterbuf[0] = NULL;
pengine->masterbuf[1] = NULL;
pengine->played=CreateEvent(NULL,FALSE,FALSE,NULL);
pengine->filled=CreateEvent(NULL,FALSE,FALSE,NULL);
pengine->newStreamEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
SetConsoleCtrlHandler(Close,TRUE);
SpawnMixerThread(pengine);
SpawnPlayerThread(pengine);
SpawnRPCThread(pengine);
return ERROR_SUCCESS;
}

View File

@@ -0,0 +1,155 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: services/audsrv/audsrv.h
* PURPOSE: Audio Service
* COPYRIGHT: Copyright 2011 Neeraj Yadav
*/
#ifndef __AUDSRV_H__
#define __AUDSRV_H__
#define NDEBUG
#define WIN32_NO_STATUS
#include <windows.h>
#include <wincon.h>
#include <memory.h>
#include <mmsystem.h>
#include <stdio.h>
#include <math.h>
#include <setupapi.h>
#include <ndk/ntndk.h>
#include <ks.h>
#include <ksmedia.h>
#include <ks.h>
#include <debug.h>
#include "audsrvrpc_s.h"
typedef struct ServerStream
{
long streamid;
int volume;
LONG freq;
int bitspersample;
/*0=signed int,1=unsigned int,2=float*/
int datatype;
int channels;
/*Standard channelmasks from WINAPI/ksmeida.h*/
ULONG channelmask;
/*Balance from -1.0 to 1.0*/
float balance;
/*state cycle 0->buffer write -> 1 -> filtering -> 2 ->playback -> 0*/
char state;
/*This buffer is filled by the client using RPC calls*/
PVOID genuinebuf;
int length_genuine;
/*This Buffer is filled by Stream-Specific Server Thread, This Buffer's matches masterbuffer specifications*/
PVOID filteredbuf;
int length_filtered;
/*These values must be filled by Stream-Specific Server Thread,these are helful for Mixer Thread*/
PVOID minsamplevalue;
PVOID maxsamplevalue;
HANDLE stream_played_event;
HANDLE buffer_write_event;
HANDLE threadready;
HANDLE thread;
CRITICAL_SECTION CriticalSection;
struct ServerStream * next;
} ServerStream;
typedef struct MixerEngine
{
/*Should be Initialized at Server Start*/
char dead;
long streamidpool;
HANDLE played;
HANDLE filled;
HANDLE newStreamEvent;
HANDLE mixerthread;
HANDLE playerthread;
HANDLE rpcthread;
int playcurrent;
/*Should be Initialized at Server Start from configuration file,Currently there is no configuration file so initialized to a fixed value at start*/
int mastervolume;
BOOL mute;
/*Should be Initialized before playing First Stream*/
long masterfreq;
int masterchannels;
unsigned long masterchannelmask;
int masterbitspersample;
int masterdatatype;
PVOID masterbuf[2];
/*Currently don't know the future of following variables*/
long bytes_to_play;
HANDLE FilterHandle;
HANDLE PinHandle;
PKSPROPERTY Property;
PKSSTREAM_HEADER Packet;
ServerStream * serverstreamlist;
} MixerEngine;
extern MixerEngine engine,*pengine;
/* rpc.c */
DWORD WINAPI RunRPCThread(LPVOID lpParameter);
/* audsrv.c*/
void MixAndFill(MixerEngine * mixer,
int buffer);
void PlayBuffer(MixerEngine * mixer,
int buffer);
/*stream.c*/
long GetNewStreamID();
long AddStream(LONG frequency,
int channels,
int bitspersample,
int datatype,
ULONG channelmask,
int volume,
int mute,
float balance);
long WriteBuffer(LONG streamid,
LONG length,
char * buffer);
/*mixer.c*/
void * MixS8(MixerEngine * mixer,
int buffer);
void * MixS16(MixerEngine * mixer,
int buffer);
void * MixS32(MixerEngine * mixer,
int buffer);
void * MixS64(MixerEngine * mixer,
int buffer);
void * MixU8(MixerEngine * mixer,
int buffer);
void * MixU16(MixerEngine * mixer,
int buffer);
void * MixU32(MixerEngine * mixer,
int buffer);
void * MixU64(MixerEngine * mixer,
int buffer);
void * MixFL32(MixerEngine * mixer,
int buffer);
void * MixFL64(MixerEngine * mixer,
int buffer);
#endif /* __AUDSRV_H__ */

View File

@@ -0,0 +1,4 @@
#define REACTOS_STR_FILE_DESCRIPTION "Audio Server\0"
#define REACTOS_STR_INTERNAL_NAME "Audsrv\0"
#define REACTOS_STR_ORIGINAL_FILENAME "Audsrv.exe\0"
#include <reactos/version.rc>

View File

@@ -0,0 +1,135 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: services/mixer.c
* PURPOSE: Audio Server
* COPYRIGHT: Copyright 2011 Neeraj Yadav
*/
#include "audsrv.h"
void * MixS8(MixerEngine * mixer,
int buffer)
{
return NULL;
}
/*Filter Should ensure that sample data is divided equally on both side of Analog-Zero Sample value[0 for signed data,maxattainablevalue/2 for unsigned]*/
void * MixS16(MixerEngine * mixer,
int buffer)
{
int length=0;
short minsamplevalue,maxsamplevalue;
float coefficient = 1.0;
int streamcount = 0,i;
PSHORT localsinkbuf,localsrcbuf;
ServerStream * stream = mixer->serverstreamlist;
/*TODOAssert(mixer->serverstreamlist == NULL)*/
/*Find the Longest Buffer within all ServerStreams*/
length = stream->length_filtered;
while(stream->next != NULL)
{
if(stream->length_filtered > length && stream->state == 2 )
length = stream->length_filtered;
stream = stream->next;
}
/*Allocate MasterBuffer*/
mixer->masterbuf[buffer] = HeapAlloc(GetProcessHeap(), 0, length);
localsinkbuf = mixer->masterbuf[buffer];
mixer->bytes_to_play = length;
/*Perform Actual Mixing*/
stream = mixer->serverstreamlist;
minsamplevalue = 0;
maxsamplevalue = 0;
while(stream != NULL)
{
EnterCriticalSection(&(stream->CriticalSection));
if(stream->state == 2 && *(short *) stream->minsamplevalue != 0 && *(short *) stream->minsamplevalue != 0)
{
coefficient = 1.0;
localsrcbuf = stream->filteredbuf;
if(minsamplevalue == 0)
minsamplevalue = *(short *) stream->minsamplevalue;
if(maxsamplevalue == 0)
maxsamplevalue = *(short *) stream->maxsamplevalue;
if( *(short *)stream->maxsamplevalue != maxsamplevalue ||
*(short *)stream->minsamplevalue != minsamplevalue )
{
if( (float) maxsamplevalue / (float)*(short *)stream->maxsamplevalue <
(float) minsamplevalue / (float)*(short *)stream->minsamplevalue )
coefficient = (float) maxsamplevalue / (float)*(short *)stream->maxsamplevalue;
else
coefficient = (float) minsamplevalue / (float)*(short *)stream->minsamplevalue;
}
for(i=0;i<stream->length_filtered/sizeof(short);i++)
{
localsinkbuf[i] = (short) (( (localsinkbuf[i] * streamcount) + ((short)((float) localsrcbuf[i] ) * coefficient) ) / (streamcount +1));
}
stream->state = 0;
HeapFree(GetProcessHeap(),
0,
stream->filteredbuf);
SetEvent(stream->stream_played_event);
}
LeaveCriticalSection(&(stream->CriticalSection));
streamcount++;
stream = stream->next;
}
return NULL;
}
void * MixS32(MixerEngine * mixer,
int buffer)
{
return NULL;
}
void * MixS64(MixerEngine * mixer,
int buffer)
{
return NULL;
}
void * MixU8(MixerEngine * mixer,
int buffer)
{
return NULL;
}
void * MixU16(MixerEngine * mixer,
int buffer)
{
return NULL;
}
void * MixU32(MixerEngine * mixer,
int buffer)
{
return NULL;
}
void * MixU64(MixerEngine * mixer,
int buffer)
{
return NULL;
}
void * MixFL32(MixerEngine * mixer,
int buffer)
{
return NULL;
}
void * MixFL64(MixerEngine * mixer,
int buffer)
{
return NULL;
}

105
base/services/audsrv/rpc.c Normal file
View File

@@ -0,0 +1,105 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: services/audsrv/rpc.c
* PURPOSE: Audio Server
* COPYRIGHT: Copyright 2011 Neeraj Yadav
*/
#include "audsrv.h"
LIST_ENTRY LogHandleListHead;
/*RPC Listener Thread,Returns values less than 0 in failures*/
DWORD WINAPI RunRPCThread(LPVOID lpParameter)
{
RPC_STATUS Status;
InitializeListHead(&LogHandleListHead);
Status = RpcServerUseProtseqEp(L"ncacn_np",
20,
L"\\pipe\\audsrv",
NULL);
if (Status != RPC_S_OK)
{
return -1;
}
Status = RpcServerRegisterIfEx(audsrv_v0_0_s_ifspec,
NULL,
NULL,
0,
RPC_C_LISTEN_MAX_CALLS_DEFAULT,
NULL );
if (Status != RPC_S_OK)
{
return -2;
}
Status = RpcServerListen(1,
20,
FALSE);
if (Status != RPC_S_OK)
{
return -3;
}
return 0;
}
/*************************RPC Functions**********************************/
long AUDInitStream( IN RPC_BINDING_HANDLE hBinding,
LONG frequency,
int channels,
int bitspersample,
int datatype,
ULONG channelmask,
int volume,
int mute,
float balance )
{
long stream;
stream = AddStream(frequency,
channels,
bitspersample,
datatype,
channelmask,
volume,
mute,
balance);
if( stream != 0 )
{
/*ERROR*/
}
return stream;
}
long AUDPlayBuffer( IN RPC_BINDING_HANDLE hBinding,
LONG streamid,
LONG length,
char* buffer)
{
WriteBuffer(streamid,length,buffer);
return 0;
}
/*************************************************************************/
void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len)
{
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
}
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
HeapFree(GetProcessHeap(), 0, ptr);
}
void __RPC_USER IELF_HANDLE_rundown(AUDSRV_HANDLE LogHandle)
{
}

View File

@@ -0,0 +1,232 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: services/stream.c
* PURPOSE: Audio Server
* COPYRIGHT: Copyright 2011 Neeraj Yadav
*/
#include "audsrv.h"
long GetNewStreamID()
{
long streamid= pengine->streamidpool;
pengine->streamidpool += 1;
return streamid;
}
BOOL FilterAudio(LPVOID param)
{
ServerStream * localstream = (ServerStream *) param;
EnterCriticalSection(&(localstream->CriticalSection));
if(localstream->state == 1)
{
/*Fake Filter,Simply gives the genuine buffer as filtered buffer*/
/*minsamplevalue and maxsamplevalue must be calculated during filtering*/
/*Filter must ensure that all the samples are distributed evenly about 0 in case of signed samples*/
localstream->length_filtered = localstream->length_genuine;
localstream->filteredbuf = HeapAlloc(GetProcessHeap(),
0,
localstream->length_filtered);
memcpy(localstream->filteredbuf,localstream->genuinebuf,localstream->length_filtered);
HeapFree(GetProcessHeap(),
0,
localstream->genuinebuf);
*((int *)localstream->minsamplevalue) = -32766;
*((int *)localstream->maxsamplevalue) = 32766;
localstream->state = 2;
LeaveCriticalSection(&(localstream->CriticalSection));
return TRUE;
}
else
{
LeaveCriticalSection(&(localstream->CriticalSection));
return FALSE;
}
}
DWORD WINAPI RunStreamThread(LPVOID param)
{
ServerStream * localstream = (ServerStream *) param;
SetEvent(localstream->threadready);
while (TRUE)
{
if(FilterAudio(param) == TRUE )
WaitForSingleObject(localstream->stream_played_event,INFINITE);
}
/*Clean Stream's data*/
}
long AddStream(LONG frequency,
int channels,
int bitspersample,
int datatype,
ULONG channelmask,
int volume,
int mute,
float balance )
{
ServerStream * newstream,*localstream;
DWORD dwID;
/*Add Data to Linked list*/
localstream = pengine->serverstreamlist;
newstream = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(ServerStream));
if(newstream == NULL)
goto error;
if(volume < 0)
newstream->volume = 0;
else if (volume > 1000)
newstream->volume = 1000;
else
newstream->volume = volume;
if(volume < -1.0)
newstream->volume = -1.0;
else if (volume > 1.0)
newstream->volume = 1.0;
else
newstream->volume = volume;
newstream->freq = frequency; /*TODO frequency validation required*/
if(datatype==0 || datatype==1 || datatype==2)
newstream->datatype=datatype;
else
goto error;
if ((datatype==0 && (bitspersample == 8 || bitspersample == 16 || bitspersample == 32 || bitspersample == 64 )) ||
(datatype==1 && (bitspersample == 8 || bitspersample == 16 || bitspersample == 32 || bitspersample == 64)) ||
(datatype==2 && (bitspersample == 32 || bitspersample == 64)) )
newstream->bitspersample = bitspersample; /*TODO bitspersample validation*/
else
goto error;
newstream->channels = channels; /*TODO validation*/
newstream->channelmask = channelmask; /*TODO validation*/
newstream->state = 0;
newstream->length_genuine = 0;
newstream->genuinebuf = NULL;
newstream->length_filtered = 0;
newstream->filteredbuf = NULL;
newstream->minsamplevalue = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
bitspersample/8);
newstream->maxsamplevalue = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
bitspersample/8);
newstream->next = NULL;
newstream->stream_played_event = CreateEvent(NULL,
FALSE,
FALSE,
NULL);
newstream->buffer_write_event = CreateEvent(NULL,
FALSE,
FALSE,
NULL);
newstream->threadready = CreateEvent(NULL,
FALSE,
FALSE,
NULL);
if(newstream->stream_played_event == NULL || newstream->threadready == NULL)
goto error;
newstream->streamid=GetNewStreamID();
if (!InitializeCriticalSectionAndSpinCount(&(newstream->CriticalSection),
0x00000400) )
goto error;
newstream->thread=CreateThread(NULL,
0,
RunStreamThread,
newstream,
0,
&dwID);
if(newstream->thread == NULL)
goto error;
WaitForSingleObject(newstream->threadready,
INFINITE);
if(localstream == NULL)
{
pengine->serverstreamlist = newstream;
pengine->masterfreq=frequency;
pengine->masterchannels=channels;
pengine->masterchannelmask=channelmask;
pengine->masterbitspersample=bitspersample;
pengine->masterdatatype = datatype;
}
else
{
while(localstream->next != NULL)
localstream = localstream->next;
localstream->next = newstream;
}
SetEvent(pengine->newStreamEvent);
return newstream->streamid;
error:
HeapFree(GetProcessHeap(),
0,
newstream);
return 0;
}
long WriteBuffer(LONG streamid,
LONG length,
char * buffer)
{
ServerStream * localstream = pengine->serverstreamlist;
while(localstream!=NULL)
{
if(localstream->streamid == streamid) break;
localstream = localstream->next;
}
if(localstream == NULL)
return -1;
EnterCriticalSection(&(localstream->CriticalSection));
if(localstream->state == 0)
{
localstream->length_genuine = length;
localstream->genuinebuf = (PSHORT) HeapAlloc(GetProcessHeap(),
0,
length);
memcpy(localstream->genuinebuf,buffer,length);
localstream->state = 1;
}
LeaveCriticalSection(&(localstream->CriticalSection));
return 0;
}
/*Dont forget to clean ServerStream's minsamplevalue and maxsamplevalue while removing the stream*/
/*Delete Critical Section while cleaning Stream*/

View File

@@ -7,6 +7,7 @@ add_subdirectory(advapi32)
add_subdirectory(advpack)
add_subdirectory(atl)
add_subdirectory(authz)
add_subdirectory(audsrvapi)
add_subdirectory(avicap32)
add_subdirectory(avifil32)
add_subdirectory(batt)

View File

@@ -0,0 +1,22 @@
set_unicode()
include_directories(${REACTOS_BINARY_DIR}/include/reactos/idl)
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs)
spec2def(audsrvapi.dll audsrvapi.spec)
list(APPEND SOURCE
dllmain.c
audsrvapi.c
${CMAKE_CURRENT_BINARY_DIR}/audsrvapi.def)
add_library(audsrvapi SHARED ${SOURCE})
set_module_type(audsrvapi win32dll)
target_link_libraries(audsrvapi audsrvrpc uuid wine ${PSEH_LIB})
add_pch(audsrv ${CMAKE_CURRENT_SOURCE_DIR}/audsrv.h ${SOURCE})
add_importlibs(audsrvapi rpcrt4 ole32 oleaut32 user32 advapi32 msvcrt kernel32 ntdll)
add_cab_target(audsrvapi 1)
add_importlib_target(audsrvapi.spec)

View File

@@ -0,0 +1,203 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll\win32\audsrvapi\audsrvapi.c
* PURPOSE: Audio Server
* COPYRIGHT: Copyright 2011 Neeraj Yadav
*/
#include "audsrvapi.h"
#include <math.h>
/*All the wrappers for Remote Function should be here*/
int status = 0;
/*Initialize an audio stream
*Return -1 if callbacks are NULL pointers
*/
int
WINAPI
InitStream (ClientStream * clientstream,
LONG frequency,
int channels,
int bitspersample,
int datatype,
ULONG channelmask,
int volume,
int mute,
float balance)
{
long streamid;
if (clientstream == NULL )
return -1;
if (clientstream->callbacks.OpenComplete == NULL || clientstream->callbacks.BufferCopied == NULL || clientstream->callbacks.PlayComplete == NULL)
return -2;
/*Validity of all other data will be checked at server*/
/*Check Connection Status If not connected call Connect()*/
/*If connected Properly call the remote audsrv_initstream() function*/
RpcTryExcept
{
streamid = AUDInitStream (audsrv_v0_0_c_ifspec,
frequency,
channels,
bitspersample,
datatype,
channelmask,
volume,
mute,
balance);
if(streamid != 0)
clientstream->stream = streamid;
}
RpcExcept(1)
{
status = RpcExceptionCode();
}
RpcEndExcept
/*Analyse the return by the function*/
/*Currently Suppose the return is 0 and a valid streamid is returned*/
clientstream->ClientEventPool[0]=CreateEvent(NULL,
FALSE,
FALSE,
NULL);
clientstream->dead = 0;
return 0;
}
int
WINAPI
PlayAudio ( ClientStream * clientstream )
{
/******************************************/
int i =0;
PSHORT tempbuf;
/******************************************/
/*This is an ActiveScheduler*/
clientstream->callbacks.OpenComplete(0);
while(TRUE)
{
while(WaitForSingleObject(clientstream->ClientEventPool[0],
100)!=0)
{
if(clientstream->dead)
break;
}
if(clientstream->dead)
break;
/*Check Connection Status If not connected call Connect()*/
/*If connected Properly call the remote audsrv_play() function,This will be a blocking call, placing a dummy wait function here is a good idea.*/
tempbuf = (PSHORT) HeapAlloc(GetProcessHeap(),
0,
44100);
for(i = 0;i<22050;i+=2)
{
tempbuf[i+1] = tempbuf[i] = 0x7FFF * sin( i * 500 * 3.14 / clientstream->wavefreq);
}
RpcTryExcept
{
AUDPlayBuffer (audsrv_v0_0_c_ifspec,
clientstream->stream,
44100,
(char *)tempbuf);
}
RpcExcept(1)
{
status = RpcExceptionCode();
}
RpcEndExcept
HeapFree(GetProcessHeap(),
0,
tempbuf);
clientstream->callbacks.BufferCopied(0);
}
clientstream->callbacks.PlayComplete(0);
/*Audio Thread Ended*/
return 0;
}
int
WINAPI
StopAudio (ClientStream * clientstream )
{
/*Server Side termination is remaining*/
/*If connected Properly call the remote audsrv_stop() function*/
clientstream->dead = 1; /*Client Side termination*/
return 0;
}
int
WINAPI
Volume(ClientStream * clientstream,
int * volume )
{
return 0;
}
int
WINAPI
SetVolume(ClientStream * clientstream ,
const int newvolume)
{
return 0;
}
int
WINAPI
Write(ClientStream * clientstream ,
const char * aData)
{
if(clientstream->dead)
return -1;
SetEvent(clientstream->ClientEventPool[0]);
return 0;
}
int
WINAPI
SetBalance(ClientStream * clientstream ,
float balance)
{
return 0;
}
int
WINAPI
GetBalance(ClientStream * clientstream ,
float * balance)
{
return 0;
}
/******************************************************/
/* MIDL allocate and free */
/******************************************************/
void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
{
return(malloc(len));
}
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
free(ptr);
}

View File

@@ -0,0 +1,11 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll\win32\audsrvapi\audsrvapi.h
* PURPOSE: Audio Server
* COPYRIGHT: Copyright 2011 Neeraj Yadav
*/
#include "audsrvrpc_c.h"
#include <audsrv/audsrvapi.h>

View File

@@ -0,0 +1,8 @@
@ stdcall InitStream (ptr long long long long long long long long)
@ stdcall PlayAudio ( ptr);
@ stdcall StopAudio (ptr );
@ stdcall Volume(ptr ptr );
@ stdcall SetVolume(ptr long);
@ stdcall Write(ptr ptr);
@ stdcall SetBalance(ptr long);
@ stdcall GetBalance(ptr ptr);

View File

@@ -0,0 +1,57 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll\win32\audsrvapi\dllmain.c
* PURPOSE: Audio Server
* COPYRIGHT: Copyright 2011 Neeraj Yadav
*/
#include "audsrvapi.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
RPC_STATUS status;
unsigned short * pszStringBinding = NULL;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
status = RpcStringBindingComposeW(NULL,
L"ncacn_np",
NULL,
L"\\pipe\\audsrv",
NULL,
&pszStringBinding);
status = RpcBindingFromStringBindingW(pszStringBinding,
&audsrv_v0_0_c_ifspec);
if (status)
{
/*Connection Problem*/
}
status = RpcStringFree(&pszStringBinding);
if (status)
{
/*problem*/
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
status = RpcBindingFree(audsrv_v0_0_c_ifspec);
if (status == RPC_S_INVALID_BINDING)
OutputDebugStringA("Error Closing RPC Connection\n");
break;
}
return TRUE;
}

View File

@@ -1,3 +1,4 @@
add_subdirectory(audio_test)
add_subdirectory(audclient)
add_subdirectory(portcls)

View File

@@ -0,0 +1,11 @@
set_unicode(audclient yes)
add_executable(audclient
audclient.c)
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/audsrv)
set_module_type(audclient win32cui)
add_importlibs(audclient audsrvapi advapi32 user32 ksuser setupapi msvcrt kernel32)
add_cab_target(audclient 1)
add_dependencies(audclient audsrvapi)

View File

@@ -0,0 +1,94 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: services/audsrv.c
* PURPOSE: Audio Server
* COPYRIGHT: Copyright 2011 Neeraj Yadav
*/
#define WIN32_NO_STATUS
#define _KSDDK_
#include <audsrvapi.h>
#include <stdio.h>
#include <debug.h>
#include <windows.h>
#include <winbase.h>
void OpenComplete (int error );
void BufferCopied (int error );
void PlayComplete (int error );
ClientStream clientstream = {0,
0,
{NULL},
{OpenComplete,
BufferCopied,
PlayComplete}
};
DWORD WINAPI RunAudioThread(LPVOID param)
{
ClientStream * localstream = (ClientStream *) param;
PlayAudio(localstream);
return 0;
}
void OpenComplete (int error )
{
/*Copy First Buffer and write*/
Write(&clientstream,
"HELLO_RANDOM_STRING");
}
void BufferCopied (int error )
{
Write(&clientstream,
"HELLO_RANDOM_STRING");
}
void PlayComplete (int error )
{
}
int
__cdecl
wmain(int argc,
char* argv[])
{
int error;
DWORD dwID;
HANDLE audiothread = NULL;
char input='\0';
printf("ReactOS Audio Mixer Sample Client.Enter 'a' to Stop.\nPlease Enter the frequency of the sinusoidal wave [Hz] : ");
scanf("%ld",&(clientstream.wavefreq));
/*[out]HANDLE * streamhandle,[in] long frequency,[in] int number of channels,[in] int bitspersample,[in]ULONG channelmask,[in] int volume,[in] int mute,[in] float balance*/
error = InitStream ( &clientstream ,
44100 ,
2 ,
16 ,
0,
KSAUDIO_SPEAKER_STEREO ,
1000 ,
0,
0.0 );
if ( error )
{
goto error;
}
else
{
audiothread = CreateThread(NULL,0,RunAudioThread,&clientstream,0,&dwID);
}
while ( input != 'a' )
scanf("%c",&input);
StopAudio(&clientstream);
WaitForSingleObject(audiothread,INFINITE);
return 0;
error:
return -1;
}

View File

@@ -42,7 +42,8 @@ TestKs()
SP_DEVINFO_DATA DeviceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA DetailData;
HDEVINFO DeviceHandle;
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
PKSDATAFORMAT DataFormat;
PWAVEFORMATEXTENSIBLE WaveFormat;
PKSPIN_CONNECT PinConnect;
PKSSTREAM_HEADER Packet;
PKSPROPERTY Property;
@@ -61,7 +62,7 @@ TestKs()
DeviceHandle = SetupDiGetClassDevs(&CategoryGuid,
NULL,
NULL,
DIGCF_DEVICEINTERFACE); //DIGCF_PRESENT
DIGCF_DEVICEINTERFACE |DIGCF_PRESENT);
printf("DeviceHandle %p\n", DeviceHandle);
@@ -83,7 +84,7 @@ TestKs()
//
Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR);
DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(),
0,
HEAP_ZERO_MEMORY,
Length);
DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
DeviceData.cbSize = sizeof(DeviceData);
@@ -118,14 +119,15 @@ TestKs()
//
// Allocate a KS Pin Connection Request Structure
//
Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX);
printf("Length %ld KSPIN %u DATAFORMAT %u\n", Length, sizeof(KSPIN_CONNECT), sizeof(KSDATAFORMAT_WAVEFORMATEX));
PinConnect = (PKSPIN_CONNECT)HeapAlloc(GetProcessHeap(), 0, Length);
DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)(PinConnect + 1);
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;
@@ -140,23 +142,30 @@ TestKs()
//
// Setup the KS Data Format Information
//
DataFormat->WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
DataFormat->WaveFormatEx.nChannels = 2;
DataFormat->WaveFormatEx.nSamplesPerSec = 48000;
DataFormat->WaveFormatEx.nBlockAlign = 4;
DataFormat->WaveFormatEx.nAvgBytesPerSec = 48000 * 4;
DataFormat->WaveFormatEx.wBitsPerSample = 16;
DataFormat->WaveFormatEx.cbSize = 0;
DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) +
sizeof(WAVEFORMATEX);
DataFormat->DataFormat.Flags = KSDATAFORMAT_ATTRIBUTES;
DataFormat->DataFormat.Reserved = 0;
DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
DataFormat->DataFormat.SampleSize = 4;
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 = 4;
DataFormat->FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEXTENSIBLE);
WaveFormat->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
WaveFormat->Format.nChannels = 2;
WaveFormat->Format.nSamplesPerSec = 48000;
WaveFormat->Format.nBlockAlign = 4;
WaveFormat->Format.nAvgBytesPerSec = WaveFormat->Format.nSamplesPerSec * WaveFormat->Format.nBlockAlign;
WaveFormat->Format.wBitsPerSample = 16;
WaveFormat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
WaveFormat->Samples.wValidBitsPerSample = 16;
WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
printf("Creating pin\n");
//
// Create the pin
//
Status = KsCreatePin(FilterHandle, PinConnect, GENERIC_WRITE, &PinHandle);

View File

@@ -348,6 +348,25 @@ typedef struct {
WAVEFORMATEX WaveFormatEx;
} KSDATAFORMAT_WAVEFORMATEX, *PKSDATAFORMAT_WAVEFORMATEX;
#ifndef _WAVEFORMATEXTENSIBLE_
#define _WAVEFORMATEXTENSIBLE_
typedef struct {
WAVEFORMATEX Format;
union
{
WORD wValidBitsPerSample;
WORD wSamplesPerBlock;
WORD wReserved;
}Samples;
DWORD dwChannelMask;
GUID SubFormat;
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
#endif
#if !defined(WAVE_FORMAT_EXTENSIBLE)
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
#endif
typedef struct {
ULONG Flags;
ULONG Control;
@@ -734,4 +753,50 @@ typedef struct
ULONG ChannelMask;
} KSDATARANGE_MUSIC, *PKSDATARANGE_MUSIC;
#ifndef _SPEAKER_POSITIONS_
#define _SPEAKER_POSITIONS_
#define SPEAKER_FRONT_LEFT 0x1
#define SPEAKER_FRONT_RIGHT 0x2
#define SPEAKER_FRONT_CENTER 0x4
#define SPEAKER_LOW_FREQUENCY 0x8
#define SPEAKER_BACK_LEFT 0x10
#define SPEAKER_BACK_RIGHT 0x20
#define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
#define SPEAKER_BACK_CENTER 0x100
#define SPEAKER_SIDE_LEFT 0x200
#define SPEAKER_SIDE_RIGHT 0x400
#define SPEAKER_TOP_CENTER 0x800
#define SPEAKER_TOP_FRONT_LEFT 0x1000
#define SPEAKER_TOP_FRONT_CENTER 0x2000
#define SPEAKER_TOP_FRONT_RIGHT 0x4000
#define SPEAKER_TOP_BACK_LEFT 0x8000
#define SPEAKER_TOP_BACK_CENTER 0x10000
#define SPEAKER_TOP_BACK_RIGHT 0x20000
#define SPEAKER_RESERVED 0x7FFC0000
#define SPEAKER_ALL 0x80000000
#endif
#if (NTDDI_VERSION >= NTDDI_WINXP)
#define KSAUDIO_SPEAKER_DIRECTOUT 0
#endif
#define KSAUDIO_SPEAKER_MONO (SPEAKER_FRONT_CENTER)
#define KSAUDIO_SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)
#define KSAUDIO_SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
#define KSAUDIO_SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER)
#define KSAUDIO_SPEAKER_5POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \
SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
#define KSAUDIO_SPEAKER_7POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \
SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | \
SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER)
#endif

View File

@@ -2,6 +2,7 @@
include_directories(.)
add_rpc_library(eventlogrpc eventlogrpc.idl)
add_rpc_library(audsrvrpc audsrvrpc.idl)
add_rpc_library(lsarpc lsa.idl)
add_rpc_library(svcctlrpc svcctl.idl)
add_rpc_library(wlansvcrpc wlansvc.idl)

View File

@@ -0,0 +1,6 @@
[
implicit_handle(handle_t bindhandle), strict_context_handle
]
interface audsrv
{
}

View File

@@ -0,0 +1,44 @@
/*
* Event Log RPC interface definition
*/
#include <wtypes.idl>
cpp_quote("#if !defined(__AUDSRV_H__) ")
typedef long NTSTATUS;
cpp_quote("#endif")
typedef [range(0, 0x0007FFFF)] unsigned long RULONG;
typedef struct _RPC_STRING {
USHORT Length;
USHORT MaximumLength;
[size_is(MaximumLength), length_is(Length)] LPSTR Buffer;
} RPC_STRING, *PRPC_STRING;
typedef [context_handle] PVOID AUDSRV_HANDLE;
typedef AUDSRV_HANDLE *PAUDSRV_HANDLE;
typedef [handle, unique] LPWSTR AUDSRV_HANDLE_W;
typedef [handle, unique] LPSTR AUDSRV_HANDLE_A;
typedef struct _RPC_CLIENT_ID {
DWORD UniqueProcess;
DWORD UniqueThread;
} RPC_CLIENT_ID, *PRPC_CLIENT_ID;
[
uuid(F4CB5F3D-84CC-4BFF-BB16-1397896E3A38),
version(0.0),
pointer_default(unique)
#ifndef __midl
,explicit_handle
#endif
]
interface audsrv
{
long AUDInitStream([in] handle_t h1,[in]LONG frequency,[in]int channels,[in]int bitspersample,[in]int datatype,[in] ULONG channelmask,[in]int volume,[in]int mute,[in]float balance);
long AUDPlayBuffer([in] handle_t h1,[in]LONG streamid,[in]LONG length,[in, size_is(length)]char* buffer);
}

View File

@@ -0,0 +1,72 @@
#ifndef _AUDSRVAPI_H
#define _AUDSRVAPI_H
#include <windows.h>
#include <ks.h>
#include <ksmedia.h>
#include <stdio.h>
/********************Structures*********************/
typedef struct CallBacks
{
void (*OpenComplete) (int error );
void (*BufferCopied) (int error );
void (*PlayComplete) (int error );
} CallBacks;
typedef struct ClientStream
{
long stream;
int dead;
HANDLE ClientEventPool[1];
struct CallBacks callbacks;
/*Just for the time being when we dont have any audio source*/
long wavefreq;
} ClientStream;
/********************API Functions******************/
int
WINAPI
InitStream (ClientStream * clientstream,
LONG frequency,
int channels,
int bitspersample,
int datatype, /*0=signed int,1=unsigned int,2=float*/
ULONG channelmask,
int volume,
int mute,
float balance);
int
WINAPI
PlayAudio ( ClientStream * clientstream);
int
WINAPI
StopAudio (ClientStream * clientstream );
int
WINAPI
Volume(ClientStream * clientstream,
int * volume );
int
WINAPI
SetVolume(ClientStream * clientstream ,
const int newvolume);
int
WINAPI
Write(ClientStream * clientstream ,
const char * aData);
int
WINAPI
SetBalance(ClientStream * clientstream ,
float balance);
int
WINAPI
GetBalance(ClientStream * clientstream ,
float * balance);
#endif