diff --git a/Hubs/DiscChangerHub.cs b/Hubs/DiscChangerHub.cs index 87e860c..c49e419 100644 --- a/Hubs/DiscChangerHub.cs +++ b/Hubs/DiscChangerHub.cs @@ -27,12 +27,14 @@ namespace DiscChanger.Hubs public class DiscChangerHub : Hub { public DiscChangerService discChangerService; + public CustomDiscService customDiscService; private readonly Microsoft.Extensions.Logging.ILogger _logger; - public DiscChangerHub(DiscChangerService discChangerService, ILogger logger) + public DiscChangerHub(DiscChangerService discChangerService, CustomDiscService customDiscService, ILogger logger) { _logger = logger; this.discChangerService = discChangerService; + this.customDiscService = customDiscService; } public void Control(string changerKey, string command) @@ -98,7 +100,15 @@ public async Task DeleteDiscs(string changerKey, string discSet) { try { + // Delete from regular changer await discChangerService.Changer(changerKey).DeleteDiscs(discSet); + + // Also delete from custom discs + var slots = Models.DiscChanger.ParseSet(discSet); + foreach (var slot in slots) + { + await customDiscService.DeleteCustomDisc(changerKey, slot.ToString()); + } } catch (Exception e) { diff --git a/Models/CustomDisc.cs b/Models/CustomDisc.cs new file mode 100644 index 0000000..fe8138d --- /dev/null +++ b/Models/CustomDisc.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; + +namespace DiscChanger.Models +{ + /// + /// Represents a custom disc entry stored separately from scanned discs + /// + public class CustomDisc + { + [JsonPropertyName("ChangerKey")] + public string ChangerKey { get; set; } + + [JsonPropertyName("Slot")] + public string Slot { get; set; } + + [JsonPropertyName("DiscType")] + public string DiscType { get; set; } + + [JsonPropertyName("Artist")] + public string Artist { get; set; } + + [JsonPropertyName("Title")] + public string Title { get; set; } + + [JsonPropertyName("CoverArtFileName")] + public string CoverArtFileName { get; set; } + + [JsonPropertyName("Tracks")] + public List Tracks { get; set; } + + [JsonPropertyName("DateTimeAdded")] + public DateTime? DateTimeAdded { get; set; } + + public CustomDisc() + { + Tracks = new List(); + } + + public string ToHtml(string changerName) + { + string HtmlEncode(string s) => System.Web.HttpUtility.HtmlEncode(s); + string HtmlAttributeEncode(string s) => System.Web.HttpUtility.HtmlAttributeEncode(s); + + var afp = !string.IsNullOrEmpty(CoverArtFileName) ? "/CustomCoverArt/" + System.Web.HttpUtility.UrlEncode(CoverArtFileName) : null; + + var slotHtml = HtmlEncode(Slot ?? "--"); + var a = HtmlEncode(Artist ?? String.Empty); + var t = HtmlEncode(Title ?? String.Empty); + + StringBuilder sb = new StringBuilder(@"
")); + sb.Append(@""" data-bs-content="""); + StringBuilder content = new StringBuilder(8192); + + if (Tracks != null && Tracks.Count > 0) + { + content.Append(@""); + foreach (var track in Tracks) + { + content.Append(@""); + } + content.Append(@"
"); + content.Append(track.Position); + content.Append(@""); content.Append(HtmlEncode(track.Title ?? "---")); content.Append(""); + content.Append(track.Length ?? "--"); + content.Append(@"
"); + } + + // Add Go and Edit buttons to content (before encoding) - use single quotes to avoid encoding issues + content.Append(@"
"); + content.Append(@""); + content.Append(@"Edit"); + content.Append(@"
"); + + sb.Append(HtmlAttributeEncode(content.ToString())); + sb.Append(@""" data-changer="""); + sb.Append(ChangerKey); sb.Append(@""" data-slot="""); sb.Append(slotHtml); + sb.Append(@""" data-media-type="""); + sb.Append((DiscType != null && DiscType.ToUpper().Contains("CD")) ? "CD" : ((DiscType != null && (DiscType.ToUpper().Contains("DVD") || DiscType.ToUpper().Contains("BD") || DiscType.ToUpper().Contains("BLU"))) ? "MOVIE" : "OTHER")); + sb.Append(@""">"); + + if (afp != null) + { + sb.Append(""); + } + sb.Append(@"
"); + sb.Append(a); + sb.Append(@"
"); + sb.Append(t); + sb.Append(@"
"); + sb.Append(HtmlEncode(changerName)); sb.Append(':'); sb.Append(slotHtml); + sb.Append(@""); + sb.Append(HtmlEncode(DiscType ?? "-")); + sb.Append("
"); + sb.Append(@"
"); + return sb.ToString(); + } + } + + public class TrackInfo + { + [JsonPropertyName("Position")] + public int Position { get; set; } + + [JsonPropertyName("Title")] + public string Title { get; set; } + + [JsonPropertyName("Length")] + public string Length { get; set; } + } + + /// + /// Container for all custom discs + /// + public class CustomDiscCollection + { + [JsonPropertyName("CustomDiscs")] + public List CustomDiscs { get; set; } + + public CustomDiscCollection() + { + CustomDiscs = new List(); + } + } +} + diff --git a/Models/CustomDiscService.cs b/Models/CustomDiscService.cs new file mode 100644 index 0000000..b98fa26 --- /dev/null +++ b/Models/CustomDiscService.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.AspNetCore.Hosting; + +namespace DiscChanger.Models +{ + /// + /// Service for managing custom discs stored separately from scanned discs + /// + public class CustomDiscService + { + private readonly ILogger _logger; + private readonly IWebHostEnvironment _webHostEnvironment; + private readonly string _customDiscsFilePath; + private CustomDiscCollection _customDiscs; + private readonly object _lockObject = new object(); + + public CustomDiscService(ILogger logger, IWebHostEnvironment webHostEnvironment) + { + _logger = logger; + _webHostEnvironment = webHostEnvironment; + _customDiscsFilePath = Path.Combine(_webHostEnvironment.WebRootPath, "CustomDiscs.json"); + LoadCustomDiscs(); + } + + private void LoadCustomDiscs() + { + try + { + if (File.Exists(_customDiscsFilePath)) + { + string json = File.ReadAllText(_customDiscsFilePath); + _customDiscs = JsonSerializer.Deserialize(json, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); + _logger.LogInformation($"Loaded {_customDiscs.CustomDiscs.Count} custom discs from {_customDiscsFilePath}"); + } + else + { + _customDiscs = new CustomDiscCollection(); + _logger.LogInformation("No custom discs file found, starting with empty collection"); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error loading custom discs"); + _customDiscs = new CustomDiscCollection(); + } + } + + public async Task SaveCustomDiscs() + { + try + { + lock (_lockObject) + { + string json = JsonSerializer.Serialize(_customDiscs, new JsonSerializerOptions + { + WriteIndented = true + }); + File.WriteAllText(_customDiscsFilePath, json); + _logger.LogInformation($"Saved {_customDiscs.CustomDiscs.Count} custom discs to {_customDiscsFilePath}"); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error saving custom discs"); + } + } + + public CustomDisc GetCustomDisc(string changerKey, string slot) + { + return _customDiscs.CustomDiscs.FirstOrDefault(d => d.ChangerKey == changerKey && d.Slot == slot); + } + + public List GetCustomDiscsForChanger(string changerKey) + { + return _customDiscs.CustomDiscs.Where(d => d.ChangerKey == changerKey).ToList(); + } + + public async Task AddOrUpdateCustomDisc(CustomDisc customDisc) + { + lock (_lockObject) + { + // Remove existing custom disc for this slot if it exists + _customDiscs.CustomDiscs.RemoveAll(d => d.ChangerKey == customDisc.ChangerKey && d.Slot == customDisc.Slot); + + // Add the new/updated custom disc + _customDiscs.CustomDiscs.Add(customDisc); + } + + await SaveCustomDiscs(); + } + + public async Task RemoveCustomDisc(string changerKey, string slot) + { + lock (_lockObject) + { + _customDiscs.CustomDiscs.RemoveAll(d => d.ChangerKey == changerKey && d.Slot == slot); + } + + await SaveCustomDiscs(); + } + + public async Task DeleteCustomDisc(string changerKey, string slot) + { + await RemoveCustomDisc(changerKey, slot); + } + + public Dictionary GetAllCustomDiscs() + { + var result = new Dictionary(); + foreach (var disc in _customDiscs.CustomDiscs) + { + string key = $"{disc.ChangerKey}_{disc.Slot}"; + result[key] = disc; + } + return result; + } + } +} + diff --git a/Models/Disc.cs b/Models/Disc.cs index 443ec25..b89de22 100644 --- a/Models/Disc.cs +++ b/Models/Disc.cs @@ -162,25 +162,36 @@ public virtual string ToHtml() } content.Append(@""); } - if (DataMusicBrainz != null) - { - content.Append(@"
"); - var urls = DataMusicBrainz?.URLs; - if (urls != null) - foreach (var url in urls) - { - content.Append(@""); - } - content.Append(@""); - content.Append(@"
"); - } + // URLs section hidden per user request + // if (DataMusicBrainz != null) + // { + // content.Append(@"
"); + // var urls = DataMusicBrainz?.URLs; + // if (urls != null) + // foreach (var url in urls) + // { + // content.Append(@""); + // } + // content.Append(@""); + // content.Append(@"
"); + // } + + // Add Go and Edit buttons to content (before encoding) - use single quotes to avoid encoding issues + content.Append(@"
"); + content.Append(@""); + content.Append(@"Edit"); + content.Append(@"
"); + sb.Append(HtmlAttributeEncode(content.ToString())); sb.Append(@""" data-changer="""); - sb.Append(DiscChanger.Key); sb.Append(@""" data-slot= """); sb.Append(slotHtml); sb.Append(@""">
"); - sb.Append(HtmlEncode(DiscChanger.Name)); sb.Append(':'); sb.Append(slotHtml); - sb.Append(@""); - sb.Append(HtmlEncode(GetDiscType() ?? "-")); - sb.Append("
"); + sb.Append(DiscChanger.Key); sb.Append(@""" data-slot="""); sb.Append(slotHtml); + sb.Append(@""" data-media-type="""); + sb.Append(IsCD() ? "CD" : (IsDVD() || IsBD()) ? "MOVIE" : "OTHER"); + sb.Append(@""">"); if (afp != null) { @@ -190,7 +201,11 @@ public virtual string ToHtml() sb.Append(a); sb.Append(@"
"); sb.Append(t); - sb.Append(@"
"); + sb.Append(@"
"); + sb.Append(HtmlEncode(DiscChanger.Name)); sb.Append(':'); sb.Append(slotHtml); + sb.Append(@""); + sb.Append(HtmlEncode(GetDiscType() ?? "-")); + sb.Append("
"); sb.Append(@""); return sb.ToString(); } diff --git a/Models/MetaDataGD3.cs b/Models/MetaDataGD3.cs index 195945e..cded05f 100644 --- a/Models/MetaDataGD3.cs +++ b/Models/MetaDataGD3.cs @@ -94,15 +94,34 @@ public abstract class Match public static async Task WriteImage(byte[] image, string path, string fileNameBase) { - var imageInfo = Image.Identify(image); - var format = imageInfo.Metadata.DecodedImageFormat; - var ext = format?.FileExtensions?.FirstOrDefault(); - var albumImageFileName = Path.ChangeExtension(fileNameBase, ext); - using (var f = File.Create(Path.Combine(path, albumImageFileName))) + try + { + // Ensure directory exists + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + System.Diagnostics.Debug.WriteLine($"Created directory: {path}"); + } + + var imageInfo = Image.Identify(image); + var format = imageInfo.Metadata.DecodedImageFormat; + var ext = format?.FileExtensions?.FirstOrDefault() ?? "jpg"; + var albumImageFileName = Path.ChangeExtension(fileNameBase, ext); + var fullPath = Path.Combine(path, albumImageFileName); + + using (var f = File.Create(fullPath)) + { + await f.WriteAsync(image); + } + + System.Diagnostics.Debug.WriteLine($"Saved GD3 image: {fullPath}"); + return albumImageFileName; + } + catch (Exception ex) { - await f.WriteAsync(image); + System.Diagnostics.Debug.WriteLine($"ERROR saving GD3 image to {path}/{fileNameBase}: {ex.Message}"); + throw; } - return albumImageFileName; } public class MatchCD : Match { diff --git a/Pages/AddCustomDisc.cshtml b/Pages/AddCustomDisc.cshtml new file mode 100644 index 0000000..418f5ec --- /dev/null +++ b/Pages/AddCustomDisc.cshtml @@ -0,0 +1,127 @@ +@page +@model AddCustomDiscModel +@{ + ViewData["Title"] = Model.IsEditMode ? "Edit Disc" : "Add Custom Disc"; +} + +

@ViewData["Title"]

+ +
+
+ Disc Details + + + +
+ +
+ + + + @if (Model.IsEditMode) + { + Change the slot number to move this disc to a different slot + } +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + @if (!string.IsNullOrEmpty(Model.ExistingCoverArtUrl)) + { +
+ Current cover art +

Upload a new image to replace

+
+ } + +
+ +
+

Tracks

+
+ @if (Model.Tracks != null && Model.Tracks.Count > 0) + { + for (int i = 0; i < Model.Tracks.Count; i++) + { +
+ +
+ Track @Model.Tracks[i].Position +
+
+ + +
+
+ + +
+
+ } + } + else + { +

No tracks yet. Save disc first, then tracks can be edited by clicking Edit button on the disc.

+ } +
+ @if (Model.Tracks != null && Model.Tracks.Count > 0) + { + + } +
+ +
+ + +
+
+
+ + + + diff --git a/Pages/AddCustomDisc.cshtml.cs b/Pages/AddCustomDisc.cshtml.cs new file mode 100644 index 0000000..8d025e4 --- /dev/null +++ b/Pages/AddCustomDisc.cshtml.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.Hosting; +using DiscChanger.Models; + +namespace DiscChanger.Pages +{ + public class AddCustomDiscModel : PageModel + { + private readonly CustomDiscService customDiscService; + private readonly DiscChangerService discChangerService; + private readonly IWebHostEnvironment webHostEnvironment; + + public AddCustomDiscModel(CustomDiscService customDiscService, DiscChangerService discChangerService, IWebHostEnvironment webHostEnvironment) + { + this.customDiscService = customDiscService; + this.discChangerService = discChangerService; + this.webHostEnvironment = webHostEnvironment; + } + + [BindProperty(SupportsGet = true)] + public string ChangerKey { get; set; } + + [BindProperty] + public string Slot { get; set; } + + [BindProperty] + public string DiscType { get; set; } + + [BindProperty] + public string Artist { get; set; } + + [BindProperty] + public string Title { get; set; } + + [BindProperty] + public IFormFile CoverArt { get; set; } + + [BindProperty] + public List Tracks { get; set; } + + [BindProperty] + public string OriginalSlot { get; set; } + + public string ExistingCoverArtUrl { get; set; } + public bool IsEditMode { get; set; } + + public async Task OnGetAsync(string changerKey, string slot) + { + ChangerKey = changerKey; + Slot = slot; + + var changer = discChangerService.Changer(ChangerKey); + if (changer == null) + { + ModelState.AddModelError("", "Invalid changer"); + return RedirectToPage("Index"); + } + + // Check if we're editing an existing custom disc + var existingCustomDisc = customDiscService.GetCustomDisc(ChangerKey, Slot); + if (existingCustomDisc != null) + { + IsEditMode = true; + OriginalSlot = Slot; // Track original slot for moves + Artist = existingCustomDisc.Artist; + Title = existingCustomDisc.Title; + DiscType = existingCustomDisc.DiscType; + + if (!string.IsNullOrEmpty(existingCustomDisc.CoverArtFileName)) + { + ExistingCoverArtUrl = "/CustomCoverArt/" + System.Web.HttpUtility.UrlEncode(existingCustomDisc.CoverArtFileName); + } + + // Load tracks + if (existingCustomDisc.Tracks != null) + { + Tracks = existingCustomDisc.Tracks.ToList(); + } + } + // Check if editing a scanned disc (copy data from it) + else if (!string.IsNullOrEmpty(Slot) && changer.Discs.TryGetValue(Slot, out Disc scannedDisc)) + { + IsEditMode = true; + OriginalSlot = Slot; // Track original slot for moves + Artist = scannedDisc.GetArtist(); + Title = scannedDisc.getTitle(); + DiscType = scannedDisc.GetDiscType(); + + // Load existing cover art from scanned disc + if (scannedDisc.DataGD3Match?.GetArtFileURL() != null) + { + ExistingCoverArtUrl = scannedDisc.DataGD3Match.GetArtFileURL(); + } + else if (scannedDisc.DataMusicBrainz?.GetArtFileURL() != null) + { + ExistingCoverArtUrl = scannedDisc.DataMusicBrainz.GetArtFileURL(); + } + + // Load tracks from scanned disc + var existingTracks = scannedDisc.GetTracks(); + if (existingTracks != null) + { + Tracks = existingTracks.Select(t => new TrackInfo + { + Position = t.Position ?? 0, + Title = t.Title, + Length = t.Length?.ToString(@"h\:mm\:ss") ?? "" + }).ToList(); + } + } + + return Page(); + } + + public async Task OnPostAsync(string op) + { + if (op == "cancel") + { + return RedirectToPage("Index"); + } + + if (!ModelState.IsValid || string.IsNullOrEmpty(Title)) + { + return Page(); + } + + var changer = discChangerService.Changer(ChangerKey); + if (changer == null) + { + ModelState.AddModelError("", "Invalid changer"); + return Page(); + } + + // Auto-assign slot if not provided + if (string.IsNullOrEmpty(Slot)) + { + var availableSlots = changer.GetAvailableSlots(); + var slots = DiscChanger.Models.DiscChanger.ParseSet(availableSlots); + Slot = slots.First().ToString(); + } + else + { + // Validate slot number + if (!int.TryParse(Slot, out int slotNum) || slotNum < 1) + { + ModelState.AddModelError("Slot", "Slot must be a positive number"); + return Page(); + } + + // If editing and slot changed, check if new slot is available + if (!string.IsNullOrEmpty(OriginalSlot) && OriginalSlot != Slot) + { + // Check if target slot has a custom disc + if (customDiscService.GetCustomDisc(ChangerKey, Slot) != null) + { + ModelState.AddModelError("Slot", $"Slot {Slot} is already occupied by another custom disc."); + return Page(); + } + // Check if target slot has a scanned disc + if (changer.Discs.ContainsKey(Slot)) + { + ModelState.AddModelError("Slot", $"Slot {Slot} is already occupied by a scanned disc."); + return Page(); + } + } + } + + // Create custom disc + var customDisc = new CustomDisc + { + ChangerKey = ChangerKey, + Slot = Slot, + DiscType = DiscType ?? "CD", + Artist = Artist, + Title = Title, + DateTimeAdded = DateTime.Now + }; + + // Handle cover art upload + if (CoverArt != null && CoverArt.Length > 0) + { + var coverArtDir = Path.Combine(webHostEnvironment.WebRootPath, "CustomCoverArt"); + if (!Directory.Exists(coverArtDir)) + { + Directory.CreateDirectory(coverArtDir); + } + + var extension = Path.GetExtension(CoverArt.FileName); + var fileName = $"{ChangerKey}_{Slot}_{DateTime.Now.Ticks}{extension}"; + var filePath = Path.Combine(coverArtDir, fileName); + + using (var stream = new FileStream(filePath, FileMode.Create)) + { + await CoverArt.CopyToAsync(stream); + } + customDisc.CoverArtFileName = fileName; + } + else + { + // Preserve existing cover art filename if editing + var slotToCheck = !string.IsNullOrEmpty(OriginalSlot) ? OriginalSlot : Slot; + var existingCustomDisc = customDiscService.GetCustomDisc(ChangerKey, slotToCheck); + if (existingCustomDisc != null && !string.IsNullOrEmpty(existingCustomDisc.CoverArtFileName)) + { + customDisc.CoverArtFileName = existingCustomDisc.CoverArtFileName; + } + } + + // Handle tracks - preserve existing tracks if not explicitly editing them + var hasTrackEdits = Tracks != null && Tracks.Any(t => !string.IsNullOrWhiteSpace(t.Title) || !string.IsNullOrWhiteSpace(t.Length)); + + if (hasTrackEdits) + { + // User provided track data - update tracks + customDisc.Tracks = new List(); + foreach (var track in Tracks) + { + // Only add tracks that have at least a title or length + if (!string.IsNullOrWhiteSpace(track.Title) || !string.IsNullOrWhiteSpace(track.Length)) + { + customDisc.Tracks.Add(track); + } + } + } + else + { + // No track edits provided - preserve existing tracks + // Check from OriginalSlot if moving, otherwise from current Slot + var slotToCheck = !string.IsNullOrEmpty(OriginalSlot) ? OriginalSlot : Slot; + var existingCustomDisc = customDiscService.GetCustomDisc(ChangerKey, slotToCheck); + if (existingCustomDisc != null && existingCustomDisc.Tracks != null) + { + // Preserve tracks from existing custom disc + customDisc.Tracks = existingCustomDisc.Tracks; + } + else + { + // Check if there's a regular disc in the changer we're converting from + var sourceChanger = discChangerService.Changer(ChangerKey); + if (sourceChanger != null && sourceChanger.Discs.TryGetValue(slotToCheck, out Disc existingDisc)) + { + // Get tracks from the original disc and convert to TrackInfo format + var originalTracks = existingDisc.GetTracks(); + if (originalTracks != null) + { + customDisc.Tracks = originalTracks.Select(t => new TrackInfo + { + Position = t.Position ?? 0, + Title = t.Title ?? "", + Length = t.Length?.ToString(@"h\:mm\:ss") ?? "" + }).ToList(); + } + } + } + } + + // If slot changed, delete from original slot + if (!string.IsNullOrEmpty(OriginalSlot) && OriginalSlot != Slot) + { + await customDiscService.DeleteCustomDisc(ChangerKey, OriginalSlot); + // Also remove from scanned discs if present + if (changer.Discs.TryRemove(OriginalSlot, out Disc removedDisc)) + { + discChangerService.needsSaving = true; + } + } + + // Save to CustomDiscs.json + await customDiscService.AddOrUpdateCustomDisc(customDisc); + + return RedirectToPage("Index"); + } + } +} diff --git a/Pages/DiscChangerConfig.cshtml b/Pages/DiscChangerConfig.cshtml index 29a9b6c..c1cc275 100644 --- a/Pages/DiscChangerConfig.cshtml +++ b/Pages/DiscChangerConfig.cshtml @@ -41,7 +41,7 @@ @Html.DropDownListFor(m => m.Connection, new SelectList(Model.ConnectionTypes), Model.OnChangeSubmit) } - @if (Model.Connection == global::DiscChanger.Models.DiscChanger.CONNECTION_SERIAL_PORT) + @if (!String.IsNullOrEmpty(Model.Connection) && Model.Connection == global::DiscChanger.Models.DiscChanger.CONNECTION_SERIAL_PORT) { @Html.DropDownListFor(m => m.PortName, diff --git a/Pages/DiscChangerConfig.cshtml.cs b/Pages/DiscChangerConfig.cshtml.cs index ee312b9..65077c1 100644 --- a/Pages/DiscChangerConfig.cshtml.cs +++ b/Pages/DiscChangerConfig.cshtml.cs @@ -107,18 +107,21 @@ public async Task OnPostAsync(string op = null) string nh = null; int? np = null; bool valid = !String.IsNullOrEmpty(Type) && !String.IsNullOrEmpty(Name) && !String.IsNullOrEmpty(Connection); - switch (Connection) + if (!String.IsNullOrEmpty(Connection)) { - case DiscChanger.Models.DiscChanger.CONNECTION_SERIAL_PORT: - if (HardwareFlowControl != null) - hfc = Boolean.Parse(HardwareFlowControl); - pn = PortName; - valid = valid && !String.IsNullOrEmpty(pn); - break; - case DiscChanger.Models.DiscChanger.CONNECTION_NETWORK: - nh = NetworkHost?.Trim(); np = NetworkPort; - valid = valid && !String.IsNullOrEmpty(nh) && np > 1; - break; + switch (Connection) + { + case DiscChanger.Models.DiscChanger.CONNECTION_SERIAL_PORT: + if (HardwareFlowControl != null) + hfc = Boolean.Parse(HardwareFlowControl); + pn = PortName; + valid = valid && !String.IsNullOrEmpty(pn); + break; + case DiscChanger.Models.DiscChanger.CONNECTION_NETWORK: + nh = NetworkHost?.Trim(); np = NetworkPort; + valid = valid && !String.IsNullOrEmpty(nh) && np > 1; + break; + } } switch (op) { @@ -136,7 +139,9 @@ public async Task OnPostAsync(string op = null) return RedirectToPage("Index"); case "Test": if (valid) + { this.TestResult = await discChangerService.Test(Key, Type, Connection, CommandMode, pn, hfc, nh, np); + } break; } updateModel(Key); diff --git a/Pages/Index.cshtml b/Pages/Index.cshtml index 4a7dec7..2a15de3 100644 --- a/Pages/Index.cshtml +++ b/Pages/Index.cshtml @@ -1,6 +1,7 @@ @page @model IndexModel @inject DiscChangerService dcs +@inject CustomDiscService customDiscService @{ ViewData["Title"] = "DiscChanger.NET " + DiscChangerService.Version?.ToString()??"--"; ViewData["Description"] = "Disc Changer Management using ASP.NET Core"; @@ -9,19 +10,78 @@ @{var discDisplaySize = Request.Cookies["DiscDisplaySize"] ?? "15"; } -