diff --git a/GUIs/skyscraper8.UI.ImGui.MonoGame.Bridge/BaseGame.cs b/GUIs/skyscraper8.UI.ImGui.MonoGame.Bridge/BaseGame.cs index 10d3aa5..023513f 100644 --- a/GUIs/skyscraper8.UI.ImGui.MonoGame.Bridge/BaseGame.cs +++ b/GUIs/skyscraper8.UI.ImGui.MonoGame.Bridge/BaseGame.cs @@ -114,7 +114,12 @@ public class BaseGame : Game renderable.Render(); } Monitor.Exit(_imGuiRenderables); - - Console.WriteLine("X = {0}, Y = {1}", _imGuiRenderer.LastKnownMouseX,_imGuiRenderer.LastKnownMouseY); + + if (DebugMouse) + { + Console.WriteLine("X = {0}, Y = {1}", _imGuiRenderer.LastKnownMouseX, _imGuiRenderer.LastKnownMouseY); + } } + + public bool DebugMouse { get; set; } } \ No newline at end of file diff --git a/GUIs/skyscraper8.UI.ImGui.MonoGame/Forms/MessageWindow.cs b/GUIs/skyscraper8.UI.ImGui.MonoGame/Forms/MessageWindow.cs new file mode 100644 index 0000000..afb97dc --- /dev/null +++ b/GUIs/skyscraper8.UI.ImGui.MonoGame/Forms/MessageWindow.cs @@ -0,0 +1,63 @@ +using ImGuiNET; +using skyscraper8.UI.MonoGame.Bridge; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Numerics; + +namespace skyscraper8.UI.MonoGame.Forms +{ + internal class MessageWindow : ImGuiRenderable + { + public string Message { get; } + private string WindowUuid; + + public MessageWindow(string message) + { + Message = message; + WindowUuid = Guid.NewGuid().ToString(); + } + + private bool sizeSet; + public void Update() + { + + } + + private bool Closed; + public void Render() + { + bool closeMe = true; + if (!sizeSet) + { + ImGui.SetNextWindowSize(new Vector2(300, 160)); + sizeSet = true; + } + + ImGui.Begin(String.Format("Information ##{0}", WindowUuid), ref closeMe); + ImGui.TextWrapped(Message); + if (ImGui.Button("OK")) + closeMe = false; + ImGui.End(); + if (!closeMe) + { + Closed = true; + if (OnClose != null) + OnClose(); + } + } + + public bool WasClosed() + { + return Closed; + } + + public Action OnClose { get; set; } + public void Dispose() + { + + } + } +} diff --git a/GUIs/skyscraper8.UI.ImGui.MonoGame/Program.cs b/GUIs/skyscraper8.UI.ImGui.MonoGame/Program.cs index 2027c57..060584b 100644 --- a/GUIs/skyscraper8.UI.ImGui.MonoGame/Program.cs +++ b/GUIs/skyscraper8.UI.ImGui.MonoGame/Program.cs @@ -1,10 +1,308 @@ -namespace skyscraper8.UI.MonoGame +using skyscraper5.Skyscraper; +using skyscraper5.Skyscraper.Equipment; +using skyscraper5.Skyscraper.Gps; +using skyscraper5.Skyscraper.IO.TunerInterface; +using skyscraper5.Skyscraper.Scraper.Storage.Filesystem; +using skyscraper5.Skyscraper.Scraper.Storage.InMemory; +using skyscraper5.src.Skyscraper; +using skyscraper8.Skyscraper.Plugins; +using skyscraper8.Skyscraper.Scraper.Storage; +using System.IO; +using System.Net.NetworkInformation; + +namespace skyscraper8.UI.MonoGame { class Program { public static void Main(string[] args) { - SkyscraperGame game = new SkyscraperGame(); + PluginLogger localLogger = PluginLogManager.GetLogger(typeof(Program)); + SkyscraperHandleCollection handles = new SkyscraperHandleCollection(); + Queue errors = new Queue(); + + localLogger.Log(PluginLogLevel.Info,"Starting up..."); + + //LOAD STORAGE ---------------------------------------------------------------------------------------------------------------------------------------------------------- + + localLogger.Log(PluginLogLevel.Info, "Starting Storage Connection Manager..."); + StorageConnectionManager connectionManager = StorageConnectionManager.GetInstance(); + + localLogger.Log(PluginLogLevel.Info, "Enumerating Data Storage Factories..."); + handles.AllDataStorages = connectionManager.GetDataStorages().ToList().AsReadOnly(); + + localLogger.Log(PluginLogLevel.Debug, "Enumerating Object Storage Factories..."); + handles.AllObjectStorages = connectionManager.GetObjectStorages().ToList().AsReadOnly(); + + localLogger.Log(PluginLogLevel.Debug, "Checking for configuration file..."); + if (!connectionManager.IniExists()) + { + localLogger.Log(PluginLogLevel.Warn, "Configuration file not found!"); + errors.Enqueue(String.Format("The configuration file does not exist.\r\nPlease create one in the UI!")); + handles.Ini = new Ini(); + } + + DataStorageFactory dataStorageFactory; + try + { + localLogger.Log(PluginLogLevel.Debug, "Getting default data storage factory..."); + dataStorageFactory = connectionManager.GetDefaultDataStorageFactory(); + } + catch (Exception e) + { + localLogger.Log(PluginLogLevel.Error, "Failed to start the data storage factory: {0}", e.Message); + errors.Enqueue(String.Format("Could not load the data storage factory.\nThe following went wrong:\n\n{0}\n\n", e.Message)); + dataStorageFactory = new InMemoryScraperStorageFactory(); + } + + ObjectStorageFactory objectStorageFactory; + try + { + localLogger.Log(PluginLogLevel.Debug, "Getting default object storage factory..."); + objectStorageFactory = connectionManager.GetDefaultObjectStorageFactory(); + } + catch (Exception e) + { + localLogger.Log(PluginLogLevel.Error, "Failed to start the object storage factory: {0}", e.Message); + errors.Enqueue(String.Format("Could not load the object storage factory.\nThe following went wrong:\n\n{0}\n\n", e.Message)); + objectStorageFactory = new FilesystemScraperStorageFactory() + { + Directory = "dummy_object_storage" + }; + } + + localLogger.Log(PluginLogLevel.Info, "Creating Data Storage..."); + handles.DataStorage = dataStorageFactory.CreateDataStorage(); + + + localLogger.Log(PluginLogLevel.Info, "Checking whether the data storage and the object storage are the same..."); + bool equivalentStorages = objectStorageFactory.IsEquivalent(dataStorageFactory); + + if (equivalentStorages) + { + localLogger.Log(PluginLogLevel.Info, "Casting Data Storage to Object Storage."); + handles.ObjectStorage = (ObjectStorage)handles.DataStorage; + } + else + { + localLogger.Log(PluginLogLevel.Info,"It isn't -> Creating object storage..."); + try + { + handles.ObjectStorage = objectStorageFactory.CreateObjectStorage(); + } + catch (Exception e) + { + string objectStorageName = connectionManager.GetName(objectStorageFactory); + localLogger.Log(PluginLogLevel.Error, "Failed to start the object storage factory: {0}", e.Message); + errors.Enqueue(String.Format("Could not load {1}.\nThe following went wrong:\n\n{0}\n\n", e.Message, objectStorageName)); + } + } + + + localLogger.Log(PluginLogLevel.Info,"Reporting UI Version to the storages..."); + handles.DataStorage?.UiSetVersion(2); + handles.ObjectStorage?.UiSetVersion(2); + + + localLogger.Log(PluginLogLevel.Info,"Testing whether the data storage is responding..."); + try + { + handles.DataStorage.Ping(); + } + catch (Exception e) + { + string brokenStorageName = connectionManager.GetName(dataStorageFactory); + InMemoryScraperStorageFactory fssf = new InMemoryScraperStorageFactory(); + handles.DataStorage = fssf.CreateDataStorage(); + errors.Enqueue(String.Format( + "{0} failed to respond.\nThe following went wrong:\n\n{1}\n\nI've switched to a volatile in-memory storage. This will work, but is quite possibly not what you want. It will not and cannot save any data. Please consider configuring {0} correctly.", + brokenStorageName, e.Message)); + } + + localLogger.Log(PluginLogLevel.Info,"Please wait while I test whether the object storage is responding..."); + try + { + handles.ObjectStorage.Ping(); + } + catch (Exception e) + { + string brokenStorageName = connectionManager.GetName(objectStorageFactory); + FilesystemScraperStorageFactory fssf = new FilesystemScraperStorageFactory(); + fssf.Directory = "dummy_object_storage"; + handles.ObjectStorage = fssf.CreateObjectStorage(); + errors.Enqueue(String.Format( + "{0} failed to respond.\nThe following went wrong:\n\n{1}\n\nI've switched to a file system based storage. This will work, but is quite possibly not what you want. Please consider configuring {0} correctly.", + brokenStorageName, e.Message)); + } + + //LOAD GPS ---------------------------------------------------------------------------------------------------------------------------------------------------------------- + localLogger.Log(PluginLogLevel.Info, "Please wait while I load the GPS receiver library..."); + int gpsReceiverId = GpsManager.GetConfiguredGpsId(); + IGpsReceiverFactory gpsReceiverFactory = GpsManager.GetGpsReceiverFactoryById(gpsReceiverId); + GpsManager.AutoconfigureGpsReceiverFactory(gpsReceiverFactory); + + localLogger.Log(PluginLogLevel.Info,"Instantiating the GPS receiver..."); + handles.Gps = gpsReceiverFactory.CreateGpsReceiver(); + + localLogger.Log(PluginLogLevel.Info,"Starting the GPS receiver..."); + handles.Gps.Start(); + + //LOAD BASE DATA -------------------------------------------------------------------------------------------------------------------------------------------------------------- + localLogger.Log(PluginLogLevel.Info,"Querying the storage for known satellite positions..."); + handles.SatellitePositions = handles.DataStorage.UiSatellitesListAll(); + + localLogger.Log(PluginLogLevel.Info,"Checking for the default LNB types..."); + EquipmentUtilities.InsertDefaultLnbTypes(handles.DataStorage); + + localLogger.Log(PluginLogLevel.Info,"Querying the storage for known LNB types..."); + handles.LnbTypes = handles.DataStorage.UiLnbTypesListAll(); + + localLogger.Log(PluginLogLevel.Info,"Checking for the default dish types..."); + EquipmentUtilities.InsertDefaultDishTypes(handles.DataStorage); + + localLogger.Log(PluginLogLevel.Info,"Querying the storage for known Dish types..."); + handles.DishTypes = handles.DataStorage.UiDishTypesListAll(); + + //LOAD TUNER -------------------------------------------------------------------------------------------------------------------------------------------------------------------- + localLogger.Log(PluginLogLevel.Info,"Chcking the Tuner Factory classes..."); + TunerFactoryConnectionManager tunerFactoryConnectionManager = TunerFactoryConnectionManager.GetInstance(); + handles.AllTunerFactories = tunerFactoryConnectionManager.GetKnownFactories(); + int tunerFactory = handles.Ini.ReadValue("startup", "tunerFactory", 0); + KeyValuePair bootingTuner = handles.AllTunerFactories.First(x => x.Key.Id == tunerFactory); + bool isNoTuner = bootingTuner.Key.DisplayName.Equals("No tuner"); + if (isNoTuner) + { + errors.Enqueue("Please not that Skyscraper is currently configured to not use a Tuner Factory Class. This will work, but functionality will be severely limited. Please configure a Tuner Factory Class in order to get the best experience."); + } + + localLogger.Log(PluginLogLevel.Info,"Applying the tuner factory class configuration..:"); + TunerFactoryConnectionManager.ConfigureFactoryFromIni(bootingTuner, handles.Ini); + + List foundTuners = new List(); + localLogger.Log(PluginLogLevel.Info,"Please wait while the Tuner Factory class code is being executed..."); + try + { + handles.StreamReader = bootingTuner.Value.CreateStreamReader(); + try + { + localLogger.Log(PluginLogLevel.Info,"Trying to see whether the tuner factory works..."); + handles.StreamReader.CheckForDVB(); + } + catch (BadImageFormatException e) + { + errors.Enqueue("The configured tuner factory is not suitable for the current processor architecture. Tuning won't work, therefore functionality will be severely limited. Please configure a Tuner Factory Class suitable for this processor architecture in order to get the best experience. If you need to run crazycat69's StreamReader.dll on 64-bit machines, try RemoteStreamReader."); + handles.StreamReader = new NullTunerFactory().CreateStreamReader(); + } + + localLogger.Log(PluginLogLevel.Info, "Checking for your tuners..."); + bool checkForDvbExEx = handles.StreamReader.CheckForDVBExEx((index, name, type) => + { + TunerMetadata tuner = new TunerMetadata(index, name, type); + localLogger.Log(PluginLogLevel.Info, String.Format("Found tuner {0}", name)); + foundTuners.Add(tuner); + }); + if (!checkForDvbExEx) + { + if (!isNoTuner) + localLogger.Log(PluginLogLevel.Error, String.Format("{0} has failed. Tuning won't be possible!", nameof(handles.StreamReader.CheckForDVBExEx))); + } + } + catch (Exception e) + { + localLogger.Log(PluginLogLevel.Error,"Oh dear, it failed."); + errors.Enqueue( + "Please not that the Tuner Factory class code failed to execute. " + + "This won't stop the program from working, but functionality will be severely limited. " + + "Please make sure the Tuner Factory Class is properly configured in order to get the best experience.\n\n" + + "The following went wrong:\n" + e.Message); + handles.StreamReader = new NullTunerFactory().CreateStreamReader(); + } + + + + foreach (TunerMetadata foundTuner in foundTuners) + { + handles.StreamReader.StopDVB(); + + localLogger.Log(PluginLogLevel.Info,String.Format("Starting tuner {0}", foundTuner.Name)); + bool startDvbEx = handles.StreamReader.StartDvbEx(foundTuner.Index); + if (!startDvbEx) + { + localLogger.Log(PluginLogLevel.Error,String.Format("Failed to start {0}", foundTuner.Name)); + Thread.Sleep(1000); + continue; + } + + localLogger.Log(PluginLogLevel.Info, String.Format("Checking capabilities of {0}", foundTuner.Name)); + foundTuner.Caps = handles.StreamReader.GetCaps(); + + byte[] macBuffer = new byte[6]; + localLogger.Log(PluginLogLevel.Info, String.Format("Reading MAC Address of {0}", foundTuner.Name)); + bool mac = handles.StreamReader.GetMAC(macBuffer); + if (!mac) + { + localLogger.Log(PluginLogLevel.Error,String.Format("Failed to read MAC Address of {0}", foundTuner.Name)); + Thread.Sleep(1000); + } + else + { + foundTuner.MacAddress = new PhysicalAddress(macBuffer); + } + + localLogger.Log(PluginLogLevel.Info, String.Format("Stopping {0}", foundTuner.Name)); + bool stopDvb = handles.StreamReader.StopDVB(); + if (!stopDvb) + { + localLogger.Log(PluginLogLevel.Error, String.Format("Failed to stop {0}", foundTuner.Name)); + Thread.Sleep(1000); + continue; + } + + localLogger.Log(PluginLogLevel.Info, String.Format("Querying storage for configuration of {0}...", foundTuner.Name)); + if (handles.DataStorage.UiTunerTestFor(foundTuner)) + { + handles.DataStorage.UiTunerGetConfiguration(foundTuner); + } + + if (handles.Tuners == null) + handles.Tuners = new List(); + handles.Tuners.Add(foundTuner); + } + + localLogger.Log(PluginLogLevel.Info,"Checking the engine Version..."); + string engineProductName = handles.StreamReader.GetEngineName(); + Version engineVersion = handles.StreamReader.GetEngineVersion(); + + if (!engineProductName.Equals("NullStreamReader")) + { + bool finalCaps = handles.StreamReader.CheckForDVB(); + if (!finalCaps) + { + errors.Enqueue("Somehow CheckForDVB failed after a second call."); + } + } + + localLogger.Log(PluginLogLevel.Info,"Qualifying the engine..."); + QualificationToolResultEnum qualification = QualificationTool.QualifyTunerFactory(engineProductName, engineVersion); + switch (qualification) + { + case QualificationToolResultEnum.Good: + break; + case QualificationToolResultEnum.Bad: + errors.Enqueue(String.Format("You are using {0}, Version {1}\nThis version is known to cause issues with skyscraper. You can continue using it, but if it causes issues, you're on your own.", engineProductName, engineVersion)); + break; + case QualificationToolResultEnum.Unknown: + errors.Enqueue(String.Format("You are using {0}, Version {1}\nThis version has not been tested with skyscraper, and might cause some issues. Consider submitting a copy of this version to the author.", engineProductName, engineVersion)); + break; + case QualificationToolResultEnum.PossibleIssues: + errors.Enqueue(String.Format("You are using {0}, Version {1}\nThis version will work, but might have minor issues in some edge cases.", engineProductName, engineVersion)); + break; + default: + errors.Enqueue(String.Format("You are using {0}, Version {1}\nThe Qualification said \"{2}\", but this status is not implemented.\n Possibly your skyscraper Version and your testdrid Version mismatch?", engineProductName, engineVersion, qualification.ToString())); + break; + } + + + SkyscraperGame game = new SkyscraperGame(handles,errors); game.Run(); } } diff --git a/GUIs/skyscraper8.UI.ImGui.MonoGame/SkyscraperGame.cs b/GUIs/skyscraper8.UI.ImGui.MonoGame/SkyscraperGame.cs index 28ce49b..e13cc16 100644 --- a/GUIs/skyscraper8.UI.ImGui.MonoGame/SkyscraperGame.cs +++ b/GUIs/skyscraper8.UI.ImGui.MonoGame/SkyscraperGame.cs @@ -8,6 +8,23 @@ namespace skyscraper8.UI.MonoGame { internal class SkyscraperGame : BaseGame { + public SkyscraperGame(SkyscraperHandleCollection handles, Queue errors) + { + this.Handles = handles; + + while (errors.Count > 0) + { + string dequeue = errors.Dequeue(); + EnqueueUpdateJob(() => + { + _imGuiRenderables.Add(new MessageWindow(dequeue)); + }); + } + } + + public SkyscraperHandleCollection Handles { get; set; } + + private ScreenhackManager screenhackManager; protected override void LoadContent() { @@ -46,11 +63,12 @@ namespace skyscraper8.UI.MonoGame base.Update(gameTime); } + private const int MENU_TEST_ABOUT = 1; private bool MenuTest(int opcode) { switch (opcode) { - case 1: + case MENU_TEST_ABOUT: if (aboutWindow != null) { if (!aboutWindow.WasClosed()) @@ -65,6 +83,9 @@ namespace skyscraper8.UI.MonoGame } private AboutWindow aboutWindow; + + + protected override void ImGuiLayout() { @@ -89,7 +110,7 @@ namespace skyscraper8.UI.MonoGame if (ImGui.BeginMenu("Help")) { - if (ImGui.MenuItem("About",MenuTest(1))) + if (ImGui.MenuItem("About",MenuTest(MENU_TEST_ABOUT))) { EnqueueUpdateJob(() => { diff --git a/GUIs/skyscraper8.UI.ImGui.MonoGame/SkyscraperHandleCollection.cs b/GUIs/skyscraper8.UI.ImGui.MonoGame/SkyscraperHandleCollection.cs new file mode 100644 index 0000000..6c2b295 --- /dev/null +++ b/GUIs/skyscraper8.UI.ImGui.MonoGame/SkyscraperHandleCollection.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using skyscraper5.Skyscraper; +using skyscraper5.Skyscraper.Equipment; +using skyscraper5.Skyscraper.Gps; +using skyscraper5.Skyscraper.IO; +using skyscraper5.Skyscraper.IO.TunerInterface; +using skyscraper8.Skyscraper.Scraper.Storage; + +namespace skyscraper8.UI.MonoGame +{ + internal class SkyscraperHandleCollection + { + public ReadOnlyCollection> AllDataStorages { get; set; } + public ReadOnlyCollection> AllObjectStorages { get; set; } + public Ini Ini { get; set; } + public DataStorage DataStorage { get; set; } + public ObjectStorage ObjectStorage { get; set; } + public IGpsReceiver Gps { get; set; } + public List SatellitePositions { get; set; } + public List LnbTypes { get; set; } + public List DishTypes { get; set; } + public ReadOnlyCollection> AllTunerFactories { get; set; } + public IStreamReader StreamReader { get; set; } + public List Tuners { get; set; } + } +}