Skip to content

Commit

Permalink
Update to 1.3.3 with better handling of WAV files that do have CART c…
Browse files Browse the repository at this point in the history
…hunk 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.
  • Loading branch information
kcbieng committed May 12, 2023
1 parent 2c558dc commit 6f2da9d
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 51 deletions.
15 changes: 15 additions & 0 deletions WavFileHandler/App.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="WavFileHandler.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<userSettings>
<WavFileHandler.Properties.Settings>
<setting name="SourcePath" serializeAs="String">
<value />
</setting>
<setting name="DestinationPath" serializeAs="String">
<value />
</setting>
</WavFileHandler.Properties.Settings>
</userSettings>
</configuration>
24 changes: 22 additions & 2 deletions WavFileHandler/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand All @@ -35,8 +37,9 @@ private set
public MainForm()
{
InitializeComponent();
this.Load += MainForm_Load;
this.FormClosing += MainForm_FormClosing;
SetStatusLabelText("Not Started");

_processedFiles = new ConcurrentDictionary<string, DateTime>(); // Initialize the dictionary
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
}

}
}
2 changes: 1 addition & 1 deletion WavFileHandler/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
46 changes: 33 additions & 13 deletions WavFileHandler/Properties/Settings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 11 additions & 6 deletions WavFileHandler/Properties/Settings.settings
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="WavFileHandler.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="SourcePath" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="DestinationPath" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>
28 changes: 28 additions & 0 deletions WavFileHandler/Settings.cs
Original file line number Diff line number Diff line change
@@ -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.
}
}
}
1 change: 1 addition & 0 deletions WavFileHandler/WavFileHandler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CartChunk.cs" />
<Compile Include="Settings.cs" />
<Compile Include="WavFileInfoForm.cs">
<SubType>Form</SubType>
</Compile>
Expand Down
99 changes: 70 additions & 29 deletions WavFileHandler/WavFileUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.IO;
using System.Text;


namespace WavFileHandler
{
public static class WavFileUtils
Expand All @@ -13,53 +12,81 @@ 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;
}

// 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
Expand All @@ -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;
}
}
}

0 comments on commit 6f2da9d

Please sign in to comment.