mirror of
https://github.com/reactos/reactos.git
synced 2025-04-25 16:10:29 +00:00
- 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:
parent
97126c89e0
commit
71c299cdfa
3 changed files with 382 additions and 12 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -678,4 +678,6 @@ DECLARE_INTERFACE_(IDmaChannelInit, IUnknown)
|
|||
IN PDEVICE_OBJECT DeviceObject) PURE;
|
||||
};
|
||||
|
||||
#undef INTERFACE
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue