Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds FX3 colorization support #367

Merged
merged 21 commits into from
Apr 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ csharp_style_inlined_variable_declaration = true:suggestion
# C# Formatting Rules #
###############################
# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_open_brace = accessors,types,methods,properties,indexers,events,anonymous_methods,anonymous_types,object_collection_array_initalizers,lambdas,local_functions
csharp_new_line_before_else = false
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
Expand Down
2 changes: 1 addition & 1 deletion Console/Common/BaseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public void Execute(HashSet<string> reportingTags, Action onCompleted, Action<Ex
GetRenderGraphs(reportingTags).Init().StartRendering(onCompleted, onError);
}

public void Dispose()
public virtual void Dispose()
{
if (_config == null || !_config.Global.NoClear) {
_graphs?.ClearDisplay();
Expand Down
5 changes: 4 additions & 1 deletion Console/Common/BaseOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ internal abstract class BaseOptions : IConfiguration
[Option("retry-interval", HelpText = "In seconds, interval between Websocket connection retry attempts. Default: 5 seconds")]
public int WebsocketRetryInterval { get; set; } = 5;

[Option("colorize", HelpText = "Enable frame-by-frame colorization")]
public bool Colorize { get; set; } = false;

public IGlobalConfig Global { get; }
public IVirtualDmdConfig VirtualDmd { get; }
public IVirtualAlphaNumericDisplayConfig VirtualAlphaNumericDisplay { get; }
Expand Down Expand Up @@ -201,7 +204,7 @@ public GlobalConfig(BaseOptions options)
public ResizeMode Resize => _options.Resize;
public bool FlipHorizontally => _options.FlipHorizontally;
public bool FlipVertically => _options.FlipVertically;
public bool Colorize => false;
public bool Colorize => _options.Colorize;
public bool QuitWhenDone => _options.QuitWhenDone;
public int QuitAfter => _options.QuitAfter;
public bool NoClear => _options.NoClear;
Expand Down
134 changes: 119 additions & 15 deletions Console/Mirror/MirrorCommand.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using DmdExt.Common;
using LibDmd;
using LibDmd.Common;
using LibDmd.Converter;
using LibDmd.DmdDevice;
using LibDmd.Input;
using LibDmd.Input.FutureDmd;
using LibDmd.Input.PinballFX;
using LibDmd.Input.ProPinball;
using LibDmd.Input.ScreenGrabber;
using LibDmd.Input.TPAGrabber;
using LibDmd.Output;
using LibDmd.Processor;

namespace DmdExt.Mirror
Expand All @@ -17,56 +21,70 @@ class MirrorCommand : BaseCommand
{
private readonly MirrorOptions _options;
private readonly IConfiguration _config;
private RenderGraph _graph;
private ColorizationLoader _colorizationLoader;
private readonly CompositeDisposable _subscriptions = new CompositeDisposable();
private List<IDestination> _renderers;

public MirrorCommand(IConfiguration config, MirrorOptions options)
{
_config = config;
_options = options;
}

protected override void CreateRenderGraphs(RenderGraphCollection graphs, HashSet<string> reportingTags)
private RenderGraph CreateGraph(ISource source, string name, HashSet<string> reportingTags)
{
// create graph with renderers
_graph = new RenderGraph {
Destinations = GetRenderers(_config, reportingTags),
if (_renderers == null) {
_renderers = GetRenderers(_config, reportingTags);
}
var graph = new RenderGraph {
Name = name,
Source = source,
Destinations = _renderers,
Resize = _config.Global.Resize,
FlipHorizontally = _config.Global.FlipHorizontally,
FlipVertically = _config.Global.FlipVertically,
IdleAfter = _options.IdleAfter,
IdlePlay = _options.IdlePlay
};
_graph.SetColor(_config.Global.DmdColor);
graph.SetColor(_config.Global.DmdColor);

return graph;
}

protected override void CreateRenderGraphs(RenderGraphCollection graphs, HashSet<string> reportingTags)
{
// setup source and additional processors
switch (_options.Source) {

case SourceType.PinballFX2: {
_graph.Source = new PinballFX2Grabber { FramesPerSecond = _options.FramesPerSecond };
reportingTags.Add("In:PinballFX2");
graphs.Add(CreateGraph(new PinballFX2Grabber { FramesPerSecond = _options.FramesPerSecond }, "Pinball FX2 Render Graph", reportingTags));
break;
}

case SourceType.PinballFX3: {
if (_options.Fx3GrabScreen) {
_graph.Source = new PinballFX3Grabber { FramesPerSecond = _options.FramesPerSecond };
reportingTags.Add("In:PinballFX3Legacy");
graphs.Add(CreateGraph(new PinballFX3Grabber { FramesPerSecond = _options.FramesPerSecond }, "Pinball FX3 (legacy) Render Graph", reportingTags));

} else {
_graph.Source = new PinballFX3MemoryGrabber { FramesPerSecond = _options.FramesPerSecond };
reportingTags.Add("In:PinballFX3");
graphs.Add(CreateGraph(new PinballFX3MemoryGrabber { FramesPerSecond = _options.FramesPerSecond }, "Pinball FX3 Render Graph", reportingTags));
}
break;
}

case SourceType.PinballArcade: {
_graph.Source = new TPAGrabber { FramesPerSecond = _options.FramesPerSecond };
reportingTags.Add("In:PinballArcade");
var tpaGrabber = new TPAGrabber { FramesPerSecond = _options.FramesPerSecond };
graphs.Add(CreateGraph(tpaGrabber.Gray2Source, "Pinball Arcade (2-bit) Render Graph", reportingTags));
graphs.Add(CreateGraph(tpaGrabber.Gray4Source, "Pinball Arcade (4-bit) Render Graph", reportingTags));
break;
}

case SourceType.ProPinball: {
_graph.Source = new ProPinballSlave(_options.ProPinballArgs);
reportingTags.Add("In:ProPinball");
graphs.Add(CreateGraph(new ProPinballSlave(_options.ProPinballArgs), "Pro Pinball Render Graph", reportingTags));
break;
}

Expand All @@ -89,20 +107,106 @@ protected override void CreateRenderGraphs(RenderGraphCollection graphs, HashSet
});
}

_graph.Source = grabber;
reportingTags.Add("In:ScreenGrab");
graphs.Add(CreateGraph(grabber, "Screen Grabber Render Graph", reportingTags));
break;

case SourceType.FuturePinball:
_graph.Source = new FutureDmdSink(_options.FramesPerSecond);
reportingTags.Add("In:FutureDmdSink");
graphs.Add(CreateGraph(new FutureDmdSink(_options.FramesPerSecond), "Future Pinball Render Graph", reportingTags));
break;

default:
throw new ArgumentOutOfRangeException();
}
graphs.Add(_graph);

// if colorization enabled, subscribe to name changes to re-load colorizer.
if (_config.Global.Colorize) {
foreach (var graph in graphs.Graphs) {
if (!(graph.Source is IGameNameSource gameNameSource)) {
continue;
}

if (_colorizationLoader == null) {
_colorizationLoader = new ColorizationLoader();
graphs.ClearColor();
}

var converter = new SwitchingConverter(GetFrameFormat(graph.Source));
graph.Converter = converter;

_subscriptions.Add(gameNameSource.GetGameName().Subscribe(name => {
converter.Switch(LoadColorizer(name));
}));

if (graph.Source is IDmdColorSource dmdColorSource) {
dmdColorSource.GetDmdColor().Subscribe(color => {
converter.SetColor(color);
});
}
}
}
else {

// When not colorizing, subscribe to DMD color changes to inform the graph.
var colorSub = graphs.Graphs
.Select(g => g.Source as IDmdColorSource)
.FirstOrDefault(s => s != null)
?.GetDmdColor()
.Subscribe(graphs.SetColor);
if (colorSub != null) {
_subscriptions.Add(colorSub);
}

// print game names
var nameSub = graphs.Graphs
.Select(g => g.Source as IGameNameSource)
.FirstOrDefault(s => s != null)
?.GetGameName()
.Subscribe(name => Logger.Info($"New game detected: {name}"));

if (nameSub != null) {
_subscriptions.Add(nameSub);
}
}

graphs.SetDimensions(new LibDmd.Input.Dimensions(_options.ResizeTo[0], _options.ResizeTo[1]));
}

public override void Dispose()
{
base.Dispose();
_subscriptions.Dispose();
}

private IConverter LoadColorizer(string gameName)
{
if (gameName == null) {
return null;
}

var serumColorizer = _colorizationLoader.LoadSerum(gameName, _config.Global.ScalerMode);
if (serumColorizer != null) {
return serumColorizer;
}

return _colorizationLoader.LoadColorizer(gameName, _config.Global.ScalerMode)?.gray2;
}

private FrameFormat GetFrameFormat(ISource source)
{
switch (source) {
case IGray2Source _: return FrameFormat.Gray2;
case IGray4Source _: return FrameFormat.Gray4;
case IGray6Source _: return FrameFormat.Gray6;
case IRgb24Source _: return FrameFormat.Rgb24;
case IColoredGray2Source _: return FrameFormat.ColoredGray2;
case IColoredGray4Source _: return FrameFormat.ColoredGray4;
case IColoredGray6Source _: return FrameFormat.ColoredGray6;
case IAlphaNumericSource _: return FrameFormat.AlphaNumeric;
case IBitmapSource _: return FrameFormat.Bitmap;
}
throw new ArgumentException($"Unknown source type: {source.Name}");
}
}
}
2 changes: 1 addition & 1 deletion Console/Server/ServerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using LibDmd.Input;
using LibDmd.Input.FileSystem;
using LibDmd.Input.Network;
using LibDmd.Input.PinMame;
using LibDmd.Input.Passthrough;
using LibDmd.Output;

namespace DmdExt.Server
Expand Down
4 changes: 2 additions & 2 deletions Console/Test/TestCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using LibDmd.DmdDevice;
using LibDmd.Input;
using LibDmd.Input.FileSystem;
using LibDmd.Input.PinMame;
using LibDmd.Input.Passthrough;
using LibDmd.Output;

namespace DmdExt.Test
Expand Down Expand Up @@ -44,7 +44,7 @@ protected override void CreateRenderGraphs(RenderGraphCollection graphs, HashSet
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
});
_graph = new RenderGraph {
Source = new VpmAlphaNumericSource(alphaNumericFrame),
Source = new PassthroughAlphaNumericSource(alphaNumericFrame),
Destinations = renderers,
Resize = _config.Global.Resize,
FlipHorizontally = _config.Global.FlipHorizontally,
Expand Down
Loading