+typedef struct
+{
+ CPortPinWaveCyclic *Pin;
+ KSSTATE NewState;
+ PIO_WORKITEM WorkItem;
+ PIRP Irp;
+
+}SETPIN_CONTEXT, *PSETPIN_CONTEXT;
+
+VOID
+CALLBACK
+PinSetStateWorkerRoutine(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context)
+{
+ PSETPIN_CONTEXT PinWorkContext = (PSETPIN_CONTEXT)Context;
+ NTSTATUS Status;
+
+ // try set stream
+ Status = PinWorkContext->Pin->m_Stream->SetState(PinWorkContext->NewState);
+
+ DPRINT1("Setting state %u %x\n", PinWorkContext->NewState, Status);
+ if (NT_SUCCESS(Status))
+ {
+ // store new state
+ PinWorkContext->Pin->m_State = PinWorkContext->NewState;
+
+ if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP)
+ {
+ /* FIXME complete pending irps with successfull state */
+ PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
+ PinWorkContext->Pin->m_Stream->Silence(PinWorkContext->Pin->m_CommonBuffer, PinWorkContext->Pin->m_CommonBufferSize);
+ PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
+ PinWorkContext->Pin->m_Position.PlayOffset = 0;
+ PinWorkContext->Pin->m_Position.WriteOffset = 0;
+ PinWorkContext->Pin->m_GlitchCount = 0;
+ PinWorkContext->Pin->m_GlitchLength = 0;
+
+ // unregister the time out
+ PcUnregisterIoTimeout(GetDeviceObject(PinWorkContext->Pin->m_Port), PinWaveCyclicIoTimerRoutine, (PVOID)PinWorkContext->Pin);
+ }
+ else if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP)
+ {
+ /* FIXME complete pending irps with successfull state */
+ PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
+ PinWorkContext->Pin->m_Stream->Silence(PinWorkContext->Pin->m_CommonBuffer, PinWorkContext->Pin->m_CommonBufferSize);
+ PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
+ PinWorkContext->Pin->m_Position.PlayOffset = 0;
+ PinWorkContext->Pin->m_Position.WriteOffset = 0;
+ PinWorkContext->Pin->m_GlitchCount = 0;
+ PinWorkContext->Pin->m_GlitchLength = 0;
+
+ // unregister the time out
+ PcUnregisterIoTimeout(GetDeviceObject(PinWorkContext->Pin->m_Port), PinWaveCyclicIoTimerRoutine, (PVOID)PinWorkContext->Pin);
+ }
+ }
+
+ // store result
+ if (PinWorkContext->Irp)
+ {
+ PinWorkContext->Irp->IoStatus.Information = sizeof(KSSTATE);
+ PinWorkContext->Irp->IoStatus.Status = Status;
+
+ // complete irp
+ IoCompleteRequest(PinWorkContext->Irp, IO_NO_INCREMENT);
+ }
+
+ // free work item
+ IoFreeWorkItem(PinWorkContext->WorkItem);
+
+ // free work context
+ FreeItem(PinWorkContext, TAG_PORTCLASS);
+
+}
+
+VOID
+NTAPI
+PinWaveCyclicIoTimerRoutine(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context)
+{
+ CPortPinWaveCyclic *Pin;
+ //PSETPIN_CONTEXT Ctx;
+ LARGE_INTEGER CurrentTime;
+
+ // cast to pin impl
+ Pin = (CPortPinWaveCyclic*)Context;
+
+ /* query system time */
+ KeQuerySystemTime(&CurrentTime);
+
+ /* check if the connection matches */
+ if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING && Pin->m_ResetState == KSRESET_END && Pin->m_State != KSSTATE_STOP && Pin->m_Started)
+ {
+ LARGE_INTEGER Diff;
+
+ Diff.QuadPart = CurrentTime.QuadPart - Pin->m_LastPacketTime.QuadPart;
+
+ if (Diff.QuadPart >= Int32x32To64(3000, 10000))
+ {
+ DPRINT1("AudioThread Hang detected: Last Packet %I64u CurrentTime %I64u Diff %I64u\n", Pin->m_LastPacketTime.QuadPart, CurrentTime.QuadPart, Diff.QuadPart);
+#if 0
+ /* allocate pin context */
+ Ctx = (PSETPIN_CONTEXT)AllocateItem(NonPagedPool, sizeof(SETPIN_CONTEXT), TAG_PORTCLASS);
+
+ if (!Ctx)
+ {
+ /* no memory */
+ return;
+ }
+
+ /* initialize ctx */
+ Ctx->Pin = Pin;
+ if (Pin->m_State == KSSTATE_RUN)
+ Ctx->NewState = KSSTATE_PAUSE;
+ else if (Pin->m_State == KSSTATE_PAUSE)
+ Ctx->NewState = KSSTATE_ACQUIRE;
+ else if (Pin->m_State == KSSTATE_ACQUIRE)
+ Ctx->NewState = KSSTATE_STOP;
+
+ Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
+ Ctx->Irp = NULL;
+
+ if (!Ctx->WorkItem)
+ {
+ /* no memory */
+ FreeItem(Ctx, TAG_PORTCLASS);
+ return;
+ }
+
+ /* queue the work item */
+ IoQueueWorkItem(Ctx->WorkItem, PinSetStateWorkerRoutine, DelayedWorkQueue, (PVOID)Ctx);
+#endif
+ }
+ }
+}
+
+