public void RenderGray2(DMDFrame frame) { if (!_isOpen) { Init(); } int width = frame.width; int height = frame.height; if (_gray2Colorizer != null && frame.width == 128 && frame.height == 16 && _gray2Colorizer.Has128x32Animation) { // Pin2DMD colorization may have 512 byte masks with a 128x16 source, // indicating this should be upsized and treated as a centered 128x32 DMD. height = frame.height; height *= 2; if (_upsizedFrame == null) { _upsizedFrame = new DMDFrame() { width = width, height = height, Data = new byte[width * height] } } ; else { _upsizedFrame.Update(width, height, _upsizedFrame.Data); } Buffer.BlockCopy(frame.Data, 0, _upsizedFrame.Data, 8 * width, frame.Data.Length); if (_config.Global.ScaleToHd) { width = 256; height = 64; _upsizedFrame.Update(width, height, _upsizedFrame.Data); } _gray2Colorizer.SetDimensions(width, height); _vpmGray2Source.NextFrame(_upsizedFrame); } else { if (_config.Global.ScaleToHd) { if (width == 128 && height == 32) { width *= 2; height *= 2; frame.Update(width, height, frame.Data); } } _gray2Colorizer?.SetDimensions(width, height); _gray4Colorizer?.SetDimensions(width, height); _vpmGray2Source.NextFrame(frame); } }
public void RenderGray4(DMDFrame frame) { if (!_isOpen) { Init(); } int width = frame.width; int height = frame.height; if (_config.Global.ScaleToHd) { if (width == 128 && height == 32) { width *= 2; height *= 2; frame.Update(width, height, frame.Data); } } _gray2Colorizer?.SetDimensions(frame.width, frame.height); _gray4Colorizer?.SetDimensions(frame.width, frame.height); _vpmGray4Source.NextFrame(frame); }
public IObservable <DMDFrame> GetGray4Frames() { if (_framesGray4 != null) { return(_framesGray4); } CreateBridge(); Logger.Info("Subscribing to Pro Pinball's message queue..."); _framesGray4 = Observable.Create <DMDFrame>(o => { var len = Dimensions.Value.Width * Dimensions.Value.Height; // this is blocking, so use a new thread var thread = new Thread(() => { unsafe { _bridge.GetFrames(frame => { var arr = _dmdFrame.Update(Dimensions.Value.Width, Dimensions.Value.Height, new byte[len]); Marshal.Copy((IntPtr)frame, arr.Data, 0, len); o.OnNext(arr); }, err => { throw new ProPinballSlaveException(new string(err)); }, () => { Logger.Debug("Received exit signal from Pro Pinball, closing."); Process.GetCurrentProcess().Kill(); }); } }); thread.Start(); Logger.Debug("Subscribed to Pro Pinball's message queue."); return(Disposable.Create(() => { thread.Abort(); Logger.Debug("Disposing Pro Pinball's message queue..."); })); }); return(_framesGray4); }
public void RenderAlphaNumeric(NumericalLayout layout, ushort[] segData, ushort[] segDataExtended) { if (!_isOpen) { Init(); } _vpmAlphaNumericSource.NextFrame(new AlphaNumericFrame(layout, segData, segDataExtended)); _dmdFrame.width = Width; _dmdFrame.height = Height; //Logger.Info("Alphanumeric: {0}", layout); switch (layout) { case NumericalLayout.__2x16Alpha: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x16Alpha(segData))); break; case NumericalLayout.None: case NumericalLayout.__2x20Alpha: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x20Alpha(segData))); break; case NumericalLayout.__2x7Alpha_2x7Num: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x7Alpha_2x7Num(segData))); break; case NumericalLayout.__2x7Alpha_2x7Num_4x1Num: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x7Alpha_2x7Num_4x1Num(segData))); break; case NumericalLayout.__2x7Num_2x7Num_4x1Num: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x7Num_2x7Num_4x1Num(segData))); break; case NumericalLayout.__2x7Num_2x7Num_10x1Num: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x7Num_2x7Num_10x1Num(segData, segDataExtended))); break; case NumericalLayout.__2x7Num_2x7Num_4x1Num_gen7: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x7Num_2x7Num_4x1Num_gen7(segData))); break; case NumericalLayout.__2x7Num10_2x7Num10_4x1Num: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x7Num10_2x7Num10_4x1Num(segData))); break; case NumericalLayout.__2x6Num_2x6Num_4x1Num: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x6Num_2x6Num_4x1Num(segData))); break; case NumericalLayout.__2x6Num10_2x6Num10_4x1Num: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x6Num10_2x6Num10_4x1Num(segData))); break; case NumericalLayout.__4x7Num10: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render4x7Num10(segData))); break; case NumericalLayout.__6x4Num_4x1Num: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render6x4Num_4x1Num(segData))); break; case NumericalLayout.__2x7Num_4x1Num_1x16Alpha: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render2x7Num_4x1Num_1x16Alpha(segData))); break; case NumericalLayout.__1x16Alpha_1x16Num_1x7Num: _vpmGray2Source.NextFrame(_dmdFrame.Update(AlphaNumeric.Render1x16Alpha_1x16Num_1x7Num(segData))); break; default: throw new ArgumentOutOfRangeException(nameof(layout), layout, null); } }
public ImageSourceGray4(BitmapSource bmp) { SetDimensions(bmp.PixelWidth, bmp.PixelHeight); _frames = new BehaviorSubject <DMDFrame>(_dmdFrame.Update(bmp.PixelWidth, bmp.PixelHeight, ImageUtil.ConvertToGray4(bmp))); }
private void ServerThread(object data) { try { var server = new NamedPipeServerStream(PipeName, PipeDirection.In, 1, PipeTransmissionMode.Message); var isGameRunning = true; var chunkSize = 0; var gray2Frame = new DMDFrame { width = 132, height = 32 }; var messageChunk = new byte[4096]; // for each frame do { // connect and wait for a new frame server.WaitForConnection(); _lastTick = DateTime.Now.Ticks; // for each chunk do { chunkSize = server.Read(messageChunk, 0, messageChunk.Length); // game table has ended, clear the DMD with an empty byte array - chunkSize is only 4 if "done" is recieved from the pipe if (chunkSize == 4) { messageChunk = new byte[messageChunk.Length]; if (!_isPaused) { _onPause.OnNext(Unit.Default); _isPaused = true; } } else if (_isPaused) { _onResume.OnNext(Unit.Default); _isPaused = false; } } while (chunkSize != 0 || !server.IsMessageComplete); // convert message to frame data UpdateFrame(messageChunk); // publish frame data _framesGray4.OnNext(gray2Frame.Update(_frame)); // disconnect as the pipe was consumed server.Disconnect(); // wait for next cycle var sleepTicks = _ticksPerCycle - (DateTime.Now.Ticks - _lastTick); var sleepMs = (int)(sleepTicks / TimeSpan.TicksPerMillisecond); if (sleepMs > 0) { Thread.Sleep(sleepMs); } } while (isGameRunning); Logger.Info($"Pipe server for FutureDMD terminated!"); if (server != null) { server.Dispose(); } server = null; } catch (IOException e) { Logger.Error(e); } }
public void OnRgb24(uint timestamp, byte[] frame) => Rgb24Source.FramesRgb24.OnNext(_dmdFrame.Update(frame));