private void pollingThreadProc() { long oldCounter = long.MaxValue; while (true) { var getChangesBuffer = (GetChangesBuffer)Marshal.PtrToStructure(_getChangesBuffer, typeof(GetChangesBuffer)); var buffer = (ChangesBuffer)Marshal.PtrToStructure(getChangesBuffer.Buffer, typeof(ChangesBuffer)); // Initialize oldCounter if (oldCounter == long.MaxValue) { oldCounter = buffer.counter; } if (oldCounter != buffer.counter) { Trace.WriteLine(string.Format("Counter changed. Old is {0} new is {1}", oldCounter, buffer.counter)); //for (long currentChange = oldCounter; currentChange != buffer.counter; currentChange++ ) //{ // if (currentChange >= ChangesBuffer.MAXCHANGES_BUF) // currentChange = 0; // if (DesktopChange != null) // DesktopChange(this, // new DesktopChangeEventArgs(buffer.pointrect[currentChange].rect.x1, // buffer.pointrect[currentChange].rect.y1, // buffer.pointrect[currentChange].rect.x2, // buffer.pointrect[currentChange].rect.y2, // (OperationType) buffer.pointrect[currentChange].type)); //} long now = System.DateTime.Now.Ticks / 10000; DesktopChangeEventArgs args = new DesktopChangeEventArgs(); if (buffer.counter - oldCounter > 50) { } Console.WriteLine(args.rectangles.Count); DesktopChange(this, args); Console.WriteLine((System.DateTime.Now.Ticks / 10000 - now) + "ms"); oldCounter = buffer.counter; } // Just to prevent 100-percent CPU load and to provide thread-safety use manual reset event instead of simple in-memory flag. if (_terminatePollingThread.WaitOne(PollInterval, false)) { Trace.WriteLine("The thread now exits"); break; } } // We can be sure that _pollingThreadTerminated exists _pollingThreadTerminated.Set(); }
/// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="dce"></param> static private unsafe void _DesktopChange(object sender, DesktopChangeEventArgs dce) { if (streamer.clients.Count > 0) // No one is listening, why bother to process updates { try { lock (streamer.updates.SyncRoot) { if (streamer.updates.Count == 0) { if (numUpdates++ > 5) { // Send the iFrame GCbuf screenbuf = new GCbuf(); #if USE_BITMAP_COMPRESS int ptr = DesktopMirror._bitmapWidth * DesktopMirror._bitmapHeight, num = 0; for (int i = 0; i < ptr; i++) { screenbuf.buf[num++] = 0xFF; } for (int i = 0; i < (ptr * 4); i += 4) { screenbuf.buf[num++] = _mirror.screen[i]; screenbuf.buf[num++] = _mirror.screen[i + 1]; screenbuf.buf[num++] = _mirror.screen[i + 2]; } #else Buffer.BlockCopy(_mirror.screen, 0, screenbuf.buf, 0, _mirror.screen.Length); // for (int i = 0; i < _mirror.screen.Length; i++) // screenbuf.buf[i] = _mirror.screen[i]; #endif screenbuf.Length = _mirror.screen.Length; streamer.updates.Enqueue(new sendUpdate(null, screenbuf, maskX, maskY, maskWidth, maskHeight)); numUpdates = 0; } else { if (maskValid == true) { System.Drawing.Rectangle cur = new System.Drawing.Rectangle(dce.x, dce.y, dce.w, dce.h); System.Drawing.Rectangle mask = new System.Drawing.Rectangle(Program.maskX, Program.maskY, Program.maskWidth, Program.maskHeight); cur.Intersect(mask); if (cur.IsEmpty) { return; } else { streamer.updates.Enqueue(new sendUpdate(null, null, cur.X, cur.Y, cur.Width, cur.Height)); } } else { streamer.updates.Enqueue(new sendUpdate(null, null, dce.x, dce.y, dce.w, dce.h)); } } } else { System.Drawing.Rectangle orig = new System.Drawing.Rectangle(dce.x, dce.y, dce.w, dce.h); if (maskValid == true) { System.Drawing.Rectangle mask = new System.Drawing.Rectangle(Program.maskX, Program.maskY, Program.maskWidth, Program.maskHeight); orig.Intersect(mask); if (orig.IsEmpty) { return; } } for (int i = streamer.updates.Count; i > 0; i--) { sendUpdate upd = (sendUpdate)streamer.updates.Dequeue(); System.Drawing.Rectangle cur = new System.Drawing.Rectangle(upd.x, upd.y, upd.w, upd.h); /* I don't think that I need to do this * if (maskValid == true) { * cur.Intersect(mask); * if (cur.IsEmpty) * continue; * } */ cur.Intersect(orig); if (cur.IsEmpty) { // Move this update to the back of the line? Okay because all pending updates are disjoint streamer.updates.Enqueue(upd); // Moved to the front of the for loop // upd = (sendUpdate)streamer.updates.Dequeue(); } else { cur.X = upd.x; cur.Y = upd.y; cur.Width = upd.w; cur.Height = upd.h; System.Drawing.Rectangle combined = System.Drawing.Rectangle.Union(orig, cur); Boolean anymoreCombine = true; // int count = 0; while (anymoreCombine) { anymoreCombine = false; for (int j = streamer.updates.Count; j > 0; j--) { sendUpdate u = (sendUpdate)streamer.updates.Dequeue(); System.Drawing.Rectangle nxt = new System.Drawing.Rectangle(u.x, u.y, u.w, u.h); /* I don't think that I need this either * if (maskValid == true) { * nxt.Intersect(mask); * if (nxt.IsEmpty) * continue; * } */ nxt.Intersect(combined); if (nxt.IsEmpty) { streamer.updates.Enqueue(u); } else { nxt.X = u.x; nxt.Y = u.y; nxt.Width = u.w; nxt.Height = u.h; combined = System.Drawing.Rectangle.Union(combined, nxt); anymoreCombine = true; Trace.WriteLine("DEBUG: ----"); break; } } } streamer.updates.Enqueue(new sendUpdate(null, null, combined.X, combined.Y, combined.Width, combined.Height)); // Trace.WriteLine("DEBUG: need to make sure that this update does not overlap with prior non-overlapping rectangles"); // Actually don't need to because of the way that Queue's work? return; } } if (maskValid == true) { System.Drawing.Rectangle cur = new System.Drawing.Rectangle(dce.x, dce.y, dce.w, dce.h); System.Drawing.Rectangle mask = new System.Drawing.Rectangle(Program.maskX, Program.maskY, Program.maskWidth, Program.maskHeight); cur.Intersect(mask); if (cur.IsEmpty) { return; } streamer.updates.Enqueue(new sendUpdate(null, null, cur.X, cur.Y, cur.Width, cur.Height)); } else { streamer.updates.Enqueue(new sendUpdate(null, null, dce.x, dce.y, dce.w, dce.h)); } } } } catch (System.IO.IOException) { Trace.WriteLine("DEBUG: An internal Win32 exception is caused by update while creating event handler. Ignoring"); // Environment.Exit(1); } catch (Exception e) { MessageBox.Show("DEBUG: Error while capturing update coordinates " + e.StackTrace); } } }
private void pollingThreadProc() { long oldCounter = long.MaxValue; while (true) { var getChangesBuffer = (GetChangesBuffer) Marshal.PtrToStructure(_getChangesBuffer, typeof (GetChangesBuffer)); var buffer = (ChangesBuffer)Marshal.PtrToStructure(getChangesBuffer.Buffer, typeof(ChangesBuffer)); // Initialize oldCounter if (oldCounter == long.MaxValue) oldCounter = buffer.counter; if (oldCounter != buffer.counter) { Trace.WriteLine(string.Format("Counter changed. Old is {0} new is {1}", oldCounter, buffer.counter)); //for (long currentChange = oldCounter; currentChange != buffer.counter; currentChange++ ) //{ // if (currentChange >= ChangesBuffer.MAXCHANGES_BUF) // currentChange = 0; // if (DesktopChange != null) // DesktopChange(this, // new DesktopChangeEventArgs(buffer.pointrect[currentChange].rect.x1, // buffer.pointrect[currentChange].rect.y1, // buffer.pointrect[currentChange].rect.x2, // buffer.pointrect[currentChange].rect.y2, // (OperationType) buffer.pointrect[currentChange].type)); //} long now = System.DateTime.Now.Ticks / 10000; DesktopChangeEventArgs args = new DesktopChangeEventArgs(); if (buffer.counter - oldCounter > 50) { } Console.WriteLine(args.rectangles.Count); DesktopChange(this, args); Console.WriteLine((System.DateTime.Now.Ticks/10000-now)+"ms"); oldCounter = buffer.counter; } // Just to prevent 100-percent CPU load and to provide thread-safety use manual reset event instead of simple in-memory flag. if (_terminatePollingThread.WaitOne(PollInterval, false)) { Trace.WriteLine("The thread now exits"); break; } } // We can be sure that _pollingThreadTerminated exists _pollingThreadTerminated.Set(); }