Virtu/Virtu/Wpf/Services/WpfVideoService.cs

108 lines
3.7 KiB
C#

using System;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Jellyfish.Library;
namespace Jellyfish.Virtu.Services
{
public sealed class WpfVideoService : VideoService
{
public WpfVideoService(Machine machine, UserControl page, Image image) :
base(machine)
{
if (page == null)
{
throw new ArgumentNullException("page");
}
if (image == null)
{
throw new ArgumentNullException("image");
}
_page = page;
_image = image;
_image.Source = _bitmap;
_page.Loaded += (sender, e) => SetWindowSizeToContent();
_page.SizeChanged += (sender, e) => SetImageSize();
}
public override void SetFullScreen(bool isFullScreen)
{
if (_isFullScreen != isFullScreen)
{
_isFullScreen = isFullScreen;
_page.Dispatcher.Send(() =>
{
var window = Window.GetWindow(_page);
if (_isFullScreen)
{
window.ResizeMode = ResizeMode.NoResize;
window.WindowStyle = WindowStyle.None;
window.WindowState = WindowState.Maximized;
}
else
{
window.WindowState = WindowState.Normal;
window.WindowStyle = WindowStyle.SingleBorderWindow;
window.ResizeMode = ResizeMode.CanResize;
}
});
}
}
[SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow")]
public override void SetPixel(int x, int y, uint color)
{
_pixels[y * BitmapWidth + x] = color;
_pixelsDirty = true;
}
public override void Update() // main thread
{
if (_pixelsDirty)
{
_pixelsDirty = false;
_bitmap.WritePixels(BitmapRect, _pixels, BitmapStride, 0);
}
}
private void SetImageSize()
{
int uniformScale = Math.Max(1, Math.Min((int)_page.RenderSize.Width / BitmapWidth, (int)_page.RenderSize.Height / BitmapHeight));
_image.Width = uniformScale * BitmapWidth;
_image.Height = uniformScale * BitmapHeight;
}
private void SetWindowSizeToContent()
{
if (!_sizedToContent)
{
_sizedToContent = true;
var window = Application.Current.MainWindow;
var size = window.DesiredSize;
window.Width = size.Width;
window.Height = size.Height;
}
}
private const int BitmapWidth = 560;
private const int BitmapHeight = 384;
private const int BitmapDpi = 96;
private static readonly PixelFormat BitmapPixelFormat = PixelFormats.Bgr32;
private static readonly int BitmapStride = (BitmapWidth * BitmapPixelFormat.BitsPerPixel + 7) / 8;
private static readonly Int32Rect BitmapRect = new Int32Rect(0, 0, BitmapWidth, BitmapHeight);
private UserControl _page;
private Image _image;
private WriteableBitmap _bitmap = new WriteableBitmap(BitmapWidth, BitmapHeight, BitmapDpi, BitmapDpi, BitmapPixelFormat, null);
private uint[] _pixels = new uint[BitmapWidth * BitmapHeight];
private bool _pixelsDirty;
private bool _isFullScreen;
private bool _sizedToContent;
}
}