From 6f2da9dea999f0ad85f23d2d374c17cd798caa59 Mon Sep 17 00:00:00 2001
From: kcbieng <126266783+kcbieng@users.noreply.github.com>
Date: Fri, 12 May 2023 16:52:25 -0500
Subject: [PATCH] Update to 1.3.3 with better handling of WAV files that do
have CART chunk data.
Added "tryReadBytes" method to the WavFileUtils that checks to see if there are enough bytes left in the file to read the field.
Added Settings.cs to save sourcePath and destinationPath across runs for ease of use.
---
WavFileHandler/App.config | 15 +++
WavFileHandler/MainForm.cs | 24 ++++-
WavFileHandler/Properties/AssemblyInfo.cs | 2 +-
.../Properties/Settings.Designer.cs | 46 ++++++---
WavFileHandler/Properties/Settings.settings | 17 ++--
WavFileHandler/Settings.cs | 28 ++++++
WavFileHandler/WavFileHandler.csproj | 1 +
WavFileHandler/WavFileUtils.cs | 99 +++++++++++++------
8 files changed, 181 insertions(+), 51 deletions(-)
create mode 100644 WavFileHandler/Settings.cs
diff --git a/WavFileHandler/App.config b/WavFileHandler/App.config
index 56efbc7..90a5234 100644
--- a/WavFileHandler/App.config
+++ b/WavFileHandler/App.config
@@ -1,6 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WavFileHandler/MainForm.cs b/WavFileHandler/MainForm.cs
index 1698bab..e3941e8 100644
--- a/WavFileHandler/MainForm.cs
+++ b/WavFileHandler/MainForm.cs
@@ -5,6 +5,7 @@
using System.Threading.Tasks;
using System.Windows.Forms;
using WavFileHandler; // Add this to reference WavFileUtils
+using WavFileHandler.Properties;
using System.Collections.Concurrent; // Add this to use ConcurrentDictionary
using System.Windows.Forms.VisualStyles;
@@ -19,6 +20,7 @@ public partial class MainForm : Form
private int _processMP3FileCounter = 0; //Count MP3s Processed
private static string _logFilePath = "log.txt";
+
public static string LogFilePath
{
get
@@ -35,8 +37,9 @@ private set
public MainForm()
{
InitializeComponent();
+ this.Load += MainForm_Load;
+ this.FormClosing += MainForm_FormClosing;
SetStatusLabelText("Not Started");
-
_processedFiles = new ConcurrentDictionary(); // Initialize the dictionary
}
@@ -280,7 +283,11 @@ void UpdateCartChunkEndDate(FileStream stream)
try
{
CartChunk cartChunk = WavFileUtils.ReadCartChunkData(stream);
- if (cartChunk != null)
+ if (cartChunk == null)
+ {
+ LogMessage($"File does not contain CART chunk data.");
+ return;
+ }
{
// Get the next Sunday date
DateTime nextSunday = GetNextSunday(cartChunk.StartDate);
@@ -371,5 +378,18 @@ private void UpdateLogDisplay(string message)
SetStatusLabelText($"Error Updating Log Display: {ex.Message}");
}
}
+ private void MainForm_Load(object sender, EventArgs e)
+ {
+ txtSource.Text = Settings.Default.SourcePath;
+ txtDestination.Text = Settings.Default.DestinationPath;
+ }
+
+ private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ Settings.Default.SourcePath = txtSource.Text;
+ Settings.Default.DestinationPath = txtDestination.Text;
+ Settings.Default.Save();
+ }
+
}
}
diff --git a/WavFileHandler/Properties/AssemblyInfo.cs b/WavFileHandler/Properties/AssemblyInfo.cs
index 33e1b3f..3b6d575 100644
--- a/WavFileHandler/Properties/AssemblyInfo.cs
+++ b/WavFileHandler/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.3.2.0")]
+[assembly: AssemblyVersion("1.3.3.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/WavFileHandler/Properties/Settings.Designer.cs b/WavFileHandler/Properties/Settings.Designer.cs
index 1fb9072..90116b4 100644
--- a/WavFileHandler/Properties/Settings.Designer.cs
+++ b/WavFileHandler/Properties/Settings.Designer.cs
@@ -8,23 +8,43 @@
//
//------------------------------------------------------------------------------
-namespace WavFileHandler.Properties
-{
-
-
+namespace WavFileHandler.Properties {
+
+
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
- internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
- {
-
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
- public static Settings Default
- {
- get
- {
+
+ public static Settings Default {
+ get {
return defaultInstance;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string SourcePath {
+ get {
+ return ((string)(this["SourcePath"]));
+ }
+ set {
+ this["SourcePath"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string DestinationPath {
+ get {
+ return ((string)(this["DestinationPath"]));
+ }
+ set {
+ this["DestinationPath"] = value;
+ }
+ }
}
}
diff --git a/WavFileHandler/Properties/Settings.settings b/WavFileHandler/Properties/Settings.settings
index 3964565..1f11e03 100644
--- a/WavFileHandler/Properties/Settings.settings
+++ b/WavFileHandler/Properties/Settings.settings
@@ -1,7 +1,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WavFileHandler/Settings.cs b/WavFileHandler/Settings.cs
new file mode 100644
index 0000000..f0451e6
--- /dev/null
+++ b/WavFileHandler/Settings.cs
@@ -0,0 +1,28 @@
+namespace WavFileHandler.Properties {
+
+
+ // This class allows you to handle specific events on the settings class:
+ // The SettingChanging event is raised before a setting's value is changed.
+ // The PropertyChanged event is raised after a setting's value is changed.
+ // The SettingsLoaded event is raised after the setting values are loaded.
+ // The SettingsSaving event is raised before the setting values are saved.
+ internal sealed partial class Settings {
+
+ public Settings() {
+ // // To add event handlers for saving and changing settings, uncomment the lines below:
+ //
+ // this.SettingChanging += this.SettingChangingEventHandler;
+ //
+ // this.SettingsSaving += this.SettingsSavingEventHandler;
+ //
+ }
+
+ private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
+ // Add code to handle the SettingChangingEvent event here.
+ }
+
+ private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
+ // Add code to handle the SettingsSaving event here.
+ }
+ }
+}
diff --git a/WavFileHandler/WavFileHandler.csproj b/WavFileHandler/WavFileHandler.csproj
index c65035e..19ffe9e 100644
--- a/WavFileHandler/WavFileHandler.csproj
+++ b/WavFileHandler/WavFileHandler.csproj
@@ -62,6 +62,7 @@
+
Form
diff --git a/WavFileHandler/WavFileUtils.cs b/WavFileHandler/WavFileUtils.cs
index 4e294f3..7d6b97c 100644
--- a/WavFileHandler/WavFileUtils.cs
+++ b/WavFileHandler/WavFileUtils.cs
@@ -3,7 +3,6 @@
using System.IO;
using System.Text;
-
namespace WavFileHandler
{
public static class WavFileUtils
@@ -13,14 +12,14 @@ public static CartChunk ReadCartChunkData(FileStream stream)
stream.Position = 0;
using (BinaryReader reader = new BinaryReader(stream, Encoding.ASCII, true))
{
- // Read the RIFF header
- if (Encoding.ASCII.GetString(reader.ReadBytes(4)) != "RIFF")
+ if (!TryReadBytes(reader, 4, out byte[] riffBytes) || Encoding.ASCII.GetString(riffBytes) != "RIFF")
{
return null;
}
reader.ReadInt32(); // Skip chunk size
- if (Encoding.ASCII.GetString(reader.ReadBytes(4)) != "WAVE")
+
+ if (!TryReadBytes(reader, 4, out byte[] waveBytes) || Encoding.ASCII.GetString(waveBytes) != "WAVE")
{
return null;
}
@@ -28,38 +27,66 @@ public static CartChunk ReadCartChunkData(FileStream stream)
// Search for the CART chunk
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
- string chunkID = Encoding.ASCII.GetString(reader.ReadBytes(4));
+ if (!TryReadBytes(reader, 4, out byte[] chunkIDBytes))
+ {
+ return null;
+ }
+
+ string chunkID = Encoding.ASCII.GetString(chunkIDBytes);
int chunkSize = reader.ReadInt32();
if (chunkID == "cart")
{
- string[] allowedFormats = { "yyyy-MM-dd", "yyyy/MM/dd" };
- // Read the CART chunk data
+ string[] allowedFormats = { "yyyy-MM-dd", "yyyy/MM/dd" };
CartChunk cartChunk = new CartChunk();
- cartChunk.Version = Encoding.ASCII.GetString(reader.ReadBytes(4));
- cartChunk.Title = Encoding.ASCII.GetString(reader.ReadBytes(64)).TrimEnd('\0');
- cartChunk.Artist = Encoding.ASCII.GetString(reader.ReadBytes(64)).TrimEnd('\0');
- cartChunk.CutID = Encoding.ASCII.GetString(reader.ReadBytes(64)).TrimEnd('\0');
- cartChunk.ClientID = Encoding.ASCII.GetString(reader.ReadBytes(64)).TrimEnd('\0');
- cartChunk.Category = Encoding.ASCII.GetString(reader.ReadBytes(64)).TrimEnd('\0');
- cartChunk.Classification = Encoding.ASCII.GetString(reader.ReadBytes(64)).TrimEnd('\0');
- cartChunk.OutCue = Encoding.ASCII.GetString(reader.ReadBytes(64)).TrimEnd('\0');
+
+ if (!TryReadBytes(reader, 4, out byte[] versionBytes)) return null;
+ cartChunk.Version = Encoding.ASCII.GetString(versionBytes);
+
+ if (!TryReadBytes(reader, 64, out byte[] titleBytes)) return null;
+ cartChunk.Title = Encoding.ASCII.GetString(titleBytes).TrimEnd('\0');
+
+ if (!TryReadBytes(reader, 64, out byte[] artistBytes)) return null;
+ cartChunk.Artist = Encoding.ASCII.GetString(artistBytes).TrimEnd('\0');
+
+ if (!TryReadBytes(reader, 64, out byte[] cutIDBytes)) return null;
+ cartChunk.CutID = Encoding.ASCII.GetString(cutIDBytes).TrimEnd('\0');
+
+ if (!TryReadBytes(reader, 64, out byte[] clientIDBytes)) return null;
+ cartChunk.ClientID = Encoding.ASCII.GetString(clientIDBytes).TrimEnd('\0');
+
+ if (!TryReadBytes(reader, 64, out byte[] categoryBytes)) return null;
+ cartChunk.Category = Encoding.ASCII.GetString(categoryBytes).TrimEnd('\0');
+
+ if (!TryReadBytes(reader, 64, out byte[] classificationBytes)) return null;
+ cartChunk.Classification = Encoding.ASCII.GetString(classificationBytes).TrimEnd('\0');
+
+ if (!TryReadBytes(reader, 64, out byte[] outCueBytes)) return null;
+ cartChunk.OutCue = Encoding.ASCII.GetString(outCueBytes).TrimEnd('\0');
+
cartChunk.StartDatePosition = reader.BaseStream.Position;
- string startDateString = Encoding.ASCII.GetString(reader.ReadBytes(10));
- //Console.WriteLine($"Trying to parse StartDate: '{startDateString}'");
- cartChunk.StartDate = DateTime.ParseExact(startDateString, allowedFormats, CultureInfo.InvariantCulture, DateTimeStyles.None);
+ if (!TryReadBytes(reader, 10, out byte[] startDateBytes)) return null;
+ cartChunk.StartDate = DateTime.ParseExact(Encoding.ASCII.GetString(startDateBytes), allowedFormats, CultureInfo.InvariantCulture, DateTimeStyles.None);
+
cartChunk.StartTimePosition = reader.BaseStream.Position;
- string startTimeString = Encoding.ASCII.GetString(reader.ReadBytes(8));
- cartChunk.EndDatePosition = reader.BaseStream.Position;
- string endDateString = Encoding.ASCII.GetString(reader.ReadBytes(10));
- //Console.WriteLine($"Trying to parse EndDate: '{endDateString}'");
- cartChunk.EndDate = DateTime.ParseExact(endDateString, allowedFormats, CultureInfo.InvariantCulture, DateTimeStyles.None);
+ if (!TryReadBytes(reader, 8, out byte[] startTimeBytes)) return null;
+
+ cartChunk.EndDatePosition = reader.BaseStream.Position;
+ if (!TryReadBytes(reader, 10, out byte[] endDateBytes)) return null;
+ cartChunk.EndDate = DateTime.ParseExact(Encoding.ASCII.GetString(endDateBytes), allowedFormats, CultureInfo.InvariantCulture, DateTimeStyles.None);
+
cartChunk.EndTimePosition = reader.BaseStream.Position;
- string endTimeString = Encoding.ASCII.GetString(reader.ReadBytes(8));
- //cartChunk.EndDate = DateTime.ParseExact(Encoding.ASCII.GetString(reader.ReadBytes(10)), "yyyy/MM/dd", null);
- cartChunk.ProducerAppID = Encoding.ASCII.GetString(reader.ReadBytes(64)).TrimEnd('\0');
- cartChunk.ProducerAppVersion = Encoding.ASCII.GetString(reader.ReadBytes(64)).TrimEnd('\0');
- cartChunk.UserDef = Encoding.ASCII.GetString(reader.ReadBytes(64)).TrimEnd('\0');
+ if (!TryReadBytes(reader, 8, out byte[] endTimeBytes)) return null;
+
+ if (!TryReadBytes(reader, 64, out byte[] producerAppIDBytes)) return null;
+ cartChunk.ProducerAppID = Encoding.ASCII.GetString(producerAppIDBytes).TrimEnd('\0');
+
+ if (!TryReadBytes(reader, 64, out byte[] producerAppVersionBytes)) return null;
+ cartChunk.ProducerAppVersion = Encoding.ASCII.GetString(producerAppVersionBytes).TrimEnd('\0');
+
+ if (!TryReadBytes(reader, 64, out byte[] userDefBytes)) return null;
+ cartChunk.UserDef = Encoding.ASCII.GetString(userDefBytes).TrimEnd('\0');
+
return cartChunk;
}
else
@@ -68,10 +95,24 @@ public static CartChunk ReadCartChunkData(FileStream stream)
reader.BaseStream.Seek(chunkSize, SeekOrigin.Current);
}
}
-
}
return null;
}
+
+ private static bool TryReadBytes(BinaryReader reader, int length, out byte[] result)
+ {
+ result = null;
+
+ if (reader.BaseStream.Length - reader.BaseStream.Position < length)
+ {
+ // Not enough data left to read
+ return false;
+ }
+
+ result = reader.ReadBytes(length);
+ return true;
+ }
}
}
+