- Partly implement IMasterClock

- Implement IAllocatorMXF for IPortPinDMus
- Implement rendering midi streams using IMXF object
- WIP, not tested yet

svn path=/trunk/; revision=40837
This commit is contained in:
Johannes Anderwald 2009-05-08 13:02:08 +00:00
parent 97126c89e0
commit 71c299cdfa
3 changed files with 382 additions and 12 deletions

View file

@ -65,13 +65,15 @@ const GUID KS_CATEGORY_TOPOLOGY = {0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40
const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 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}};
const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
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 IID_IAllocatorMXF = {0xa5f0d62cL, 0xb30f, 0x11d2, {0xb7, 0xa3, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
///
/// undocumented guids

View file

@ -678,4 +678,6 @@ DECLARE_INTERFACE_(IDmaChannelInit, IUnknown)
IN PDEVICE_OBJECT DeviceObject) PURE;
};
#undef INTERFACE
#endif

View file

@ -14,6 +14,9 @@ typedef struct
{
IPortPinDMusVtbl *lpVtbl;
IServiceSinkVtbl *lpVtblServiceSink;
IMasterClockVtbl *lpVtblMasterClock;
IAllocatorMXFVtbl *lpVtblAllocatorMXF;
IMXFVtbl *lpVtblMXF;
LONG ref;
IPortDMus * Port;
@ -23,6 +26,11 @@ typedef struct
PSERVICEGROUP ServiceGroup;
PMXF Mxf;
ULONGLONG SchedulePreFetch;
NPAGED_LOOKASIDE_LIST LookAsideEvent;
NPAGED_LOOKASIDE_LIST LookAsideBuffer;
PMINIPORTMIDI MidiMiniport;
PMINIPORTMIDISTREAM MidiStream;
@ -39,8 +47,15 @@ typedef struct
ULONG PreCompleted;
ULONG PostCompleted;
ULONG LastTag;
}IPortPinDMusImpl;
typedef struct
{
DMUS_KERNEL_EVENT Event;
PVOID Tag;
}DMUS_KERNEL_EVENT_WITH_TAG, *PDMUS_KERNEL_EVENT_WITH_TAG;
typedef struct
{
@ -49,10 +64,263 @@ typedef struct
KSSTATE State;
}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
//==================================================================================================================================
static
NTSTATUS
NTAPI
IPortDMus_fnProcessNewIrp(
IPortPinDMusImpl * This);
IMasterClock_fnQueryInterface(
IMasterClock* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblMasterClock);
DPRINT("IServiceSink_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtblServiceSink;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
static
ULONG
NTAPI
IMasterClock_fnAddRef(
IMasterClock* iface)
{
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblMasterClock);
DPRINT("IServiceSink_fnAddRef entered\n");
return InterlockedIncrement(&This->ref);
}
static
ULONG
NTAPI
IMasterClock_fnRelease(
IMasterClock* iface)
{
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblMasterClock);
InterlockedDecrement(&This->ref);
DPRINT("IServiceSink_fnRelease entered %u\n", This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
static
NTSTATUS
NTAPI
IMasterClock_fnGetTime(
IMasterClock* iface,
OUT REFERENCE_TIME *prtTime)
{
UNIMPLEMENTED
return STATUS_SUCCESS;
}
static IMasterClockVtbl vt_IMasterClock =
{
IMasterClock_fnQueryInterface,
IMasterClock_fnAddRef,
IMasterClock_fnRelease,
IMasterClock_fnGetTime
};
//==================================================================================================================================
static
NTSTATUS
NTAPI
IAllocatorMXF_fnQueryInterface(
IAllocatorMXF* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
DPRINT("IServiceSink_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IAllocatorMXF) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtblServiceSink;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
static
ULONG
NTAPI
IAllocatorMXF_fnAddRef(
IAllocatorMXF* iface)
{
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
DPRINT("IServiceSink_fnAddRef entered\n");
return InterlockedIncrement(&This->ref);
}
static
ULONG
NTAPI
IAllocatorMXF_fnRelease(
IAllocatorMXF* iface)
{
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
InterlockedDecrement(&This->ref);
DPRINT("IServiceSink_fnRelease entered %u\n", This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
static
NTSTATUS
NTAPI
IAllocatorMXF_fnGetMessage(
IAllocatorMXF* iface,
OUT PDMUS_KERNEL_EVENT * ppDMKEvt)
{
PVOID Buffer;
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
Buffer = ExAllocateFromNPagedLookasideList(&This->LookAsideEvent);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
*ppDMKEvt = Buffer;
RtlZeroMemory(Buffer, sizeof(DMUS_KERNEL_EVENT));
return STATUS_SUCCESS;
}
static
USHORT
NTAPI
IAllocatorMXF_fnGetBufferSize(
IAllocatorMXF* iface)
{
return PAGE_SIZE;
}
static
NTSTATUS
NTAPI
IAllocatorMXF_fnGetBuffer(
IAllocatorMXF* iface,
OUT PBYTE * ppBuffer)
{
PVOID Buffer;
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
Buffer = ExAllocateFromNPagedLookasideList(&This->LookAsideBuffer);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
*ppBuffer = Buffer;
RtlZeroMemory(Buffer, PAGE_SIZE);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
IAllocatorMXF_fnPutBuffer(
IAllocatorMXF* iface,
IN PBYTE pBuffer)
{
PDMUS_KERNEL_EVENT_WITH_TAG Event = (PDMUS_KERNEL_EVENT_WITH_TAG)pBuffer;
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
This->IrpQueue->lpVtbl->ReleaseMappingWithTag(This->IrpQueue, Event->Tag);
ExFreeToNPagedLookasideList(&This->LookAsideBuffer, pBuffer);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
IAllocatorMXF_fnSetState(
IAllocatorMXF* iface,
IN KSSTATE State)
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
static
NTSTATUS
NTAPI
IAllocatorMXF_fnPutMessage(
IAllocatorMXF* iface,
IN PDMUS_KERNEL_EVENT pDMKEvt)
{
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
ExFreeToNPagedLookasideList(&This->LookAsideEvent, pDMKEvt);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
IAllocatorMXF_fnConnectOutput(
IAllocatorMXF* iface,
IN PMXF sinkMXF)
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
static
NTSTATUS
NTAPI
IAllocatorMXF_fnDisconnectOutput(
IAllocatorMXF* iface,
IN PMXF sinkMXF)
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
static IAllocatorMXFVtbl vt_IAllocatorMXF =
{
IAllocatorMXF_fnQueryInterface,
IAllocatorMXF_fnAddRef,
IAllocatorMXF_fnRelease,
IAllocatorMXF_fnSetState,
IAllocatorMXF_fnPutMessage,
IAllocatorMXF_fnConnectOutput,
IAllocatorMXF_fnDisconnectOutput,
IAllocatorMXF_fnGetMessage,
IAllocatorMXF_fnGetBufferSize,
IAllocatorMXF_fnGetBuffer,
IAllocatorMXF_fnPutBuffer
};
//==================================================================================================================================
@ -110,6 +378,8 @@ IServiceSink_fnRelease(
/* Return new reference count */
return This->ref;
}
static
VOID
NTAPI
@ -118,8 +388,9 @@ SetStreamWorkerRoutine(
IN PVOID Context)
{
IPortPinDMusImpl * This;
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
KSSTATE State;
NTSTATUS Status;
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
This = Ctx->Pin;
State = Ctx->State;
@ -132,9 +403,18 @@ SetStreamWorkerRoutine(
return;
/* Set the state */
if (NT_SUCCESS(This->MidiStream->lpVtbl->SetState(This->MidiStream, State)))
if (This->MidiStream)
{
/* Set internal state to stop */
Status = This->MidiStream->lpVtbl->SetState(This->MidiStream, State);
}
else
{
Status = This->Mxf->lpVtbl->SetState(This->Mxf, State);
}
if (NT_SUCCESS(Status))
{
/* Set internal state to requested state */
This->State = State;
if (This->State == KSSTATE_STOP)
@ -237,6 +517,59 @@ TransferMidiData(
}
VOID
TransferMidiDataToDMus(
IPortPinDMusImpl * This)
{
NTSTATUS Status;
PHYSICAL_ADDRESS PhysicalAddress;
ULONG BufferSize, Flags;
PVOID Buffer;
PDMUS_KERNEL_EVENT_WITH_TAG Event, LastEvent = NULL, Root = NULL;
do
{
This->LastTag++;
Status = This->IrpQueue->lpVtbl->GetMappingWithTag(This->IrpQueue, UlongToPtr(This->LastTag), &PhysicalAddress, &Buffer, &BufferSize, &Flags);
if (!NT_SUCCESS(Status))
{
break;
}
Status = IAllocatorMXF_fnGetMessage((IAllocatorMXF*)&This->lpVtblAllocatorMXF, (PDMUS_KERNEL_EVENT*)&Event);
if (!NT_SUCCESS(Status))
break;
//FIXME
//set up struct
//Event->Event.usFlags = DMUS_KEF_EVENT_COMPLETE;
Event->Event.cbStruct = sizeof(DMUS_KERNEL_EVENT);
Event->Event.cbEvent = BufferSize;
Event->Event.uData.pbData = Buffer;
if (!Root)
Root = Event;
else
LastEvent->Event.pNextEvt = (struct _DMUS_KERNEL_EVENT *)Event;
LastEvent = Event;
LastEvent->Event.pNextEvt = NULL;
LastEvent->Tag = UlongToPtr(This->LastTag);
}while(TRUE);
if (!Root)
{
SetStreamState(This, KSSTATE_STOP);
return;
}
Status = This->Mxf->lpVtbl->PutMessage(This->Mxf, (PDMUS_KERNEL_EVENT)Root);
DPRINT("Status %x\n", Status);
}
static
VOID
NTAPI
@ -251,8 +584,10 @@ IServiceSink_fnRequestService(
{
TransferMidiData(This);
}
else if (This->Mxf)
{
TransferMidiDataToDMus(This);
}
}
static IServiceSinkVtbl vt_IServiceSink =
@ -486,7 +821,7 @@ IPortPinDMus_fnClose(
PCLOSESTREAM_CONTEXT Ctx;
IPortPinDMusImpl * This = (IPortPinDMusImpl*)iface;
if (This->MidiStream)
if (This->MidiStream || This->Mxf)
{
Ctx = AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
if (!Ctx)
@ -757,6 +1092,38 @@ IPortPinDMus_fnInit(
if (!NT_SUCCESS(Status))
return Status;
}
else
{
Status = This->Miniport->lpVtbl->NewStream(This->Miniport,
&This->Mxf,
NULL,
NonPagedPool,
ConnectDetails->PinId,
Capture, //FIXME
This->Format,
&This->ServiceGroup,
(PAllocatorMXF)&This->lpVtblAllocatorMXF,
(PMASTERCLOCK)&This->lpVtblMasterClock,
&This->SchedulePreFetch);
DPRINT("IPortPinDMus_fnInit Status %x\n", Status);
if (!NT_SUCCESS(Status))
return Status;
if (Capture == DMUS_STREAM_MIDI_CAPTURE)
{
Status = This->Mxf->lpVtbl->ConnectOutput(This->Mxf, (PMXF)&This->lpVtblMXF);
if (!NT_SUCCESS(Status))
{
DPRINT("IMXF_ConnectOutput failed with Status %x\n", Status);
return Status;
}
}
ExInitializeNPagedLookasideList(&This->LookAsideEvent, NULL, NULL, 0, sizeof(DMUS_KERNEL_EVENT_WITH_TAG), TAG_PORTCLASS, 0);
ExInitializeNPagedLookasideList(&This->LookAsideBuffer, NULL, NULL, 0, PAGE_SIZE, TAG_PORTCLASS, 0);
}
if (This->ServiceGroup)
{
@ -832,6 +1199,8 @@ NTSTATUS NewPortPinDMus(
This->ref = 1;
This->lpVtbl = &vt_IPortPinDMus;
This->lpVtblServiceSink = &vt_IServiceSink;
This->lpVtblMasterClock = &vt_IMasterClock;
This->lpVtblAllocatorMXF = &vt_IAllocatorMXF;
/* store result */
@ -839,6 +1208,3 @@ NTSTATUS NewPortPinDMus(
return STATUS_SUCCESS;
}