diff --git a/src/Acoustics.Tools/Audio/AbstractUtility.cs b/src/Acoustics.Tools/Audio/AbstractUtility.cs index 77408758e..c4eeb0b9e 100644 --- a/src/Acoustics.Tools/Audio/AbstractUtility.cs +++ b/src/Acoustics.Tools/Audio/AbstractUtility.cs @@ -271,12 +271,14 @@ protected void CheckExe(FileInfo file, string expectedFileName) if (file == null) { - throw new ArgumentNullException(nameof(file)); + throw new ArgumentNullException( + nameof(file), + $"Expected path to binary with file name {expectedFileName} but was supplied with null."); } if (!File.Exists(file.FullName)) { - throw new FileNotFoundException("Could not find exe: " + file.FullName, file.FullName); + throw new FileNotFoundException("Could not find binary: " + file.FullName, file.FullName); } if (!file.Name.Contains(expectedFileName)) diff --git a/src/Acoustics.Tools/Audio/AudioFormatNotSupportedException.cs b/src/Acoustics.Tools/Audio/AudioFormatNotSupportedException.cs new file mode 100644 index 000000000..5998ce3d1 --- /dev/null +++ b/src/Acoustics.Tools/Audio/AudioFormatNotSupportedException.cs @@ -0,0 +1,16 @@ +// +// All code in this file and all associated files are the copyright and property of the QUT Ecoacoustics Research Group (formerly MQUTeR, and formerly QUT Bioacoustics Research Group). +// + +namespace Acoustics.Tools.Audio +{ + using System; + + public class AudioFormatNotSupportedException : NotSupportedException + { + public AudioFormatNotSupportedException(string message) + : base(message) + { + } + } +} diff --git a/src/Acoustics.Tools/Audio/MasterAudioUtility.cs b/src/Acoustics.Tools/Audio/MasterAudioUtility.cs index 7273ee575..fefb55194 100644 --- a/src/Acoustics.Tools/Audio/MasterAudioUtility.cs +++ b/src/Acoustics.Tools/Audio/MasterAudioUtility.cs @@ -310,6 +310,11 @@ public override AudioUtilityInfo Info(FileInfo source) if (mediaType == MediaTypes.MediaTypeWavpack) { + if (this.wvunpackUtility == null) + { + throw new AudioFormatNotSupportedException(WavPackAudioUtility.MissingBinary); + } + info = this.Combine(this.wvunpackUtility.Info(source), this.ffmpegUtility.Info(source)); } else if (mediaType == MediaTypes.MediaTypeMp3 || mediaType == MediaTypes.MediaTypeWav) @@ -399,11 +404,19 @@ protected override AudioUtilityInfo GetInfo(FileInfo source, ProcessRunner proce /// protected override void CheckRequestValid(FileInfo source, string sourceMimeType, FileInfo output, string outputMediaType, AudioUtilityRequest request) { - // no restrictions + if (this.wvunpackUtility == null) + { + throw new AudioFormatNotSupportedException(WavPackAudioUtility.MissingBinary); + } } private FileInfo SegmentWavpackToWav(FileInfo source, AudioUtilityRequest request) { + if (this.wvunpackUtility == null) + { + throw new AudioFormatNotSupportedException(WavPackAudioUtility.MissingBinary); + } + // use a temp file for wvunpack. var wavunpackTempFile = TempFileHelper.NewTempFile(this.TemporaryFilesDirectory, MediaTypes.GetExtension(MediaTypes.MediaTypeWav)); diff --git a/src/Acoustics.Tools/Audio/WavPackAudioUtility.cs b/src/Acoustics.Tools/Audio/WavPackAudioUtility.cs index e014f6b83..c099659ec 100644 --- a/src/Acoustics.Tools/Audio/WavPackAudioUtility.cs +++ b/src/Acoustics.Tools/Audio/WavPackAudioUtility.cs @@ -41,6 +41,8 @@ public class WavPackAudioUtility : AbstractAudioUtility, IAudioUtility // -w = regenerate .wav header (ignore RIFF data in file) */ + public const string MissingBinary = "Converting from WavPack is not supported because we cannot find a wvunpack binary."; + private const string ArgsDefault = " -m -q -w "; private const string ArgsSkip = " --skip={0} "; private const string ArgsUtil = " --until={0}{1} "; @@ -53,10 +55,14 @@ public class WavPackAudioUtility : AbstractAudioUtility, IAudioUtility /// The wav Unpack. /// /// + /// If the provided binary does not exist. /// /// + /// If is null. + /// + /// + /// If does contain the string "wavUnpack". /// - /// wavUnpack public WavPackAudioUtility(FileInfo wavUnpack) { this.CheckExe(wavUnpack, "wvunpack"); @@ -73,10 +79,14 @@ public WavPackAudioUtility(FileInfo wavUnpack) /// The wav Unpack. /// /// + /// If the provided binary does not exist. /// /// + /// If is null. + /// + /// + /// If does contain the string "wavUnpack". /// - /// wavUnpack public WavPackAudioUtility(FileInfo wavUnpack, DirectoryInfo temporaryFilesDirectory) { this.CheckExe(wavUnpack, "wvunpack"); @@ -128,7 +138,7 @@ protected override string ConstructModifyArgs(FileInfo source, FileInfo output, // only deals with start and end, does not do anything with sampling, channels or bit rate. if (request.OffsetStart.HasValue || request.OffsetEnd.HasValue) { - + if (request.OffsetStart.HasValue && request.OffsetStart.Value > TimeSpan.Zero) { sb.AppendFormat(ArgsSkip, FormatTimeSpan(request.OffsetStart.Value)); diff --git a/src/AnalysisPrograms/CheckEnvironment.cs b/src/AnalysisPrograms/CheckEnvironment.cs index ae6c44437..310873afe 100644 --- a/src/AnalysisPrograms/CheckEnvironment.cs +++ b/src/AnalysisPrograms/CheckEnvironment.cs @@ -25,6 +25,7 @@ public class CheckEnvironment private int Execute(Arguments arguments) { var errors = new List(); + var warnings = new List(); Log.Info("Checking required executables and libraries can be found and loaded"); @@ -49,6 +50,11 @@ private int Execute(Arguments arguments) errors.Add(ex.Message); } + if (AppConfigHelper.WvunpackExe == null) + { + warnings.Add("Cannot find wvunpack - we'll be unable to process any wavpack files."); + } + if (MainEntry.CheckForDataAnnotations() is string message) { errors.Add(message); @@ -60,6 +66,11 @@ private int Execute(Arguments arguments) errors.Add($"We no longer use Mono with ${Meta.Name}. DO NOT prefix the {Meta.Name} prefix with `mono`."); } + foreach (var warning in warnings) + { + Log.Warn(warning); + } + // don't have much more to check at the current time if (errors.Count == 0) { diff --git a/tests/Acoustics.Test/Tools/MasterAudioUtilityTests.cs b/tests/Acoustics.Test/Tools/MasterAudioUtilityTests.cs index b7bdfd851..18bc6e256 100644 --- a/tests/Acoustics.Test/Tools/MasterAudioUtilityTests.cs +++ b/tests/Acoustics.Test/Tools/MasterAudioUtilityTests.cs @@ -343,7 +343,7 @@ public void ValidatesNonExistingExePaths() public void ValidatesNullExePaths() { TestHelper.ExceptionMatches( - () => new FfmpegAudioUtility(null,null), "Value cannot be null"); + () => new FfmpegAudioUtility(null, null), "Value cannot be null"); //TestHelper.ExceptionMatches( // () => new Mp3SpltAudioUtility(null), "Value cannot be null"); @@ -358,13 +358,44 @@ public void ValidatesNullExePaths() public void MasterAudioUtilityAllowsOptionalSupportForMp3splt() { // creation should normally fail but MasterAudioUtility was changed so that Mp3Splt was optional - var utility = new MasterAudioUtility( + new MasterAudioUtility( (FfmpegAudioUtility)TestHelper.GetAudioUtilityFfmpeg(), (WavPackAudioUtility)TestHelper.GetAudioUtilityWavunpack(), (SoxAudioUtility)TestHelper.GetAudioUtilitySox(), (FfmpegRawPcmAudioUtility)TestHelper.GetAudioUtilityFfmpegRawPcm()); } + [TestMethod] + public void MasterAudioUtilityAllowsOptionalSupportFoWavPack() + { + // creation should normally fail but MasterAudioUtility was changed so that WavPack was optional + new MasterAudioUtility( + (FfmpegAudioUtility)TestHelper.GetAudioUtilityFfmpeg(), + null, + (SoxAudioUtility)TestHelper.GetAudioUtilitySox(), + (FfmpegRawPcmAudioUtility)TestHelper.GetAudioUtilityFfmpegRawPcm()); + } + + [TestMethod] + public void MasterAudioUtilityCheckRequestValidFailsWhenWavpackIsMissing() + { + var utility = new MasterAudioUtility( + (FfmpegAudioUtility)TestHelper.GetAudioUtilityFfmpeg(), + null, + (SoxAudioUtility)TestHelper.GetAudioUtilitySox(), + (FfmpegRawPcmAudioUtility)TestHelper.GetAudioUtilityFfmpegRawPcm()); + + var source = PathHelper.GetTestAudioFile("Raw_audio_id_cd6e8ba1-11b4-4724-9562-f6ec893110aa.wv"); + + Assert.ThrowsException( + () => utility.Info(source), + "Converting from WavPack is not supported because we cannot find a wvunpack binary."); + + Assert.ThrowsException( + () => utility.Modify(source, MediaTypes.MediaTypeWavpack, PathHelper.GetTempFile(MediaTypes.ExtWav), MediaTypes.MediaTypeWav, new AudioUtilityRequest()), + "Converting from WavPack is not supported because we cannot find a wvunpack binary."); + } + private static FileInfo GetAudioUtilityExe(string name) { var baseResourceDir = PathHelper.GetResourcesBaseDir(); @@ -498,7 +529,7 @@ private static string GetDurationInfo(AudioUtilityInfo info) private static void SegmentsCorrectly( string filename, string mimetype, TimeSpan start, TimeSpan end, TimeSpan maxVariance) { - foreach (var util in new[] { TestHelper.GetAudioUtility()}) + foreach (var util in new[] { TestHelper.GetAudioUtility() }) { var dir = PathHelper.GetTempDir();