├── .gitignore ├── .nuget ├── NuGet.Config ├── NuGet.exe └── NuGet.targets ├── Common.TaskScheduler ├── Common.TaskScheduler.csproj ├── Configurations │ ├── AbstractConfiguration.cs │ ├── DailyConfiguration.cs │ ├── ImpersonateDailyConfiguration.cs │ └── StartOnLogonConfiguration.cs ├── Extensions │ ├── SecureStringExtensions.cs │ └── TaskDefinitionExtensions.cs ├── Factory │ ├── ITaskSchedulerFactory.cs │ └── TaskSchedulerFactory.cs ├── LICENSE ├── NOTICE ├── Properties │ └── AssemblyInfo.cs ├── Schedulers │ ├── AbstractScheduler.cs │ ├── Constants.cs │ ├── ITaskScheduler.cs │ ├── PackagerScheduler.cs │ └── ReporterScheduler.cs └── packages.config ├── Common.Tests ├── Common.Tests.csproj ├── Models │ ├── FileUsagesTests.cs │ └── MediaFormatsTests.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── Common ├── Common.csproj ├── Exceptions │ └── AbstractEngineException.cs ├── Extensions │ └── StringExtensions.cs ├── LICENSE ├── Models │ ├── AbstractOperationReport.cs │ ├── FileUsages.cs │ ├── MediaFormats.cs │ ├── PackagerObjectReport.cs │ └── PackagerReport.cs ├── NOTICE ├── Properties │ ├── Annotations.cs │ └── AssemblyInfo.cs ├── UserInterface │ ├── Commands │ │ ├── AsyncRelayCommand.cs │ │ └── RelayCommand.cs │ ├── HighlightingRules │ │ ├── HighlightRules.xsd │ │ ├── HighlightRules.xshd │ │ └── HighlightingConfiguration.cs │ ├── LineGenerators │ │ └── AbstractBarcodeElementGenerator.cs │ └── ViewModels │ │ ├── ILogPanelViewModel.cs │ │ ├── LogPanelViewModel.cs │ │ └── SectionModel.cs └── packages.config ├── InteractiveScheduler ├── App.config ├── App.xaml ├── App.xaml.cs ├── Converters │ ├── BooleanInverter.cs │ └── BooleanToVisibilityConverter.cs ├── Extensions │ ├── ProcessExtensions.cs │ └── SecureStringExtensions.cs ├── InteractiveScheduler.csproj ├── LICENSE ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── ManagedCode │ └── UserInterfaceHelper.cs ├── Models │ ├── BooleanResult.cs │ ├── TaskEntry.cs │ └── ViewModel.cs ├── NOTICE ├── Properties │ ├── Annotations.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Services │ ├── FileDialogService.cs │ ├── IFileDialogService.cs │ ├── IUserService.cs │ └── UserService.cs └── packages.config ├── LICENSE ├── MediaHelper.sln ├── MediaHelper.sln.DotSettings ├── NOTICE ├── Packager.Test ├── Attributes │ ├── BextFieldAttributeTests.cs │ └── FFMPEGArgumentAttributeTests.cs ├── Deserializers │ └── PodResultDeserializerTests.cs ├── Engine │ └── EngineTests.cs ├── Extensions │ ├── ArrayExtensionTests.cs │ ├── DigitalFileExtensionTests.cs │ ├── ExceptionExtensionTests.cs │ ├── FileModelExtensionTests.cs │ ├── StringBuilderExtensionsTests.cs │ ├── StringExtensionTests.cs │ └── XElementExtensionTests.cs ├── Factories │ ├── ArgumentsFactories │ │ ├── AudioFFMPEGArgumentsGeneratorTests.cs │ │ ├── CdrFFMPEGArgumentsGeneratorTests.cs │ │ ├── FFMPEGArgumentsFactoryTests.cs │ │ └── VideoFFMPEGArgumentsGeneratorTests.cs │ ├── AudioCarrierDataFactoryTests.cs │ ├── AudioIngestFactoryTests.cs │ ├── AudioSideDataFactoryTests.cs │ ├── CodingHistory │ │ ├── CodingHistoryGeneratorTestsBase.cs │ │ ├── DatCodingHistoryGeneratorTests.cs │ │ ├── LacquerOrCylinderCodingHistoryGeneratorTests.cs │ │ ├── SeventyEightCodingHistoryGeneratorTests.cs │ │ └── StandardCodingHistoryGeneratorTests.cs │ ├── EmbeddedAudioMetadataFactoryTests.cs │ ├── EmbeddedVideoMetadataFactoryTests.cs │ ├── FileModelFactoryTests.cs │ ├── ImportableFactoryTests.cs │ ├── PlaceFolderFactoryTests.cs │ ├── SettingsFactoryTests.cs │ ├── VideoCarrierDataFactoryTests.cs │ ├── VideoIngestFactoryTests.cs │ └── VideoSideDataFactoryTests.cs ├── Mocks │ ├── MockBextMetadata.cs │ ├── MockDependencyProvider.cs │ ├── MockGrouping.cs │ ├── MockPodMetadata.cs │ ├── MockProcessRunner.cs │ └── MockProgramSettings.cs ├── Models │ ├── EmailMessageTests │ │ ├── EngineIssueMessageTests.cs │ │ └── ProcessingIssueMessageTests.cs │ ├── EmbeddedMetadataTests │ │ ├── EmbeddedAudioMetadataTests.cs │ │ └── EmbeddedVideoPreservationMetadataTests.cs │ ├── FileModels │ │ ├── FileModelTests.cs │ │ ├── GeneralFileModelTests.cs │ │ ├── PlaceHolderFileModelTests.cs │ │ ├── QualityControlFileModelTests.cs │ │ ├── UnknownFileModelTests.cs │ │ └── XmlFileModelTests.cs │ ├── MetadataModels │ │ ├── DeviceTests.cs │ │ ├── DigitalFileProvenanceTests.cs │ │ ├── PlaybackSpeedTests.cs │ │ └── PodMetadataTests.cs │ ├── OutputModels │ │ ├── CarrierModelTests.cs │ │ └── IngestModelTests.cs │ ├── PlaceHolderConfigurations │ │ ├── PlaceHolderConfigurationTestsBase.cs │ │ ├── PresIntAudioPlaceHolderConfigurationTests.cs │ │ ├── StandardAudioPlaceHolderConfigurationTests.cs │ │ └── StandardVideoPlaceHolderConfigurationTests.cs │ ├── ProgramArgumentsModels │ │ └── ProgramArgumentsModelsTests.cs │ └── SettingsModelsTests │ │ └── ProgramSettingsTests.cs ├── Packager.Tests.csproj ├── PodMetadataProviderTests.cs ├── Processors │ ├── AbstractProcessorTests.cs │ ├── AudioProcessorTests.cs │ └── VideoProcessorTests.cs ├── Properties │ └── AssemblyInfo.cs ├── Providers │ └── PodMetadataProviderTests.cs ├── Utilities │ ├── ArgumentBuilderTests.cs │ ├── BextProcessorClearMetadataTests.cs │ ├── BwfMetaEditRunnerTests.cs │ ├── FFMPEGRunnerTests.cs │ ├── HasherTests.cs │ ├── ImageImporterTests.cs │ ├── ReportWriterTests.cs │ └── SuccessFolderCleanerTests.cs ├── Validators │ ├── DirectoryValidatorTests.cs │ ├── FileValidatorTests.cs │ ├── HasMembersValidatorTests.cs │ ├── UriValidatorTests.cs │ └── ValueRequiredValidatorTests.cs ├── Verifiers │ └── BwfMetaEditResultsVerifierTests.cs └── packages.config ├── Packager ├── App.config ├── App.cs ├── App.xaml ├── Attributes │ ├── AbstractFromConfigSettingAttribute.cs │ ├── BextFieldAttribute.cs │ └── FFMPEGArgumentAttribute.cs ├── Deserializers │ └── PodResultDeserializer.cs ├── Engine │ ├── EngineExitCodes.cs │ ├── IEngine.cs │ └── StandardEngine.cs ├── Exceptions │ ├── DeserializeValueException.cs │ ├── DetermineProcessorException.cs │ ├── EmbeddedMetadataException.cs │ ├── FileDirectoryExistsException.cs │ ├── FormatNotSupportedException.cs │ ├── GenerateDerivativeException.cs │ ├── LoggedException.cs │ ├── LookupException.cs │ ├── NormalizeOriginalException.cs │ ├── OutputXmlException.cs │ ├── PodMetadataException.cs │ ├── ProgramSettingsException.cs │ ├── ResolverException.cs │ └── UserCancelledException.cs ├── Extensions │ ├── ArrayExtensions.cs │ ├── DigitalFileExtensions.cs │ ├── ExceptionExtensions.cs │ ├── FileModelExtensions.cs │ ├── StringBuilderExtensions.cs │ ├── StringExtensions.cs │ └── XElmentExtensions.cs ├── Factories │ ├── AbstractEmbeddedMetadataFactory.cs │ ├── AudioCarrierDataFactory.cs │ ├── CodingHistory │ │ ├── AbstractCodingHistoryGenerator.cs │ │ ├── CdrCodingHistoryGenerator.cs │ │ ├── DatCodingHistoryGenerator.cs │ │ ├── ICodingHistoryGenerator.cs │ │ ├── LacquerDiscIreneCodingHistoryGenerator.cs │ │ ├── LacquerOrCylinderCodingHistoryGenerator.cs │ │ ├── MagnabeltCodingHistoryGenerator.cs │ │ ├── SeventyEightCodingHistoryGenerator.cs │ │ └── StandardCodingHistoryGenerator.cs │ ├── EmbeddedAudioMetadataFactory.cs │ ├── EmbeddedVideoMetadataFactory.cs │ ├── FFMPEGArguments │ │ ├── AbstractFFMPEGArgumentGenerator.cs │ │ ├── AudioFFMPEGArgumentsGenerator.cs │ │ ├── CdrFFMPEGArgumentsGenerator.cs │ │ ├── FFMPEGArgumentsFactory.cs │ │ ├── IFFMPEGArgumentsFactory.cs │ │ ├── IFFMPEGArgumentsGenerator.cs │ │ └── VideoFFMPEGArgumentsGenerator.cs │ ├── FileModelFactory.cs │ ├── ICarrierDataFactory.cs │ ├── IEmbeddedMetadataFactory.cs │ ├── IImportable.cs │ ├── IIngestDataFactory.cs │ ├── IPlaceHolderFactory.cs │ ├── ISideDataFactory.cs │ ├── ImportableFactory.cs │ ├── IngestDataFactory.cs │ ├── PlaceHolderFactory.cs │ ├── SettingsFactory.cs │ ├── SideDataFactory.cs │ └── VideoCarrierDataFactory.cs ├── Instructions.docx ├── LICENSE ├── Models │ ├── EmailMessageModels │ │ ├── AbstractEmailMessage.cs │ │ ├── DeferredEmailMessage.cs │ │ ├── EngineIssueMessage.cs │ │ ├── ProcessingIssueMessage.cs │ │ └── SuccessEmailMessage.cs │ ├── EmbeddedMetadataModels │ │ ├── AbstractEmbeddedMetadata.cs │ │ ├── AbstractEmbeddedVideoMetadata.cs │ │ ├── EmbeddedAudioMetadata.cs │ │ ├── EmbeddedVideoMezzanineMetadata.cs │ │ └── EmbeddedVideoPreservationMetadata.cs │ ├── FileModels │ │ ├── AbstractFile.cs │ │ ├── AbstractPreservationFile.cs │ │ ├── AbstractPreservationIntermediateFile.cs │ │ ├── AccessFile.cs │ │ ├── AudioPreservationFile.cs │ │ ├── AudioPreservationIntermediateFile.cs │ │ ├── AudioPreservationIntermediateToneReferenceFile.cs │ │ ├── AudioPreservationToneReferenceFile.cs │ │ ├── CueFile.cs │ │ ├── FilesArchiveFile.cs │ │ ├── InfoFile.cs │ │ ├── MediaInfo.cs │ │ ├── MezzanineFile.cs │ │ ├── PlaceHolderFile.cs │ │ ├── ProductionFile.cs │ │ ├── QualityControlFile.cs │ │ ├── TextFile.cs │ │ ├── TiffImageFile.cs │ │ ├── UnknownFile.cs │ │ ├── VideoPreservationFile.cs │ │ ├── VideoPreservationIntermediateFile.cs │ │ └── XmlFile.cs │ ├── OutputModels │ │ ├── AudioConfigurationData.cs │ │ ├── BakingData.cs │ │ ├── Carrier │ │ │ ├── AbstractCarrierData.cs │ │ │ ├── AudioCarrier.cs │ │ │ ├── RecordCarrier.cs │ │ │ └── VideoCarrier.cs │ │ ├── CleaningData.cs │ │ ├── ExportableManifest.cs │ │ ├── File.cs │ │ ├── ImportableManifest.cs │ │ ├── Ingest │ │ │ ├── AbstractIngest.cs │ │ │ ├── AudioIngest.cs │ │ │ ├── Device.cs │ │ │ └── VideoIngest.cs │ │ ├── PartsData.cs │ │ ├── PhysicalConditionData.cs │ │ ├── PreviewData.cs │ │ ├── SideData.cs │ │ └── VideoConfigurationData.cs │ ├── PlaceHolderConfigurations │ │ ├── AbstractPlaceHolderConfiguration.cs │ │ ├── IPlaceHolderConfiguration.cs │ │ ├── PresIntAudioPlaceHolderConfiguration.cs │ │ ├── StandardAudioPlaceHolderConfiguration.cs │ │ └── StandardVideoPlaceHolderConfiguration.cs │ ├── PodMetadataModels │ │ ├── AbstractDigitalFile.cs │ │ ├── AbstractPodMetadata.cs │ │ ├── AudioPodMetadata.cs │ │ ├── Device.cs │ │ ├── DigitalAudioFile.cs │ │ ├── DigitalVideoFile.cs │ │ └── VideoPodMetadata.cs │ ├── ProgramArgumentsModels │ │ ├── IProgramArguments.cs │ │ └── ProgramArguments.cs │ ├── ResultModels │ │ ├── DurationResult.cs │ │ ├── IProcessResult.cs │ │ └── ProcessResult.cs │ ├── SettingsModels │ │ ├── IProgramSettings.cs │ │ ├── PodAuth.cs │ │ └── ProgramSettings.cs │ └── UserInterfaceModels │ │ └── SectionModel.cs ├── NOTICE ├── Observers │ ├── AbstractNLogObserver.cs │ ├── GeneralNLogObserver.cs │ ├── IObserver.cs │ ├── IObserverCollection.cs │ ├── IssueEmailerObserver.cs │ ├── LayoutRenderers │ │ ├── BarcodeLayoutRenderer.cs │ │ ├── LoggingDirectoryLayoutRenderer.cs │ │ ├── ProcessingDirectoryNameLayoutRenderer.cs │ │ └── ProjectCodeLayoutRenderer.cs │ ├── ObjectNLogObserver.cs │ ├── ObserverCollection.cs │ ├── ObserverCollectionEqualityComparer.cs │ └── ViewModelObserver.cs ├── Packager.csproj ├── Processors │ ├── AbstractProcessor.cs │ ├── AudioProcessor.cs │ ├── IProcessor.cs │ └── VideoProcessor.cs ├── Program.cs ├── Properties │ ├── Annotations.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Providers │ ├── DirectoryProvider.cs │ ├── FileProvider.cs │ ├── IDirectoryProvider.cs │ ├── IFileProvider.cs │ ├── IMediaInfoProvider.cs │ ├── IPodMetadataProvider.cs │ ├── ISystemInfoProvider.cs │ ├── MediaInfoProvider.cs │ ├── PodMetadataProvider.cs │ └── SystemInfoProvider.cs ├── ReleaseNotes.txt ├── UserInterface │ ├── CancelPanel.xaml │ ├── CancelPanel.xaml.cs │ ├── IViewModel.cs │ ├── LineGenerators │ │ ├── BarCodeLinkText.cs │ │ └── BarcodeSectionLineGenerator.cs │ ├── OutputWindow.cs │ ├── View.xaml │ └── ViewModel.cs ├── Utilities │ ├── Bext │ │ ├── BextFields.cs │ │ ├── BextProcessor.cs │ │ └── IBextProcessor.cs │ ├── Configuration │ │ └── ConfigurationLogger.cs │ ├── Email │ │ ├── EmailSender.cs │ │ └── IEmailSender.cs │ ├── FileSystem │ │ ├── ISuccessFolderCleaner.cs │ │ └── SuccessFolderCleaner.cs │ ├── Hashing │ │ ├── Hasher.cs │ │ └── IHasher.cs │ ├── Images │ │ ├── ILabelImageImporter.cs │ │ └── LabelImageImporter.cs │ ├── ProcessRunners │ │ ├── ArgumentBuilder.cs │ │ ├── BwfMetaEditRunner.cs │ │ ├── FFMPEGRunner.cs │ │ ├── FFProbeRunner.cs │ │ ├── FileOutputBuffer.cs │ │ ├── IBwfMetaEditRunner.cs │ │ ├── IFFMpegRunner.cs │ │ ├── IFFProbeRunner.cs │ │ ├── IOutputBuffer.cs │ │ ├── IProcessRunner.cs │ │ ├── ProcessRunner.cs │ │ └── StringOutputBuffer.cs │ ├── Reporting │ │ ├── IReportWriter.cs │ │ └── ReportWriter.cs │ └── Xml │ │ ├── IXmlExporter.cs │ │ └── XmlExporter.cs ├── Validators │ ├── Attributes │ │ ├── HasMembersAttribute.cs │ │ ├── PropertyValidationAttribute.cs │ │ ├── RequiredAttribute.cs │ │ ├── ValidateFileAttribute.cs │ │ ├── ValidateFolderAttribute.cs │ │ ├── ValidateObjectAttribute.cs │ │ └── ValidateUriAttribute.cs │ ├── DirectoryExistsValidator.cs │ ├── FileExistsValidator.cs │ ├── IValidator.cs │ ├── IValidatorCollection.cs │ ├── MembersValidator.cs │ ├── StandardValidatorCollection.cs │ ├── UriValidator.cs │ ├── ValidationResult.cs │ ├── ValidationResults.cs │ └── ValueRequiredValidator.cs ├── Verifiers │ ├── BwfMetaeditResultsVerifier.cs │ └── IBwfMetaEditResultsVerifier.cs ├── copy to input.bat ├── packages.config └── readme.md ├── README.md ├── Recorder ├── App.config ├── App.xaml ├── App.xaml.cs ├── BarcodeScanner │ ├── Interop │ │ ├── DataStructures.cs │ │ ├── Enumerations.cs │ │ ├── RegistryAccess.cs │ │ ├── Win32Consts.cs │ │ └── Win32Methods.cs │ ├── KeyPressState.cs │ ├── RawDeviceType.cs │ ├── RawInput.cs │ ├── RawInputCaptureMode.cs │ ├── RawInputEventArgs.cs │ ├── RawKeyboard.cs │ ├── RawKeyboardDevice.cs │ └── RawPresentationInput.cs ├── Controls │ ├── ActionButton.xaml │ ├── ActionButton.xaml.cs │ ├── ActionPanel.xaml │ ├── ActionPanel.xaml.cs │ ├── AudioMeter.xaml │ ├── AudioMeter.xaml.cs │ ├── BarcodePanel.xaml │ ├── BarcodePanel.xaml.cs │ ├── FinishPanel.xaml │ ├── FinishPanel.xaml.cs │ ├── FrameStats.xaml │ ├── FrameStats.xaml.cs │ ├── NavigationPanel.xaml │ ├── NavigationPanel.xaml.cs │ ├── OutputPanel.xaml │ ├── OutputPanel.xaml.cs │ ├── RecordPanel.xaml │ ├── RecordPanel.xaml.cs │ ├── YesNoQuestionPanel.xaml │ └── YesNoQuestionPanel.xaml.cs ├── Converters │ ├── BooleanToCollapsedConverter.cs │ ├── EmptyToVisibilityConverter.cs │ └── TimespanToStringConverter.cs ├── Dialogs │ ├── OutputWindow.xaml │ ├── OutputWindow.xaml.cs │ ├── UserControls.xaml │ └── UserControls.xaml.cs ├── Enums │ └── FileUses.cs ├── Exceptions │ ├── AbstractHandledException.cs │ ├── CombiningException.cs │ ├── ConfigurationException.cs │ └── RecordingException.cs ├── Extensions │ └── UserInterfaceExtensions.cs ├── Handlers │ ├── AbstractProcessOutputHandler.cs │ ├── CurrentFrameHandler.cs │ ├── DroppedFramesHandler.cs │ ├── DuplicateFrameHandler.cs │ ├── OutputLogHandler.cs │ └── TimestampReceivedHandler.cs ├── LICENSE ├── Models │ ├── AudioChannelsAndStreams.cs │ ├── ObjectModel.cs │ └── ProgramSettings.cs ├── NOTICE ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── README.md ├── Recorder.csproj ├── ReleaseNotes.txt ├── Scripts │ ├── Internal │ │ ├── betacam_fix_internal.bat │ │ └── umatic_fix_internal.bat │ ├── Shared │ │ └── common.bat │ ├── betacam_fix.bat │ ├── extract audio channels.bat │ ├── extract stereo to mono.bat │ └── umatic_fix.bat ├── Utilities │ ├── AbstractEngine.cs │ ├── BarcodeHandler.cs │ ├── CombiningEngine.cs │ ├── ICanLogConfiguration.cs │ ├── InfoEngine.cs │ ├── RecordingEngine.cs │ └── VolumeMeter.cs ├── ViewModels │ ├── AbstractNotifyModel.cs │ ├── AbstractPanelViewModel.cs │ ├── ActionButtonModel.cs │ ├── AskExitViewModel.cs │ ├── BarcodePanelViewModel.cs │ ├── FinishPanelViewModel.cs │ ├── FrameStatsViewModel.cs │ ├── IClosing.cs │ ├── IWindowHandleInitialized.cs │ ├── IssueNotifyModel.cs │ ├── OutputWindowViewModel.cs │ ├── RecordPanelViewModel.cs │ ├── UserControlsViewModel.cs │ └── VolumeMeterViewModel.cs └── packages.config ├── Reporter ├── App.config ├── App.xaml ├── App.xaml.cs ├── Converters │ └── DisabledIfEmptyConverter.cs ├── LICENSE ├── LineGenerators │ ├── OpenObjectLogFileLinkText.cs │ └── OpenObjectLogfileGenerator.cs ├── Models │ ├── AbstractReportEntry.cs │ ├── FileReportEntry.cs │ ├── ProgramSettings.cs │ └── TaskSchedulerEntry.cs ├── NOTICE ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── ReleaseNotes.txt ├── Reporter.csproj ├── ReporterWindow.xaml ├── ReporterWindow.xaml.cs ├── Utilities │ ├── FileReportRenderer.cs │ ├── IReportRenderer.cs │ └── TaskSchedulerRenderer.cs ├── ViewModel.cs └── packages.config ├── Scheduler ├── App.config ├── LICENSE ├── Models │ └── Arguments.cs ├── NOTICE ├── OpenTaskScheduler.bat ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── Schedule.bat ├── Scheduler.csproj └── packages.config ├── SetLogonAsBatchRight ├── App.config ├── LICENSE ├── LsaUtilities.cs ├── NOTICE ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── SetLogonAsBatchRight.csproj ├── WaveInfo ├── AbstractChunk.cs ├── App.config ├── BextChunk.cs ├── DataChunk.cs ├── Ds64Chunk.cs ├── Extensions │ ├── BinaryReaderExtensions.cs │ ├── StringExtensions.cs │ └── Uint64Extensions.cs ├── FactChunk.cs ├── FormatChunk.cs ├── InfoChunk.cs ├── LICENSE ├── ListChunk.cs ├── NOTICE ├── OtherChunk.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── RiffChunk.cs ├── WaveFile.cs ├── WaveFileFactory.cs └── WaveInfo.csproj ├── deploy.bat ├── example barcodes.txt └── reference ├── IU_PID_1.0_technical_only.docx ├── InputTemplate.xlsx ├── MemnonExample.xml ├── MemnonReference.xml ├── Pod-Output.xml ├── PodMetadataSchema.xsd ├── ReferenceInformation.txt └── mdpi_embeddedMD_audio_20150519.docx /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IUMDPI/IUMediaHelperApps/32afb704dc9c7691ca0b0f1c3ff01b8bbd451f53/.nuget/NuGet.exe -------------------------------------------------------------------------------- /Common.TaskScheduler/Configurations/StartOnLogonConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Common.TaskScheduler.Extensions; 3 | using Microsoft.Win32.TaskScheduler; 4 | 5 | namespace Common.TaskScheduler.Configurations 6 | { 7 | public class StartOnLogonConfiguration:AbstractConfiguration 8 | { 9 | public string Username { get; set; } 10 | public TimeSpan Delay { get; set; } 11 | 12 | public StartOnLogonConfiguration() 13 | { 14 | } 15 | 16 | private StartOnLogonConfiguration(Task task) : base(task) 17 | { 18 | var trigger = task.Definition.GetLogonTrigger(); 19 | if (trigger == null) 20 | { 21 | return; 22 | } 23 | 24 | Username = trigger.UserId; 25 | Delay = trigger.Delay; 26 | } 27 | 28 | public override AbstractConfiguration Import(Task task) 29 | { 30 | var trigger = task.Definition.GetLogonTrigger(); 31 | return trigger != null 32 | ? new StartOnLogonConfiguration(task) 33 | : null; 34 | } 35 | 36 | protected override TaskDefinition ConfigureDefinition(TaskDefinition definition) 37 | { 38 | return base.ConfigureDefinition(definition) 39 | .ConfigureForUserLogon(Username, Delay); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Common.TaskScheduler/Extensions/SecureStringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security; 4 | 5 | namespace Common.TaskScheduler.Extensions 6 | { 7 | public static class SecureStringExtensions 8 | { 9 | public static string ToUnsecureString(this SecureString password) 10 | { 11 | if (password == null) 12 | throw new ArgumentNullException(nameof(password)); 13 | 14 | var unmanagedString = IntPtr.Zero; 15 | try 16 | { 17 | unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(password); 18 | return Marshal.PtrToStringUni(unmanagedString); 19 | } 20 | finally 21 | { 22 | Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Common.TaskScheduler/Factory/ITaskSchedulerFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Common.TaskScheduler.Configurations; 3 | using Common.TaskScheduler.Schedulers; 4 | using Microsoft.Win32.TaskScheduler; 5 | 6 | namespace Common.TaskScheduler.Factory 7 | { 8 | public interface ITaskSchedulerFactory 9 | { 10 | ITaskScheduler GetForApplication(string path); 11 | ITaskScheduler GetDefaultScheduler(); 12 | List GetExistingTasks(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Common.TaskScheduler/Factory/TaskSchedulerFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Common.TaskScheduler.Configurations; 4 | using Common.TaskScheduler.Schedulers; 5 | 6 | namespace Common.TaskScheduler.Factory 7 | { 8 | public class TaskSchedulerFactory : ITaskSchedulerFactory 9 | { 10 | private List Schedulers { get; } 11 | 12 | public TaskSchedulerFactory() 13 | { 14 | Schedulers = new List 15 | { 16 | new PackagerScheduler(), 17 | new ReporterScheduler() 18 | }; 19 | } 20 | 21 | public ITaskScheduler GetForApplication(string path) 22 | { 23 | return Schedulers.SingleOrDefault(s => s.IsRecognizedAssembly(path)); 24 | } 25 | 26 | public ITaskScheduler GetDefaultScheduler() 27 | { 28 | return Schedulers.First(); 29 | } 30 | 31 | public List GetExistingTasks() 32 | { 33 | return Schedulers.SelectMany(s => s.GetExistingConfigurations()).ToList(); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Common.TaskScheduler/NOTICE: -------------------------------------------------------------------------------- 1 | INDIANA UNIVERSITY MEDIA HELPER APPLICATIONS: COMMON.TASKSCHEDULER 2 | 3 | Code library containing task scheduler code that it shared among 4 | various media-helper utilities. 5 | 6 | Copyright (C) 2014-2017, The Trustees of Indiana University. 7 | -------------------------------------------------------------------------------- /Common.TaskScheduler/Schedulers/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace Common.TaskScheduler.Schedulers 2 | { 3 | public static class Constants 4 | { 5 | public static string PackagerGuid = "fda079c7-6cc2-4033-8bcd-364b2f50da7b"; 6 | public static string PackagerProductName = "Packager"; 7 | public static string PackagerTaskName = "Media Packager"; 8 | public static string ReporterGuid = "e0d53975-8289-40a7-86f3-54b9532b9bcf"; 9 | public static string ReporterProductName = "Reporter"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Common.TaskScheduler/Schedulers/ReporterScheduler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Principal; 3 | using Common.TaskScheduler.Configurations; 4 | using Microsoft.Win32.TaskScheduler; 5 | 6 | namespace Common.TaskScheduler.Schedulers 7 | { 8 | public class ReporterScheduler:AbstractScheduler 9 | { 10 | public ReporterScheduler() : base(Constants.ReporterGuid) 11 | { 12 | } 13 | 14 | public override AbstractConfiguration GetDefaultConfiguration() 15 | { 16 | return new StartOnLogonConfiguration 17 | { 18 | Username = WindowsIdentity.GetCurrent().Name, 19 | Delay = new TimeSpan(0,2,0) 20 | }; 21 | } 22 | 23 | protected override AbstractConfiguration Import(Task task) 24 | { 25 | return new StartOnLogonConfiguration().Import(task); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Common.TaskScheduler/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Common.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Common/Exceptions/AbstractEngineException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Common.Exceptions 4 | { 5 | public abstract class AbstractEngineException : Exception 6 | { 7 | protected AbstractEngineException(string baseMessage, params object[] parameters) 8 | : base(string.Format(baseMessage, parameters)) 9 | { 10 | } 11 | 12 | protected AbstractEngineException(Exception innerException, string baseMessage, params object[] parameters) 13 | :base(string.Format(baseMessage, parameters), innerException) 14 | { 15 | 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Common/Models/PackagerObjectReport.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace Common.Models 4 | { 5 | public class PackagerObjectReport : AbstractOperationReport 6 | { 7 | [XmlAttribute("Barcode")] 8 | public string Barcode { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /Common/Models/PackagerReport.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml.Serialization; 3 | 4 | namespace Common.Models 5 | { 6 | public class PackagerReport : AbstractOperationReport 7 | { 8 | [XmlArray("Objects")] 9 | [XmlArrayItem("Object")] 10 | public List ObjectReports { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Common/NOTICE: -------------------------------------------------------------------------------- 1 | INDIANA UNIVERSITY MEDIA HELPER APPLICATIONS: COMMON 2 | 3 | Code library containing classes and models that are used in 4 | multiple media-helper utilities. 5 | 6 | Copyright (C) 2014-2017, The Trustees of Indiana University. 7 | -------------------------------------------------------------------------------- /Common/UserInterface/HighlightingRules/HighlightingConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Xml; 3 | using ICSharpCode.AvalonEdit; 4 | using ICSharpCode.AvalonEdit.Highlighting; 5 | using ICSharpCode.AvalonEdit.Highlighting.Xshd; 6 | 7 | namespace Common.UserInterface.HighlightingRules 8 | { 9 | public static class Configuration 10 | { 11 | public static void ApplyRules(TextEditor textEditor) 12 | { 13 | var assembly = Assembly.GetExecutingAssembly(); 14 | using (var s = assembly.GetManifestResourceStream("Common.UserInterface.HighlightingRules.HighlightRules.xshd")) 15 | { 16 | if (s == null) 17 | { 18 | return; 19 | } 20 | using (var reader = new XmlTextReader(s)) 21 | { 22 | 23 | textEditor.SyntaxHighlighting = HighlightingLoader.Load(reader, HighlightingManager.Instance); 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Common/UserInterface/ViewModels/ILogPanelViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using ICSharpCode.AvalonEdit; 4 | using ICSharpCode.AvalonEdit.Rendering; 5 | 6 | namespace Common.UserInterface.ViewModels 7 | { 8 | public interface ILogPanelViewModel 9 | { 10 | void BeginSection(string sectionKey, string text); 11 | void EndSection(string sectionKey, string newTitle = "", bool collapse = false); 12 | void Initialize(TextEditor textEditor, IEnumerable lineElementGenerators); 13 | void InsertLine(string value); 14 | void LogError(Exception e); 15 | void ScrollToSection(string sectionKey); 16 | void Clear(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Common/UserInterface/ViewModels/SectionModel.cs: -------------------------------------------------------------------------------- 1 | namespace Common.UserInterface.ViewModels 2 | { 3 | public class SectionModel 4 | { 5 | public int StartOffset { get; set; } 6 | public int EndOffset { get; set; } 7 | public string Key { get; set; } 8 | public bool Completed { get; set; } 9 | public int Indent { get; set; } 10 | public string Title { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Common/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /InteractiveScheduler/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /InteractiveScheduler/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /InteractiveScheduler/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace InteractiveScheduler 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /InteractiveScheduler/Converters/BooleanInverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Data; 3 | 4 | namespace InteractiveScheduler.Converters 5 | { 6 | public class BooleanInverter : IValueConverter 7 | { 8 | public object Convert(object value, Type targetType, object parameter, 9 | System.Globalization.CultureInfo culture) 10 | { 11 | if (value is bool) 12 | { 13 | return !(bool)value; 14 | } 15 | return value; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, 19 | System.Globalization.CultureInfo culture) 20 | { 21 | if (value is bool) 22 | { 23 | return !(bool)value; 24 | } 25 | return value; 26 | } 27 | 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /InteractiveScheduler/Converters/BooleanToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Data; 4 | 5 | namespace InteractiveScheduler.Converters 6 | { 7 | public class BooleanToVisibilityConverter : IValueConverter 8 | { 9 | public BooleanToVisibilityConverter() { } 10 | 11 | public bool Reverse { get; set; } 12 | 13 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 14 | { 15 | var booleanValue = value != null && (bool)value; 16 | 17 | return booleanValue != Reverse 18 | ? Visibility.Visible 19 | : Visibility.Collapsed; 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /InteractiveScheduler/Extensions/ProcessExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace InteractiveScheduler.Extensions 6 | { 7 | public static class ProcessExtensions 8 | { 9 | public static Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default(CancellationToken)) 10 | { 11 | var tcs = new TaskCompletionSource(); 12 | process.EnableRaisingEvents = true; 13 | process.Exited += (sender, args) => tcs.TrySetResult(null); 14 | if (cancellationToken != default(CancellationToken)) 15 | cancellationToken.Register(tcs.SetCanceled); 16 | 17 | return tcs.Task; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /InteractiveScheduler/Extensions/SecureStringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security; 4 | 5 | namespace InteractiveScheduler.Extensions 6 | { 7 | public static class SecureStringExtensions 8 | { 9 | public static string ToUnsecureString(this SecureString password) 10 | { 11 | if (password == null) 12 | throw new ArgumentNullException(nameof(password)); 13 | 14 | var unmanagedString = IntPtr.Zero; 15 | try 16 | { 17 | unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(password); 18 | return Marshal.PtrToStringUni(unmanagedString); 19 | } 20 | finally 21 | { 22 | Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /InteractiveScheduler/Models/BooleanResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace InteractiveScheduler.Models 8 | { 9 | public class BooleanResult 10 | { 11 | public bool Success { get; set; } 12 | public Exception Issue { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /InteractiveScheduler/Models/TaskEntry.cs: -------------------------------------------------------------------------------- 1 | using Common.TaskScheduler.Configurations; 2 | 3 | namespace InteractiveScheduler.Models 4 | { 5 | public abstract class AbstractOperation 6 | { 7 | public abstract string Name { get; } 8 | public AbstractConfiguration Value { get; protected set; } 9 | } 10 | 11 | public class EditExistingOperation:AbstractOperation 12 | { 13 | public EditExistingOperation(AbstractConfiguration configuration) 14 | { 15 | Value = configuration; 16 | } 17 | 18 | public override string Name => $"Edit {Value.TaskName}"; 19 | } 20 | 21 | public class AddNewOperation : AbstractOperation 22 | { 23 | public override string Name => "Add new scheduled task"; 24 | 25 | public AddNewOperation(AbstractConfiguration configuration) 26 | { 27 | Value = configuration; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /InteractiveScheduler/NOTICE: -------------------------------------------------------------------------------- 1 | INDIANA UNIVERSITY MEDIA HELPER APPLICATIONS: INTERACTIVE SCHEDULER 2 | 3 | Interactive utility to configure Windows scheduled tasks. 4 | 5 | Copyright (C) 2014-2017, The Trustees of Indiana University. 6 | -------------------------------------------------------------------------------- /InteractiveScheduler/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace InteractiveScheduler.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /InteractiveScheduler/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /InteractiveScheduler/Services/FileDialogService.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows; 3 | using Microsoft.Win32; 4 | 5 | namespace InteractiveScheduler.Services 6 | { 7 | public class FileDialogService : IFileDialogService 8 | { 9 | private readonly Window _owner; 10 | 11 | public FileDialogService(Window owner) 12 | { 13 | _owner = owner; 14 | } 15 | 16 | public string OpenDialog(string defaultPath = "") 17 | { 18 | var initialDirectory = string.IsNullOrWhiteSpace(defaultPath) 19 | ? string.Empty 20 | : Path.GetDirectoryName(defaultPath); 21 | 22 | var dialog = new OpenFileDialog 23 | { 24 | Filter = "exe files (*.exe) | *.exe", 25 | CheckPathExists = true, 26 | CheckFileExists = true, 27 | InitialDirectory = initialDirectory, 28 | Multiselect = false 29 | }; 30 | 31 | var result = dialog.ShowDialog(_owner); 32 | return result.Value ? dialog.FileName : string.Empty; 33 | } 34 | 35 | public bool Exists(string path) 36 | { 37 | return File.Exists(path); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /InteractiveScheduler/Services/IFileDialogService.cs: -------------------------------------------------------------------------------- 1 | namespace InteractiveScheduler.Services 2 | { 3 | public interface IFileDialogService 4 | { 5 | string OpenDialog(string defaultPath = ""); 6 | bool Exists(string path); 7 | } 8 | } -------------------------------------------------------------------------------- /InteractiveScheduler/Services/IUserService.cs: -------------------------------------------------------------------------------- 1 | using System.Security; 2 | using System.Threading.Tasks; 3 | 4 | namespace InteractiveScheduler.Services 5 | { 6 | public interface IUserService 7 | { 8 | bool CredentialsValid(string username, SecureString password); 9 | Task GrantBatchPermissions(string username); 10 | void OpenSecPol(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /InteractiveScheduler/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /MediaHelper.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True 3 | True 4 | True -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | INDIANA UNIVERSITY MEDIA HELPER APPLICATIONS 2 | 3 | A collection of utilities to aid in the digitization of Indiana University's audio/video media holdings. 4 | 5 | Copyright (C) 2014-2017, The Trustees of Indiana University. 6 | -------------------------------------------------------------------------------- /Packager.Test/Attributes/FFMPEGArgumentAttributeTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Packager.Attributes; 3 | 4 | namespace Packager.Test.Attributes 5 | { 6 | [TestFixture] 7 | public class FFMPEGArgumentAttributeTests 8 | { 9 | [Test] 10 | public void ConstructorShouldWorkCorrectly() 11 | { 12 | var attribute = new FFMPEGArgumentAttribute("value"); 13 | Assert.That(attribute.Value, Is.EqualTo("value")); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Packager.Test/Extensions/ExceptionExtensionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using Packager.Extensions; 4 | 5 | namespace Packager.Test.Extensions 6 | { 7 | [TestFixture] 8 | public class ExceptionExtensionTests 9 | { 10 | [Test] 11 | public void GetFirstMessageShouldReturnCorrectResult() 12 | { 13 | var firstException = new Exception("first message"); 14 | var secondException = new Exception("second message", firstException); 15 | var thirdException = new Exception("third message", secondException); 16 | 17 | Assert.That(firstException.GetBaseMessage(), Is.EqualTo("first message")); 18 | Assert.That(secondException.GetBaseMessage(), Is.EqualTo("first message")); 19 | Assert.That(thirdException.GetBaseMessage(), Is.EqualTo("first message")); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Packager.Test/Extensions/StringBuilderExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using NUnit.Framework; 3 | using Packager.Extensions; 4 | 5 | namespace Packager.Test.Extensions 6 | { 7 | [TestFixture] 8 | public class StringBuilderExtensionsTests 9 | { 10 | [Test] 11 | public void HasContentShouldReturnTrueIfContentPresent() 12 | { 13 | var builder = new StringBuilder("content"); 14 | Assert.That(builder.HasContent(), Is.True); 15 | } 16 | 17 | [Test] 18 | public void HasContentShouldReturnFalseIfContentPresent() 19 | { 20 | var builder = new StringBuilder(); 21 | Assert.That(builder.HasContent(), Is.False); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Packager.Test/Mocks/MockBextMetadata.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Reflection; 3 | using Packager.Attributes; 4 | using Packager.Models.EmbeddedMetadataModels; 5 | 6 | namespace Packager.Test.Mocks 7 | { 8 | public static class MockBextMetadata 9 | { 10 | public static EmbeddedAudioMetadata Get() 11 | { 12 | var result = new EmbeddedAudioMetadata(); 13 | foreach (var property in result.GetType().GetProperties().Where(p => p.GetCustomAttribute() != null)) 14 | { 15 | var value = $"{property.Name} value"; 16 | property.SetValue(result, value); 17 | } 18 | 19 | result.OriginationDate = "2015-10-1"; 20 | result.OriginationTime = "00:00:00"; 21 | result.TimeReference = "0"; 22 | 23 | return result; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Packager.Test/Mocks/MockGrouping.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Packager.Models.FileModels; 4 | 5 | namespace Packager.Test.Mocks 6 | { 7 | public class MockFileGrouping : List, IGrouping 8 | { 9 | public string Key { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Packager.Test/Mocks/MockProcessRunner.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using NSubstitute; 4 | using Packager.Models.ResultModels; 5 | using Packager.Utilities; 6 | using Packager.Utilities.ProcessRunners; 7 | 8 | namespace Packager.Test.Mocks 9 | { 10 | public static class MockProcessRunner 11 | { 12 | public static IProcessRunner Get(IProcessResult bwfMetaEditResult = null, IProcessResult ffmpegResult = null) 13 | { 14 | var runner = Substitute.For(); 15 | 16 | if (bwfMetaEditResult == null) 17 | { 18 | bwfMetaEditResult = Substitute.For(); 19 | bwfMetaEditResult.ExitCode.ReturnsForAnyArgs(0); 20 | } 21 | 22 | if (ffmpegResult == null) 23 | { 24 | ffmpegResult = Substitute.For(); 25 | ffmpegResult.ExitCode.ReturnsForAnyArgs(0); 26 | } 27 | 28 | runner.Run(null, CancellationToken.None).ReturnsForAnyArgs(Task.FromResult(bwfMetaEditResult)); 29 | runner.Run(null, CancellationToken.None).ReturnsForAnyArgs(Task.FromResult(ffmpegResult)); 30 | return runner; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Packager.Test/Models/FileModels/UnknownFileModelTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Packager.Models.FileModels; 3 | 4 | namespace Packager.Test.Models.FileModels 5 | { 6 | [TestFixture] 7 | public class UnknownFileModelTests 8 | { 9 | private const string GoodFileName = "mdpi_4890764553278906.txt"; 10 | 11 | [Test] 12 | public void IsValidShouldAlwaysReturnFalse() 13 | { 14 | var model = new UnknownFile(GoodFileName); 15 | Assert.That(model.IsImportable(), Is.False); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Packager.Test/Models/ProgramArgumentsModels/ProgramArgumentsModelsTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Packager.Models.ProgramArgumentsModels; 3 | 4 | namespace Packager.Test.Models.ProgramArgumentsModels 5 | { 6 | [TestFixture] 7 | public class ProgramArgumentsModelsTests 8 | { 9 | [TestCase("-noninteractive", false)] 10 | [TestCase("-NonInteractive", false)] 11 | [TestCase("-NONInteractive", false)] 12 | [TestCase("", true)] 13 | [TestCase("-blah", true)] 14 | public void ItShouldSetInteractiveCorrectly(string argument, bool expectedValue) 15 | { 16 | var arguments = new ProgramArguments(new []{argument}); 17 | Assert.That(arguments.Interactive, Is.EqualTo(expectedValue)); 18 | } 19 | 20 | [Test] 21 | public void ItShouldSetInteractiveToTrueIfNoArgumentsPresent() 22 | { 23 | var arguments = new ProgramArguments(new string[0]); 24 | Assert.That(arguments.Interactive, Is.True); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Packager.Test/Utilities/HasherTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | using NUnit.Framework; 4 | using Packager.Utilities; 5 | using Packager.Utilities.Hashing; 6 | 7 | namespace Packager.Test.Utilities 8 | { 9 | [TestFixture] 10 | public class HasherTests 11 | { 12 | [Test] 13 | public void OutputShouldBe32Chars() 14 | { 15 | var bytes = new byte[] { 24, 16, 8, 32 }; 16 | var result = Hasher.Hash(new MemoryStream(bytes)); 17 | Assert.That(result.Length, Is.EqualTo(32)); 18 | } 19 | 20 | [Test] 21 | public void OutputShouldOnlyContainCorrectCharacters() 22 | { 23 | var bytes = new byte[] { 24, 16, 8, 32 }; 24 | var result = Hasher.Hash(new MemoryStream(bytes)); 25 | var acceptableChars = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 26 | foreach (var c in result.ToCharArray()) 27 | { 28 | Assert.That(acceptableChars.Contains(c), Is.True); 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Packager.Test/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Packager/App.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace Packager 4 | { 5 | /// 6 | /// Interaction logic for App.xaml 7 | /// 8 | public partial class App : Application 9 | { 10 | } 11 | } -------------------------------------------------------------------------------- /Packager/App.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Packager/Attributes/AbstractFromConfigSettingAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.CodeDom; 3 | using System.Collections.Generic; 4 | 5 | namespace Packager.Attributes 6 | { 7 | public abstract class AbstractFromConfigSettingAttribute : Attribute 8 | { 9 | protected AbstractFromConfigSettingAttribute(string name) 10 | { 11 | Name = name; 12 | Issues = new List(); 13 | } 14 | 15 | public string Name { get; private set; } 16 | 17 | public abstract object Convert(string value); 18 | 19 | public List Issues { get; } 20 | } 21 | } -------------------------------------------------------------------------------- /Packager/Attributes/BextFieldAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using Packager.Extensions; 4 | using Packager.Utilities.Bext; 5 | 6 | namespace Packager.Attributes 7 | { 8 | public class BextFieldAttribute : Attribute 9 | { 10 | public BextFieldAttribute(BextFields field, int maxLength = 0) 11 | { 12 | Field = field; 13 | MaxLength = maxLength; 14 | } 15 | 16 | public BextFields Field { get; } 17 | public int MaxLength { get; } 18 | 19 | public bool ValueWithinLengthLimit(string value) 20 | { 21 | if (value.IsNotSet()) 22 | { 23 | return true; 24 | } 25 | 26 | if (MaxLength == 0) 27 | { 28 | return true; 29 | } 30 | 31 | return value.Length <= MaxLength; 32 | } 33 | 34 | public string GetFFMPEGArgument() 35 | { 36 | var type = Field.GetType(); 37 | var name = Enum.GetName(type, Field); 38 | var attribute = type.GetField(name).GetCustomAttribute(); 39 | 40 | return attribute == null ? Field.ToString() : attribute.Value; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Packager/Attributes/FFMPEGArgumentAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Packager.Attributes 4 | { 5 | public class FFMPEGArgumentAttribute : Attribute 6 | { 7 | public string Value { get; } 8 | 9 | public FFMPEGArgumentAttribute(string value) 10 | { 11 | Value = value; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Packager/Deserializers/PodResultDeserializer.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | using Packager.Extensions; 3 | using Packager.Factories; 4 | using RestSharp; 5 | using RestSharp.Deserializers; 6 | 7 | namespace Packager.Deserializers 8 | { 9 | public class PodResultDeserializer : IDeserializer 10 | { 11 | public PodResultDeserializer(IImportableFactory factory) 12 | { 13 | Factory = factory; 14 | } 15 | 16 | private IImportableFactory Factory { get; } 17 | 18 | public T Deserialize(IRestResponse response) 19 | { 20 | if (response.Content.IsNotSet()) 21 | { 22 | return default(T); 23 | } 24 | 25 | var document = XDocument.Parse(response.Content); 26 | 27 | return Factory.ToImportable(document.Root); 28 | } 29 | 30 | public string RootElement { get; set; } 31 | public string Namespace { get; set; } 32 | public string DateFormat { get; set; } 33 | } 34 | } -------------------------------------------------------------------------------- /Packager/Engine/EngineExitCodes.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Engine 2 | { 3 | public enum EngineExitCodes 4 | { 5 | Success = 0, 6 | EngineIssue = -1, 7 | ProcessingIssue = -2 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Packager/Engine/IEngine.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Packager.Observers; 4 | 5 | namespace Packager.Engine 6 | { 7 | public interface IEngine 8 | { 9 | Task Start(CancellationToken cancellationToken); 10 | void AddObserver(IObserver observer); 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Exceptions/DeserializeValueException.cs: -------------------------------------------------------------------------------- 1 | using Common.Exceptions; 2 | 3 | namespace Packager.Exceptions 4 | { 5 | public class DeserializeValueException : AbstractEngineException 6 | { 7 | public DeserializeValueException(string baseMessage, params object[] parameters) 8 | : base(baseMessage, parameters) 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Exceptions/DetermineProcessorException.cs: -------------------------------------------------------------------------------- 1 | using Common.Exceptions; 2 | 3 | namespace Packager.Exceptions 4 | { 5 | public class DetermineProcessorException : AbstractEngineException 6 | { 7 | public DetermineProcessorException(string baseMessage, params object[] parameters) 8 | : base(baseMessage, parameters) 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Exceptions/EmbeddedMetadataException.cs: -------------------------------------------------------------------------------- 1 | using Common.Exceptions; 2 | 3 | namespace Packager.Exceptions 4 | { 5 | public class EmbeddedMetadataException : AbstractEngineException 6 | { 7 | public EmbeddedMetadataException(string baseMessage, params object[] parameters) 8 | : base(baseMessage, parameters) 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Exceptions/FileDirectoryExistsException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Common.Exceptions; 3 | 4 | namespace Packager.Exceptions 5 | { 6 | public class FileDirectoryExistsException:AbstractEngineException 7 | { 8 | public FileDirectoryExistsException(string baseMessage, params object[] parameters) : base(baseMessage, parameters) 9 | { 10 | } 11 | 12 | public FileDirectoryExistsException(Exception innerException, string baseMessage, params object[] parameters) : base(innerException, baseMessage, parameters) 13 | { 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Packager/Exceptions/FormatNotSupportedException.cs: -------------------------------------------------------------------------------- 1 | using Common.Exceptions; 2 | using Common.Models; 3 | 4 | namespace Packager.Exceptions 5 | { 6 | public class FormatNotSupportedException: AbstractEngineException 7 | { 8 | public FormatNotSupportedException(IMediaFormat format) 9 | : base($"The format {format.ProperName} ({format.Key}) is not currently supported") 10 | { 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Packager/Exceptions/GenerateDerivativeException.cs: -------------------------------------------------------------------------------- 1 | using Common.Exceptions; 2 | 3 | namespace Packager.Exceptions 4 | { 5 | public class GenerateDerivativeException : AbstractEngineException 6 | { 7 | public GenerateDerivativeException(string baseMessage, params object[] parameters) 8 | : base(baseMessage, parameters) 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Exceptions/LoggedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Packager.Exceptions 4 | { 5 | public class LoggedException : Exception 6 | { 7 | public LoggedException(Exception innerException) : base("", innerException) 8 | { 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Packager/Exceptions/LookupException.cs: -------------------------------------------------------------------------------- 1 | using Common.Exceptions; 2 | 3 | namespace Packager.Exceptions 4 | { 5 | public class LookupException : AbstractEngineException 6 | { 7 | public LookupException(string baseMessage, params object[] parameters) 8 | : base(baseMessage, parameters) 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Exceptions/NormalizeOriginalException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Common.Exceptions; 3 | 4 | namespace Packager.Exceptions 5 | { 6 | public class NormalizeOriginalException : AbstractEngineException 7 | { 8 | public NormalizeOriginalException(string baseMessage, params object[] parameters) : base(baseMessage, parameters) 9 | { 10 | } 11 | 12 | public NormalizeOriginalException(Exception innerException, string baseMessage, params object[] parameters) : base(innerException, baseMessage, parameters) 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Packager/Exceptions/OutputXmlException.cs: -------------------------------------------------------------------------------- 1 | using Common.Exceptions; 2 | 3 | namespace Packager.Exceptions 4 | { 5 | public class OutputXmlException : AbstractEngineException 6 | { 7 | public OutputXmlException(string baseMessage, params object[] parameters) 8 | : base(baseMessage, parameters) 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Exceptions/PodMetadataException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Common.Exceptions; 4 | using Packager.Validators; 5 | 6 | namespace Packager.Exceptions 7 | { 8 | public class PodMetadataException : AbstractEngineException 9 | { 10 | public PodMetadataException(Exception innerException, string baseMessage, params object[] parameters) 11 | : base(innerException, baseMessage, parameters) 12 | { 13 | } 14 | 15 | public PodMetadataException(string baseMessage, params object[] parameters) 16 | : base(baseMessage, parameters) 17 | { 18 | } 19 | 20 | public PodMetadataException(ValidationResults validationResults) : base("One or more required metadata properties is missing or invalid:\n {0}", string.Join("\n ", validationResults.Issues.Distinct())) 21 | { 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Packager/Exceptions/ProgramSettingsException.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Common.Exceptions; 4 | 5 | namespace Packager.Exceptions 6 | { 7 | public class ProgramSettingsException : AbstractEngineException 8 | { 9 | public ProgramSettingsException(string baseMessage, params object[] parameters) : base(baseMessage, parameters) 10 | { 11 | } 12 | 13 | public ProgramSettingsException(IEnumerable issues) : 14 | base("One or more required settings is missing or invalid:\n {0}", string.Join("\n ", issues.Distinct())) 15 | { 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Packager/Exceptions/ResolverException.cs: -------------------------------------------------------------------------------- 1 | using Common.Exceptions; 2 | 3 | namespace Packager.Exceptions 4 | { 5 | public class ResolverException : AbstractEngineException 6 | { 7 | public ResolverException(string baseMessage, params object[] parameters) 8 | : base(baseMessage, parameters) 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Exceptions/UserCancelledException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Common.Exceptions; 3 | 4 | namespace Packager.Exceptions 5 | { 6 | public class UserCancelledException : AbstractEngineException 7 | { 8 | public UserCancelledException(Exception exception) : base(exception,"user canceled operation") 9 | { 10 | } 11 | 12 | public UserCancelledException() : base("user canceled operation") 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Packager/Extensions/ArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Packager.Extensions 5 | { 6 | public static class ArrayExtensions 7 | { 8 | public static T FromIndex(this T[] parts, int index, T defaultValue) 9 | { 10 | return parts.Length >= index + 1 ? parts[index] : defaultValue; 11 | } 12 | 13 | public static string ToSingularOrPlural(this IEnumerable values, string singular, string plural) 14 | { 15 | var count = values?.Count() ?? 0; 16 | return count.ToSingularOrPlural(singular, plural); 17 | } 18 | 19 | public static string ToSingularOrPlural(this Dictionary values, string singular, string plural) 20 | { 21 | var count = values?.Count ?? 0; 22 | return count.ToSingularOrPlural(singular, plural); 23 | } 24 | 25 | public static string ToSingularOrPlural(this int value, string singular, string plural) 26 | { 27 | return value == 1 28 | ? $"{value} {singular}" 29 | : $"{value} {plural}"; 30 | } 31 | 32 | public static bool IsFirst(this IEnumerable list, T instance) 33 | { 34 | return list.First().Equals(instance); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Packager/Extensions/DigitalFileExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Packager.Models.FileModels; 4 | using Packager.Models.PodMetadataModels; 5 | using System.IO; 6 | using Packager.Factories; 7 | 8 | namespace Packager.Extensions 9 | { 10 | public static class DigitalFileExtensions 11 | { 12 | public static AbstractDigitalFile GetFileProvenance(this IEnumerable provenances, AbstractFile model, AbstractDigitalFile defaultValue = null) 13 | { 14 | var result = provenances.SingleOrDefault(dfp => model.IsSameAs(NormalizeFileNameAndGetModel(model, dfp.Filename))); 15 | return result ?? defaultValue; 16 | } 17 | 18 | // in some cases, filenames might be stored in the POD without extensions 19 | // this method ensures that filenames have extension 20 | private static AbstractFile NormalizeFileNameAndGetModel(AbstractFile model, string value) 21 | { 22 | var normalizedValue = Path.HasExtension(value)? value : $"{value}{model.Extension}"; 23 | return FileModelFactory.GetModel(normalizedValue); 24 | 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Packager/Extensions/ExceptionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Packager.Extensions 4 | { 5 | public static class ExceptionExtensions 6 | { 7 | public static string GetBaseMessage(this Exception exception) 8 | { 9 | return exception?.GetBaseException().Message ?? ""; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Extensions/StringBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Packager.Extensions 4 | { 5 | public static class StringBuilderExtensions 6 | { 7 | public static bool HasContent(this StringBuilder builder) 8 | { 9 | return builder != null && builder.Length >= 1; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Extensions/XElmentExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Linq; 3 | 4 | namespace Packager.Extensions 5 | { 6 | public static class XElmentExtensions 7 | { 8 | public static bool AttributeEquals(this XAttribute attribute, string expectedValue, 9 | StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) 10 | { 11 | if (attribute == null || attribute.Value.IsNotSet()) 12 | { 13 | return false; 14 | } 15 | 16 | return attribute.Value.Equals(expectedValue, comparison); 17 | 18 | 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Packager/Factories/CodingHistory/CdrCodingHistoryGenerator.cs: -------------------------------------------------------------------------------- 1 | using Packager.Models.FileModels; 2 | using Packager.Models.PodMetadataModels; 3 | 4 | namespace Packager.Factories.CodingHistory 5 | { 6 | public class CdrCodingHistoryGenerator:AbstractCodingHistoryGenerator 7 | { 8 | protected override string GenerateLine1(AudioPodMetadata metadata, DigitalAudioFile provenance, AbstractFile model) 9 | { 10 | return string.Format(CodingHistoryLine1Format, DigitalFormat, StereoSoundField, 11 | GeneratePlayerTextField(metadata, provenance)); 12 | } 13 | 14 | protected override string GenerateLine2(AudioPodMetadata metadata, DigitalAudioFile provenance, AbstractFile model) 15 | { 16 | return string.Empty; 17 | } 18 | 19 | protected override string GenerateLine3(AudioPodMetadata metadata, DigitalAudioFile provenance, AbstractFile model) 20 | { 21 | const string lineFormat = "A=PCM,F=44100,W=16,M={0},T=Lynx AES16;DIO"; 22 | return string.Format(lineFormat, StereoSoundField); 23 | } 24 | 25 | protected override string GenerateLine4(AudioPodMetadata metadata, DigitalAudioFile provenance, AbstractFile model) 26 | { 27 | return string.Empty; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Packager/Factories/CodingHistory/ICodingHistoryGenerator.cs: -------------------------------------------------------------------------------- 1 | using Packager.Models.FileModels; 2 | using Packager.Models.PodMetadataModels; 3 | 4 | namespace Packager.Factories.CodingHistory 5 | { 6 | public interface ICodingHistoryGenerator 7 | { 8 | string Generate(AudioPodMetadata metadata, DigitalAudioFile provenance, AbstractFile model); 9 | } 10 | } -------------------------------------------------------------------------------- /Packager/Factories/CodingHistory/LacquerDiscIreneCodingHistoryGenerator.cs: -------------------------------------------------------------------------------- 1 | using Packager.Models.FileModels; 2 | using Packager.Models.PodMetadataModels; 3 | 4 | namespace Packager.Factories.CodingHistory 5 | { 6 | public class LacquerDiscIreneCodingHistoryGenerator : AbstractCodingHistoryGenerator 7 | { 8 | private const string Line1 = "A=ANALOG,M=Mono,T=IRENE;Lacquer Disc,"; 9 | private const string Line2 = "A=TIFF,M=Mono,T=IRENE imaging sensor,"; 10 | private const string Line3 = "A=PCM,F=130000,W=32fp,M=Mono,T=Weaver software,"; 11 | private const string Line4 = "A=PCM,F=96000,W=24,M=Mono,T=Izotope RX6"; 12 | 13 | protected override string GenerateLine1(AudioPodMetadata metadata, DigitalAudioFile provenance, AbstractFile model) 14 | { 15 | return Line1; 16 | } 17 | 18 | protected override string GenerateLine2(AudioPodMetadata metadata, DigitalAudioFile provenance, AbstractFile model) 19 | { 20 | return Line2; 21 | } 22 | 23 | protected override string GenerateLine3(AudioPodMetadata metadata, DigitalAudioFile provenance, AbstractFile model) 24 | { 25 | return Line3; 26 | } 27 | 28 | protected override string GenerateLine4(AudioPodMetadata metadata, DigitalAudioFile provenance, AbstractFile model) 29 | { 30 | return Line4; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Packager/Factories/FFMPEGArguments/AbstractFFMPEGArgumentGenerator.cs: -------------------------------------------------------------------------------- 1 | using Packager.Utilities.ProcessRunners; 2 | 3 | namespace Packager.Factories.FFMPEGArguments 4 | { 5 | public abstract class AbstractFFMPEGArgumentGenerator : IFFMPEGArgumentsGenerator 6 | { 7 | protected ArgumentBuilder AccessArguments { get; set; } 8 | protected ArgumentBuilder NormalizingArguments { get; set; } 9 | protected ArgumentBuilder ProdOrMezzArguments { get; set; } 10 | 11 | public ArgumentBuilder GetAccessArguments() => AccessArguments.Clone(); 12 | public ArgumentBuilder GetNormalizingArguments() => NormalizingArguments.Clone(); 13 | public ArgumentBuilder GetProdOrMezzArguments() => ProdOrMezzArguments.Clone(); 14 | } 15 | } -------------------------------------------------------------------------------- /Packager/Factories/FFMPEGArguments/CdrFFMPEGArgumentsGenerator.cs: -------------------------------------------------------------------------------- 1 | using Packager.Models.SettingsModels; 2 | using Packager.Utilities.ProcessRunners; 3 | 4 | namespace Packager.Factories.FFMPEGArguments 5 | { 6 | public class CdrFFMPEGArgumentsGenerator : AudioFFMPEGArgumentsGenerator 7 | { 8 | public CdrFFMPEGArgumentsGenerator(IProgramSettings programSettings) : base(programSettings) 9 | { 10 | // use normalizing arguments for production master 11 | ProdOrMezzArguments = NormalizingArguments; 12 | AccessArguments = new ArgumentBuilder("-c:a aac -b:a 192k -strict -2 -ar 44100 -map_metadata -1"); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Packager/Factories/FFMPEGArguments/FFMPEGArgumentsFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Common.Models; 3 | using Packager.Exceptions; 4 | using Packager.Utilities.ProcessRunners; 5 | 6 | namespace Packager.Factories.FFMPEGArguments 7 | { 8 | public class FFMPEGArgumentsFactory : IFFMPEGArgumentsFactory 9 | { 10 | private Dictionary Generators { get; } 11 | 12 | public FFMPEGArgumentsFactory(Dictionary generators) 13 | { 14 | Generators = generators; 15 | } 16 | 17 | private IFFMPEGArgumentsGenerator GetGenerator(IMediaFormat format) 18 | { 19 | if (!Generators.ContainsKey(format)) 20 | { 21 | throw new FormatNotSupportedException(format); 22 | } 23 | 24 | return Generators[format]; 25 | } 26 | 27 | public ArgumentBuilder GetAccessArguments(IMediaFormat format) => 28 | GetGenerator(format).GetAccessArguments(); 29 | 30 | public ArgumentBuilder GetNormalizingArguments(IMediaFormat format) => 31 | GetGenerator(format).GetNormalizingArguments(); 32 | 33 | public ArgumentBuilder GetProdOrMezzArguments(IMediaFormat format) => 34 | GetGenerator(format).GetProdOrMezzArguments(); 35 | } 36 | } -------------------------------------------------------------------------------- /Packager/Factories/FFMPEGArguments/IFFMPEGArgumentsFactory.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | using Packager.Utilities.ProcessRunners; 3 | 4 | namespace Packager.Factories.FFMPEGArguments 5 | { 6 | public interface IFFMPEGArgumentsFactory 7 | { 8 | ArgumentBuilder GetAccessArguments(IMediaFormat format); 9 | ArgumentBuilder GetNormalizingArguments(IMediaFormat format); 10 | ArgumentBuilder GetProdOrMezzArguments(IMediaFormat format); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Packager/Factories/FFMPEGArguments/IFFMPEGArgumentsGenerator.cs: -------------------------------------------------------------------------------- 1 | using Packager.Utilities.ProcessRunners; 2 | 3 | namespace Packager.Factories.FFMPEGArguments 4 | { 5 | public interface IFFMPEGArgumentsGenerator 6 | { 7 | ArgumentBuilder GetAccessArguments(); 8 | ArgumentBuilder GetNormalizingArguments(); 9 | ArgumentBuilder GetProdOrMezzArguments(); 10 | } 11 | } -------------------------------------------------------------------------------- /Packager/Factories/FFMPEGArguments/VideoFFMPEGArgumentsGenerator.cs: -------------------------------------------------------------------------------- 1 | using Packager.Models.SettingsModels; 2 | using Packager.Utilities.ProcessRunners; 3 | 4 | namespace Packager.Factories.FFMPEGArguments 5 | { 6 | public class VideoFFMPEGArgumentsGenerator : AbstractFFMPEGArgumentGenerator 7 | { 8 | public VideoFFMPEGArgumentsGenerator(IProgramSettings programSettings) 9 | { 10 | NormalizingArguments = new ArgumentBuilder("-map 0 -acodec copy -vcodec copy"); 11 | AccessArguments = new ArgumentBuilder(programSettings.FFMPEGVideoAccessArguments); 12 | ProdOrMezzArguments = new ArgumentBuilder(programSettings.FFMPEGVideoMezzanineArguments); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Packager/Factories/ICarrierDataFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Packager.Models.FileModels; 5 | using Packager.Models.OutputModels.Carrier; 6 | using Packager.Models.PodMetadataModels; 7 | 8 | namespace Packager.Factories 9 | { 10 | public interface ICarrierDataFactory where T:AbstractPodMetadata 11 | { 12 | Task Generate(T metadata, string digitizingEntity, List filesToProcess, CancellationToken cancellationToken); 13 | } 14 | } -------------------------------------------------------------------------------- /Packager/Factories/IEmbeddedMetadataFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Packager.Models.EmbeddedMetadataModels; 3 | using Packager.Models.FileModels; 4 | using Packager.Models.PodMetadataModels; 5 | 6 | namespace Packager.Factories 7 | { 8 | public interface IEmbeddedMetadataFactory where T : AbstractPodMetadata 9 | { 10 | AbstractEmbeddedMetadata Generate(IEnumerable models, AbstractFile target, T metadata); 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Factories/IImportable.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | 3 | namespace Packager.Factories 4 | { 5 | public interface IImportable 6 | { 7 | void ImportFromXml(XElement element, IImportableFactory factory); 8 | } 9 | } -------------------------------------------------------------------------------- /Packager/Factories/IIngestDataFactory.cs: -------------------------------------------------------------------------------- 1 | using Packager.Models.OutputModels.Ingest; 2 | using Packager.Models.PodMetadataModels; 3 | 4 | namespace Packager.Factories 5 | { 6 | public interface IIngestDataFactory 7 | { 8 | AbstractIngest Generate(DigitalAudioFile provenance); 9 | AbstractIngest Generate(DigitalVideoFile provenance); 10 | } 11 | } -------------------------------------------------------------------------------- /Packager/Factories/IPlaceHolderFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Common.Models; 3 | using Packager.Models.FileModels; 4 | 5 | namespace Packager.Factories 6 | { 7 | public interface IPlaceHolderFactory 8 | { 9 | List GetPlaceHoldersToAdd(IMediaFormat format, List fileModels); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Packager/Factories/ISideDataFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Packager.Models.FileModels; 3 | using Packager.Models.OutputModels; 4 | using Packager.Models.PodMetadataModels; 5 | 6 | namespace Packager.Factories 7 | { 8 | public interface ISideDataFactory 9 | { 10 | SideData[] Generate(AudioPodMetadata podMetadata, IEnumerable filesToProcess); 11 | SideData[] Generate(VideoPodMetadata podMetadata, IEnumerable filesToProcess); 12 | } 13 | } -------------------------------------------------------------------------------- /Packager/Factories/PlaceHolderFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Common.Models; 3 | using Packager.Models.FileModels; 4 | using Packager.Models.PlaceHolderConfigurations; 5 | using Packager.Observers; 6 | 7 | namespace Packager.Factories 8 | { 9 | public class PlaceHolderFactory : IPlaceHolderFactory 10 | { 11 | public PlaceHolderFactory( 12 | Dictionary knownConfigurations, 13 | IObserverCollection observers) 14 | { 15 | _knownConfigurations = knownConfigurations; 16 | _observers = observers; 17 | } 18 | 19 | private readonly Dictionary _knownConfigurations; 20 | private readonly IObserverCollection _observers; 21 | 22 | public List GetPlaceHoldersToAdd(IMediaFormat format, List fileModels) 23 | { 24 | if (!_knownConfigurations.ContainsKey(format)) 25 | { 26 | _observers.Log("No placeholder configuration found for format {0}", format.ProperName); 27 | return new List(); 28 | } 29 | 30 | return _knownConfigurations[format] 31 | .GetPlaceHoldersToAdd(fileModels); 32 | } 33 | 34 | 35 | } 36 | } -------------------------------------------------------------------------------- /Packager/Instructions.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IUMDPI/IUMediaHelperApps/32afb704dc9c7691ca0b0f1c3ff01b8bbd451f53/Packager/Instructions.docx -------------------------------------------------------------------------------- /Packager/Models/EmailMessageModels/AbstractEmailMessage.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | 4 | namespace Packager.Models.EmailMessageModels 5 | { 6 | public abstract class AbstractEmailMessage 7 | { 8 | private const string AttachmentFormat = "

For more details, see the attached {0}: {1}

"; 9 | 10 | protected AbstractEmailMessage(string[] toAddresses, string fromAddress, string[] attachments) 11 | { 12 | ToAddresses = toAddresses; 13 | From = fromAddress; 14 | Attachments = attachments; 15 | } 16 | 17 | public string[] ToAddresses { get; } 18 | public string From { get; } 19 | public abstract string Title { get; } 20 | public abstract string Body { get; } 21 | public string[] Attachments { get; } 22 | 23 | protected string GetAttachmentsText() 24 | { 25 | if (!Attachments.Any()) return ""; 26 | 27 | return Attachments.Length == 1 28 | ? string.Format(AttachmentFormat, "log", Path.GetFileName(Attachments.Single())) 29 | : string.Format(AttachmentFormat, "logs", string.Join(", ", Attachments.Select(Path.GetFileName))); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Packager/Models/EmbeddedMetadataModels/AbstractEmbeddedMetadata.cs: -------------------------------------------------------------------------------- 1 | using Packager.Utilities; 2 | using Packager.Utilities.ProcessRunners; 3 | 4 | namespace Packager.Models.EmbeddedMetadataModels 5 | { 6 | public abstract class AbstractEmbeddedMetadata 7 | { 8 | public abstract ArgumentBuilder AsArguments(); 9 | } 10 | } -------------------------------------------------------------------------------- /Packager/Models/EmbeddedMetadataModels/AbstractEmbeddedVideoMetadata.cs: -------------------------------------------------------------------------------- 1 | using Packager.Extensions; 2 | using Packager.Utilities.ProcessRunners; 3 | 4 | namespace Packager.Models.EmbeddedMetadataModels 5 | { 6 | public abstract class AbstractEmbeddedVideoMetadata : AbstractEmbeddedMetadata 7 | { 8 | public string Title { get; set; } 9 | public string Description { get; set; } 10 | public string MasteredDate { get; set; } 11 | public string Comment { get; set; } 12 | 13 | public override ArgumentBuilder AsArguments() 14 | { 15 | var arguments = new ArgumentBuilder 16 | { 17 | $"-metadata title={Title.NormalizeForCommandLine().ToQuoted()}", 18 | $"-metadata comment={Comment.NormalizeForCommandLine().ToQuoted()}", 19 | $"-metadata description={Description.NormalizeForCommandLine().ToQuoted()}" 20 | }; 21 | return arguments; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Packager/Models/EmbeddedMetadataModels/EmbeddedVideoMezzanineMetadata.cs: -------------------------------------------------------------------------------- 1 | using Packager.Extensions; 2 | using Packager.Utilities.ProcessRunners; 3 | 4 | namespace Packager.Models.EmbeddedMetadataModels 5 | { 6 | public class EmbeddedVideoMezzanineMetadata : AbstractEmbeddedVideoMetadata 7 | { 8 | public override ArgumentBuilder AsArguments() 9 | { 10 | var arguments = base.AsArguments(); 11 | arguments.Add($"-metadata date={MasteredDate.NormalizeForCommandLine().ToQuoted()}"); 12 | return arguments; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Packager/Models/EmbeddedMetadataModels/EmbeddedVideoPreservationMetadata.cs: -------------------------------------------------------------------------------- 1 | using Packager.Extensions; 2 | using Packager.Utilities.ProcessRunners; 3 | 4 | namespace Packager.Models.EmbeddedMetadataModels 5 | { 6 | public class EmbeddedVideoPreservationMetadata : AbstractEmbeddedVideoMetadata 7 | { 8 | public override ArgumentBuilder AsArguments() 9 | { 10 | var arguments = base.AsArguments(); 11 | arguments.Add($"-metadata date_digitized={MasteredDate.NormalizeForCommandLine().ToQuoted()}"); 12 | return arguments; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/AbstractPreservationFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public abstract class AbstractPreservationFile : AbstractFile 6 | { 7 | 8 | protected AbstractPreservationFile(AbstractFile original, string extension) : 9 | base(original, FileUsages.PreservationMaster, extension) 10 | { 11 | } 12 | 13 | public override bool ShouldNormalize => true; 14 | 15 | public override int Precedence => 0; 16 | } 17 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/AbstractPreservationIntermediateFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public abstract class AbstractPreservationIntermediateFile : AbstractFile 6 | { 7 | protected AbstractPreservationIntermediateFile(AbstractFile original, string extension) : 8 | base(original, FileUsages.PreservationIntermediateMaster, extension) 9 | { 10 | } 11 | 12 | public override bool ShouldNormalize => true; 13 | public override int Precedence => 2; 14 | } 15 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/AccessFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public class AccessFile : AbstractFile 6 | { 7 | private const string ExtensionValue = ".mp4"; 8 | 9 | public AccessFile(AbstractFile original) : 10 | base(original, FileUsages.AccessFile, ExtensionValue) 11 | { 12 | } 13 | 14 | public override int Precedence => 5; 15 | } 16 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/AudioPreservationFile.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Models.FileModels 2 | { 3 | public class AudioPreservationFile : AbstractPreservationFile 4 | { 5 | public AudioPreservationFile(AbstractFile original) : base(original, original.Extension) 6 | { 7 | } 8 | 9 | public override bool ShouldNormalize => Extension.Equals(".wav"); 10 | } 11 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/AudioPreservationIntermediateFile.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Models.FileModels 2 | { 3 | public class AudioPreservationIntermediateFile : AbstractPreservationIntermediateFile 4 | { 5 | private const string ExtensionValue = ".wav"; 6 | 7 | public AudioPreservationIntermediateFile(AbstractFile original) : base(original, ExtensionValue) 8 | { 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/AudioPreservationIntermediateToneReferenceFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public class AudioPreservationIntermediateToneReferenceFile : AbstractFile 6 | { 7 | private const string ExtensionValue = ".wav"; 8 | 9 | public AudioPreservationIntermediateToneReferenceFile(AbstractFile original) : 10 | base(original, FileUsages.PreservationIntermediateToneReference, ExtensionValue) 11 | { 12 | } 13 | 14 | public override bool ShouldNormalize => true; 15 | public override int Precedence => 3; 16 | } 17 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/AudioPreservationToneReferenceFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public class AudioPreservationToneReferenceFile : AbstractFile 6 | { 7 | private const string ExtensionValue = ".wav"; 8 | 9 | public AudioPreservationToneReferenceFile(AbstractFile original) : 10 | base(original, FileUsages.PreservationToneReference, ExtensionValue) 11 | { 12 | } 13 | 14 | public override bool ShouldNormalize => true; 15 | 16 | public override int Precedence => 1; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Packager/Models/FileModels/CueFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public class CueFile : AbstractFile 6 | { 7 | private const string ExtensionValue = ".cue"; 8 | 9 | public CueFile(AbstractFile original) : base(original, ExtensionValue) 10 | { 11 | } 12 | 13 | public override int Precedence => FileUsage == FileUsages.PreservationMaster ? 1 : 3; 14 | } 15 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/FilesArchiveFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public class FilesArchiveFile: AbstractFile 6 | { 7 | private const string ExtensionValue = ".zip"; 8 | 9 | public FilesArchiveFile(AbstractFile original): base(original, ExtensionValue) 10 | { 11 | } 12 | 13 | public override int Precedence => 7; 14 | } 15 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/InfoFile.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Models.FileModels 2 | { 3 | public class InfoFile : AbstractFile 4 | { 5 | private const string ExtensionValue = ".info"; 6 | 7 | public InfoFile(AbstractFile original) : base(original, original.FileUsage, ExtensionValue) 8 | { 9 | } 10 | 11 | public override int Precedence => 26; 12 | } 13 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/MediaInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Models.FileModels 2 | { 3 | public class MediaInfo 4 | { 5 | public int AudioStreams { get; set; } 6 | public int VideoStreams { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Packager/Models/FileModels/MezzanineFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public class MezzanineFile : AbstractFile 6 | { 7 | private const string ExtensionValue = ".mov"; 8 | 9 | public MezzanineFile(AbstractFile original) : 10 | base(original, FileUsages.MezzanineFile, ExtensionValue) 11 | { 12 | } 13 | 14 | public override bool ShouldNormalize => true; 15 | public override int Precedence => 4; 16 | } 17 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/PlaceHolderFile.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Models.FileModels 2 | { 3 | public class PlaceHolderFile : UnknownFile 4 | { 5 | public PlaceHolderFile(string projectCode, string barcode, int sequenceIndicator, string extension) 6 | : base($"{projectCode}_{barcode}_{sequenceIndicator}_pres.{extension}") 7 | { 8 | IsPlaceHolder = true; 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/ProductionFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public class ProductionFile : AbstractFile 6 | { 7 | private const string ExtensionValue = ".wav"; 8 | 9 | public ProductionFile(AbstractFile original) : 10 | base(original, FileUsages.ProductionMaster, ExtensionValue) 11 | { 12 | } 13 | 14 | public override bool ShouldNormalize => true; 15 | public override int Precedence => 4; 16 | } 17 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/QualityControlFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public class QualityControlFile : AbstractFile 6 | { 7 | private const string ExtensionValue = ".qctools.xml.gz"; 8 | private const string IntermediateExtensionValue = ".qctools.xml"; 9 | 10 | public string IntermediateFileName { get; } 11 | 12 | public QualityControlFile(AbstractFile original) : 13 | base(original, new QualityControlFileUsage(original.FileUsage), ExtensionValue) 14 | { 15 | Filename = $"{original.Filename}{ExtensionValue}"; 16 | IntermediateFileName = $"{original.Filename}{IntermediateExtensionValue}"; 17 | } 18 | 19 | public override int Precedence => 7; 20 | } 21 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/TextFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Extensions; 2 | using Common.Models; 3 | 4 | namespace Packager.Models.FileModels 5 | { 6 | public class TextFile : AbstractFile 7 | { 8 | private const string ExtensionValue = ".txt"; 9 | 10 | public TextFile(AbstractFile original) : base(original, ExtensionValue) 11 | { 12 | FileUsage= FileUsages.TextFile; 13 | SequenceIndicator = 1; 14 | } 15 | 16 | protected override string NormalizeFilename() 17 | { 18 | var parts = new[] 19 | { 20 | ProjectCode, 21 | BarCode 22 | }; 23 | 24 | return string.Join("_", parts) + Extension; 25 | } 26 | 27 | public override bool IsImportable() 28 | { 29 | if (ProjectCode.IsNotSet()) 30 | { 31 | return false; 32 | } 33 | 34 | if (BarCode.IsNotSet()) 35 | { 36 | return false; 37 | } 38 | 39 | if (Extension.IsNotSet()) 40 | { 41 | return false; 42 | } 43 | 44 | if (!FileUsages.IsImportable(FileUsage)) 45 | { 46 | return false; 47 | } 48 | 49 | return true; 50 | } 51 | 52 | public override int Precedence => 9; 53 | } 54 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/TiffImageFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | 3 | namespace Packager.Models.FileModels 4 | { 5 | public class TiffImageFile:AbstractFile 6 | { 7 | private const string ExtensionValue = ".tif"; 8 | 9 | public TiffImageFile(AbstractFile original) : base(original, FileUsages.LabelImageFile, ExtensionValue) 10 | { 11 | } 12 | 13 | public override int Precedence => 6; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Packager/Models/FileModels/UnknownFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Common.Models; 4 | using Packager.Extensions; 5 | 6 | namespace Packager.Models.FileModels 7 | { 8 | public class UnknownFile : AbstractFile 9 | { 10 | public UnknownFile(string file) 11 | { 12 | var parts = GetPathParts(file); 13 | 14 | ProjectCode = parts.FromIndex(0, string.Empty).ToUpperInvariant(); 15 | BarCode = parts.FromIndex(1, string.Empty).ToLowerInvariant(); 16 | SequenceIndicator = GetSequenceIndicator(parts.FromIndex(2, string.Empty)); 17 | Extension = Path.GetExtension(file); 18 | FileUsage = FileUsages.GetUsage(parts.FromIndex(3, string.Empty)); 19 | OriginalFileName = Path.GetFileName(file); 20 | Filename = OriginalFileName; 21 | } 22 | 23 | private static string[] GetPathParts(string path) 24 | { 25 | return Path.GetFileNameWithoutExtension(path) 26 | .ToDefaultIfEmpty() 27 | .ToLowerInvariant() 28 | .Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries); 29 | } 30 | 31 | public override bool IsImportable() 32 | { 33 | return false; 34 | } 35 | 36 | public override int Precedence => 200; 37 | } 38 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/VideoPreservationFile.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Models.FileModels 2 | { 3 | public class VideoPreservationFile : AbstractPreservationFile 4 | { 5 | private const string ExtensionValue = ".mkv"; 6 | 7 | public VideoPreservationFile(AbstractFile original) : base(original, ExtensionValue) 8 | { 9 | } 10 | 11 | public override bool ShouldNormalize => true; 12 | } 13 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/VideoPreservationIntermediateFile.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Models.FileModels 2 | { 3 | public class VideoPreservationIntermediateFile : AbstractPreservationIntermediateFile 4 | { 5 | private const string ExtensionValue = ".mkv"; 6 | 7 | public VideoPreservationIntermediateFile(AbstractFile original) : base(original, ExtensionValue) 8 | { 9 | } 10 | 11 | public override bool ShouldNormalize => true; 12 | } 13 | } -------------------------------------------------------------------------------- /Packager/Models/FileModels/XmlFile.cs: -------------------------------------------------------------------------------- 1 | using Common.Models; 2 | using Packager.Extensions; 3 | 4 | namespace Packager.Models.FileModels 5 | { 6 | public class XmlFile : AbstractFile 7 | { 8 | public XmlFile(string projectCode, string barCode) 9 | { 10 | ProjectCode = projectCode; 11 | BarCode = barCode; 12 | Extension = ".xml"; 13 | Filename = $"{ProjectCode}_{BarCode}{Extension}"; 14 | FileUsage = FileUsages.None; 15 | } 16 | 17 | public override int Precedence => 100; 18 | 19 | public override bool IsImportable() 20 | { 21 | return ProjectCode.IsSet() && BarCode.IsSet(); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/AudioConfigurationData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RestSharp.Extensions; 3 | 4 | namespace Packager.Models.OutputModels 5 | { 6 | [Serializable] 7 | public class AudioConfigurationData 8 | { 9 | public string Track { get; set; } 10 | public string SoundField { get; set; } 11 | public string Speed { get; set; } 12 | public string RecordingType { get; set; } 13 | 14 | public string TapeType { get; set; } 15 | public string TapeStockBrand { get; set; } 16 | public string NoiseReduction { get; set; } 17 | public string FormatDuration { get; set; } 18 | 19 | public bool ShouldSerializeTrack() => Track.HasValue(); 20 | public bool ShouldSerializeSoundField() => SoundField.HasValue(); 21 | public bool ShouldSerializeSpeed() => Speed.HasValue(); 22 | public bool ShouldSerializeRecordingType() => RecordingType.HasValue(); 23 | public bool ShouldSerializeTapeType() => TapeType.HasValue(); 24 | public bool ShouldSerializeTapeStockBrand() => TapeStockBrand.HasValue(); 25 | public bool ShouldSerializeNoiseReduction() => NoiseReduction.HasValue(); 26 | public bool ShouldSerializeFormatDuration() => FormatDuration.HasValue(); 27 | } 28 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/BakingData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Packager.Extensions; 3 | 4 | namespace Packager.Models.OutputModels 5 | { 6 | [Serializable] 7 | public class BakingData 8 | { 9 | public string Date { get; set; } 10 | 11 | public bool ShouldSerializeDate() 12 | { 13 | return Date.IsSet(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/Carrier/AbstractCarrierData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | 4 | namespace Packager.Models.OutputModels.Carrier 5 | { 6 | [Serializable] 7 | [XmlInclude(typeof (VideoCarrier))] 8 | [XmlInclude(typeof (AudioCarrier))] 9 | public abstract class AbstractCarrierData 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/Carrier/RecordCarrier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Packager.Models.OutputModels.Carrier 4 | { 5 | [Serializable] 6 | public class RecordCarrier:AudioCarrier 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Packager/Models/OutputModels/CleaningData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Packager.Extensions; 3 | 4 | namespace Packager.Models.OutputModels 5 | { 6 | [Serializable] 7 | public class CleaningData 8 | { 9 | public string Date { get; set; } 10 | public string Comment { get; set; } 11 | 12 | public bool ShouldSerializeDate() 13 | { 14 | return Date.IsSet(); 15 | } 16 | 17 | public bool ShouldSerializeComment() 18 | { 19 | return Comment.IsSet(); 20 | } 21 | } 22 | 23 | 24 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/ExportableManifest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | using Packager.Models.OutputModels.Carrier; 4 | 5 | namespace Packager.Models.OutputModels 6 | { 7 | [Serializable] 8 | [XmlRoot(ElementName = "IU")] 9 | public class ExportableManifest 10 | { 11 | public AbstractCarrierData Carrier { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/File.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | using Common.Extensions; 4 | 5 | namespace Packager.Models.OutputModels 6 | { 7 | [Serializable] 8 | public class File 9 | { 10 | public File() 11 | { 12 | PlaceHolder = string.Empty; // ensures that placeholder node gets 13 | // serialized as 14 | } 15 | 16 | [XmlElement("FileName", Order = 1)] 17 | public string FileName { get; set; } 18 | 19 | [XmlElement("CheckSum", Order =2)] 20 | public string Checksum { get; set; } 21 | 22 | [XmlElement("PlaceHolder", Order = 3)] 23 | public string PlaceHolder {get;set; } 24 | 25 | // include Checksum node if it is set; otherwise, suppress it 26 | public bool ShouldSerializeChecksum() => Checksum.IsSet(); 27 | 28 | // if checksum node is not set, include PlaceHolder node; 29 | // otherwise suppress PlaceHolder node 30 | public bool ShouldSerializePlaceHolder() => Checksum.IsNotSet(); 31 | } 32 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/ImportableManifest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | using Packager.Models.OutputModels.Carrier; 4 | 5 | namespace Packager.Models.OutputModels 6 | { 7 | [Serializable] 8 | [XmlRoot(ElementName = "IU")] 9 | public class ImportableManifest where T: AbstractCarrierData 10 | { 11 | public T Carrier { get; set; } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/Ingest/AbstractIngest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | 4 | namespace Packager.Models.OutputModels.Ingest 5 | { 6 | [Serializable] 7 | [XmlInclude(typeof (VideoIngest))] 8 | [XmlInclude(typeof (AudioIngest))] 9 | public class AbstractIngest 10 | { 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/Ingest/Device.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Models.OutputModels.Ingest 2 | { 3 | public class Device 4 | { 5 | public string Model { get; set; } 6 | public string SerialNumber { get; set; } 7 | public string Manufacturer { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/Ingest/VideoIngest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | 4 | namespace Packager.Models.OutputModels.Ingest 5 | { 6 | [Serializable] 7 | public class VideoIngest : AbstractIngest 8 | { 9 | [XmlElement(Order = 1)] 10 | public string FileName { get; set; } 11 | 12 | [XmlElement(Order = 2)] 13 | public string Date { get; set; } 14 | 15 | [XmlElement(Order = 3)] 16 | public string Comments { get; set; } 17 | 18 | [XmlElement(ElementName = "Created_by", Order = 4)] 19 | public string CreatedBy { get; set; } 20 | 21 | [XmlElement(Order = 5, ElementName = "Player")] 22 | public Device[] Players { get; set; } 23 | 24 | [XmlElement(Order = 6, ElementName = "TBC")] 25 | public Device[] TbcDevices { get; set; } 26 | 27 | [XmlElement(Order = 7, ElementName = "AD")] 28 | public Device[] AdDevices { get; set; } 29 | 30 | [XmlElement(Order = 8)] 31 | public Device Encoder { get; set; } 32 | 33 | [XmlElement(Order = 9, ElementName = "Extraction_workstation")] 34 | public Device ExtractionWorkstation { get; set; } 35 | 36 | 37 | } 38 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/PartsData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | 4 | namespace Packager.Models.OutputModels 5 | { 6 | [Serializable] 7 | public class PartsData 8 | { 9 | public string DigitizingEntity { get; set; } 10 | 11 | [XmlElement("Part")] 12 | public SideData[] Sides { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/PhysicalConditionData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Packager.Extensions; 3 | 4 | namespace Packager.Models.OutputModels 5 | { 6 | [Serializable] 7 | public class PhysicalConditionData 8 | { 9 | public string Damage { get; set; } 10 | public string PreservationProblem { get; set; } 11 | 12 | public bool ShouldSerializePreservationProblem() 13 | { 14 | return PreservationProblem.IsSet(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/PreviewData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Packager.Extensions; 3 | 4 | namespace Packager.Models.OutputModels 5 | { 6 | [Serializable] 7 | public class PreviewData 8 | { 9 | public string Comments { get; set; } 10 | 11 | public bool ShouldSerializeComments() 12 | { 13 | return Comments.IsSet(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/SideData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Xml.Serialization; 4 | using Packager.Extensions; 5 | using Packager.Models.OutputModels.Ingest; 6 | 7 | namespace Packager.Models.OutputModels 8 | { 9 | [Serializable] 10 | public class SideData 11 | { 12 | [XmlAttribute("Side")] 13 | public string Side { get; set; } 14 | 15 | [XmlElement("Ingest")] 16 | public List Ingest { get; set; } 17 | 18 | public List Files { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /Packager/Models/OutputModels/VideoConfigurationData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Packager.Models.OutputModels 4 | { 5 | [Serializable] 6 | public class VideoConfigurationData 7 | { 8 | public string DigitalFileConfigurationVariant { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /Packager/Models/PlaceHolderConfigurations/IPlaceHolderConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Packager.Models.FileModels; 3 | 4 | namespace Packager.Models.PlaceHolderConfigurations 5 | { 6 | public interface IPlaceHolderConfiguration 7 | { 8 | List GetPlaceHoldersToAdd(List fileModels); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Packager/Models/PlaceHolderConfigurations/PresIntAudioPlaceHolderConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Common.Models; 3 | using Packager.Extensions; 4 | using Packager.Factories; 5 | using Packager.Models.FileModels; 6 | 7 | namespace Packager.Models.PlaceHolderConfigurations 8 | { 9 | public class PresIntAudioPlaceHolderConfiguration : AbstractPlaceHolderConfiguration 10 | { 11 | public PresIntAudioPlaceHolderConfiguration() : base(new List { FileUsages.PreservationMaster, 12 | FileUsages.PreservationIntermediateMaster, 13 | FileUsages.ProductionMaster, 14 | FileUsages.AccessFile}) 15 | { 16 | } 17 | 18 | protected override List GetPlaceHolders(PlaceHolderFile template) 19 | { 20 | return new List 21 | { 22 | template.ConvertTo(), 23 | template.ConvertTo(), 24 | template.ConvertTo(), 25 | template.ConvertTo() 26 | }; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Packager/Models/PlaceHolderConfigurations/StandardAudioPlaceHolderConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Common.Models; 3 | using Packager.Extensions; 4 | using Packager.Models.FileModels; 5 | 6 | namespace Packager.Models.PlaceHolderConfigurations 7 | { 8 | public class StandardAudioPlaceHolderConfiguration : AbstractPlaceHolderConfiguration 9 | { 10 | public StandardAudioPlaceHolderConfiguration() : base( 11 | new List { 12 | FileUsages.PreservationMaster, 13 | FileUsages.ProductionMaster, 14 | FileUsages.AccessFile}) 15 | { 16 | } 17 | 18 | protected override List GetPlaceHolders(PlaceHolderFile template) 19 | { 20 | return new List 21 | { 22 | template.ConvertTo(), 23 | template.ConvertTo(), 24 | template.ConvertTo() 25 | }; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Packager/Models/PlaceHolderConfigurations/StandardVideoPlaceHolderConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Common.Models; 3 | using Packager.Extensions; 4 | using Packager.Models.FileModels; 5 | 6 | namespace Packager.Models.PlaceHolderConfigurations 7 | { 8 | public class StandardVideoPlaceHolderConfiguration : AbstractPlaceHolderConfiguration 9 | { 10 | public StandardVideoPlaceHolderConfiguration() : base(new List { 11 | FileUsages.PreservationMaster, 12 | FileUsages.MezzanineFile, 13 | FileUsages.AccessFile}) 14 | { 15 | } 16 | 17 | protected override List GetPlaceHolders(PlaceHolderFile template) 18 | { 19 | return new List 20 | { 21 | template.ConvertTo(), 22 | template.ConvertTo(), 23 | template.ConvertTo() 24 | }; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Packager/Models/PodMetadataModels/Device.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Linq; 3 | using Packager.Extensions; 4 | using Packager.Factories; 5 | 6 | namespace Packager.Models.PodMetadataModels 7 | { 8 | public class Device : IImportable 9 | { 10 | public string DeviceType { get; set; } 11 | public string SerialNumber { get; set; } 12 | public string Manufacturer { get; set; } 13 | public string Model { get; set; } 14 | 15 | public void ImportFromXml(XElement element, IImportableFactory factory) 16 | { 17 | DeviceType = factory.ToStringValue(element,"device_type"); 18 | SerialNumber = factory.ToStringValue(element,"serial_number"); 19 | Manufacturer = factory.ToStringValue(element,"manufacturer"); 20 | Model = factory.ToStringValue(element,"model"); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Packager/Models/PodMetadataModels/DigitalVideoFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Packager.Validators.Attributes; 5 | 6 | namespace Packager.Models.PodMetadataModels 7 | { 8 | public class DigitalVideoFile : AbstractDigitalFile 9 | { 10 | private const string VideoCaptureDeviceType = "video capture"; 11 | private const string TBCDeviceType = "tbc"; 12 | 13 | [Required] 14 | public Device Encoder 15 | { 16 | get 17 | { 18 | return SignalChain?. 19 | FirstOrDefault(d => d.DeviceType.Equals(VideoCaptureDeviceType, StringComparison.InvariantCultureIgnoreCase)); 20 | } 21 | } 22 | 23 | [HasMembers] 24 | public IEnumerable TBCDevices 25 | { 26 | get 27 | { 28 | return SignalChain?. 29 | Where(e => e.DeviceType.Equals(TBCDeviceType, StringComparison.InvariantCultureIgnoreCase)) ?? new List(); 30 | } 31 | } 32 | 33 | } 34 | } -------------------------------------------------------------------------------- /Packager/Models/PodMetadataModels/VideoPodMetadata.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Xml.Linq; 4 | using Packager.Factories; 5 | 6 | namespace Packager.Models.PodMetadataModels 7 | { 8 | public class VideoPodMetadata : AbstractPodMetadata 9 | { 10 | public string ImageFormat { get; set; } 11 | 12 | public string RecordingStandard { get; set; } 13 | 14 | public string FormatVersion { get; set; } 15 | 16 | public override void ImportFromXml(XElement element, IImportableFactory factory) 17 | { 18 | base.ImportFromXml(element, factory); 19 | ImageFormat = factory.ToStringValue(element, "data/image_format"); 20 | RecordingStandard = factory.ToStringValue(element, "data/recording_standard"); 21 | FormatVersion = factory.ToStringValue(element, "data/object/technical_metadata/format_version"); 22 | } 23 | 24 | protected override List ImportFileProvenances(XElement element, string path, 25 | IImportableFactory factory) 26 | { 27 | return factory.ToObjectList(element, path) 28 | .Cast().ToList(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Packager/Models/ProgramArgumentsModels/IProgramArguments.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Models.ProgramArgumentsModels 2 | { 3 | public interface IProgramArguments 4 | { 5 | bool Interactive { get; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Packager/Models/ProgramArgumentsModels/ProgramArguments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace Packager.Models.ProgramArgumentsModels 5 | { 6 | public class ProgramArguments : IProgramArguments 7 | { 8 | public ProgramArguments(string[] arguments) 9 | { 10 | Interactive = arguments.Any(a => a.Equals("-noninteractive", StringComparison.InvariantCultureIgnoreCase))==false; 11 | } 12 | 13 | public bool Interactive { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /Packager/Models/ResultModels/DurationResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Packager.Models.ResultModels 4 | { 5 | public class DurationResult 6 | { 7 | public TimeSpan Duration { get; } 8 | public DateTime Timestamp { get; } 9 | public bool Succeeded { get; } 10 | public bool Failed { get; } 11 | public bool Skipped { get; } 12 | public string Issue { get; } 13 | 14 | public DurationResult(DateTime startTime, string baseIssue, params object[] args) 15 | : this(startTime, false, true, false, string.Format(baseIssue, args)) 16 | { 17 | 18 | } 19 | 20 | private DurationResult(DateTime startTime, bool succeeded, bool failed, bool deferred, string issue) 21 | { 22 | Timestamp = startTime; 23 | Duration = DateTime.Now - startTime; 24 | Succeeded = succeeded; 25 | Failed = failed; 26 | Skipped = deferred; 27 | Issue = issue; 28 | 29 | } 30 | 31 | public static DurationResult Success(DateTime startTime) => 32 | new DurationResult(startTime, true, false, false, ""); 33 | 34 | public static DurationResult Deferred (DateTime startTime, string baseIssue, params object[] args) => 35 | new DurationResult(startTime, false, false, true, string.Format(baseIssue, args)); 36 | } 37 | } -------------------------------------------------------------------------------- /Packager/Models/ResultModels/IProcessResult.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Packager.Utilities; 3 | using Packager.Utilities.ProcessRunners; 4 | 5 | namespace Packager.Models.ResultModels 6 | { 7 | public interface IProcessResult 8 | { 9 | int ExitCode { get; set; } 10 | 11 | IOutputBuffer StandardOutput { get; } 12 | 13 | IOutputBuffer StandardError { get; } 14 | 15 | ProcessStartInfo StartInfo { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /Packager/Models/ResultModels/ProcessResult.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Packager.Utilities.ProcessRunners; 3 | 4 | namespace Packager.Models.ResultModels 5 | { 6 | public class ProcessResult : IProcessResult 7 | { 8 | public int ExitCode { get; set; } 9 | public IOutputBuffer StandardOutput { get; set; } 10 | public IOutputBuffer StandardError { get; set; } 11 | public ProcessStartInfo StartInfo { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Packager/Models/SettingsModels/IProgramSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms.VisualStyles; 2 | 3 | namespace Packager.Models.SettingsModels 4 | { 5 | public interface IProgramSettings 6 | { 7 | string BwfMetaEditPath { get; } 8 | string FFMPEGPath { get; } 9 | string FFProbePath { get; } 10 | string InputDirectory { get; } 11 | string ProcessingDirectory { get; } 12 | string FFMPEGAudioProductionArguments { get; } 13 | string FFMPEGAudioAccessArguments { get; } 14 | string FFMPEGVideoMezzanineArguments { get; } 15 | string FFMPEGVideoAccessArguments { get; } 16 | string FFProbeVideoQualityControlArguments { get; } 17 | string ProjectCode { get; } 18 | string DropBoxDirectoryName { get; } 19 | string WebServiceUrl { get; } 20 | string ErrorDirectoryName { get; } 21 | string SuccessDirectoryName { get; } 22 | string LogDirectoryName { get; } 23 | string[] IssueNotifyEmailAddresses { get; } 24 | string[] SuccessNotifyEmailAddresses { get; } 25 | string[] DeferredNotifyEmailAddresses { get; } 26 | string SmtpServer { get; } 27 | string FromEmailAddress { get; } 28 | int DeleteSuccessfulObjectsAfterDays { get; } 29 | string UnitPrefix { get; } 30 | string PodAuthFilePath { get; } 31 | string DigitizingEntity { get; } 32 | string ImageDirectory { get; } 33 | } 34 | } -------------------------------------------------------------------------------- /Packager/Models/SettingsModels/PodAuth.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | using Packager.Validators.Attributes; 4 | 5 | namespace Packager.Models.SettingsModels 6 | { 7 | [Serializable] 8 | [XmlRoot(ElementName = "Auth")] 9 | public class PodAuth 10 | { 11 | [XmlElement(ElementName = "username")] 12 | [Required] 13 | public string UserName { get; set; } 14 | 15 | [XmlElement(ElementName = "password")] 16 | [Required] 17 | public string Password { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Packager/Models/UserInterfaceModels/SectionModel.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Models.UserInterfaceModels 2 | { 3 | public class SectionModel 4 | { 5 | public int StartOffset { get; set; } 6 | public int EndOffset { get; set; } 7 | public string Key { get; set; } 8 | public bool Completed { get; set; } 9 | public int Indent { get; set; } 10 | public string Title { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/NOTICE: -------------------------------------------------------------------------------- 1 | INDIANA UNIVERSITY MEDIA HELPER APPLICATIONS: PACKAGER 2 | 3 | Automates the process of creating derivatives and embedding metadata 4 | in digital media objects. 5 | 6 | Copyright (C) 2014-2017, The Trustees of Indiana University. 7 | -------------------------------------------------------------------------------- /Packager/Observers/GeneralNLogObserver.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using NLog; 4 | using Packager.Extensions; 5 | using Packager.Models.SettingsModels; 6 | 7 | namespace Packager.Observers 8 | { 9 | public class GeneralNLogObserver : AbstractNLogObserver 10 | { 11 | private const string ThisLoggerName = "GeneralFileLogger"; 12 | 13 | private static readonly Logger Logger = LogManager.GetLogger(ThisLoggerName); 14 | 15 | public GeneralNLogObserver(IProgramSettings settings):base(ThisLoggerName, settings) 16 | { 17 | } 18 | 19 | protected override void Log(IEnumerable events) 20 | { 21 | foreach (var logEvent in events.Where(e => e.Message.IsSet())) 22 | { 23 | Logger.Log(logEvent); 24 | } 25 | } 26 | 27 | protected override void LogEvent(LogEventInfo eventInfo) 28 | { 29 | Logger.Log(eventInfo); 30 | } 31 | 32 | public override int UniqueIdentifier => 1; 33 | } 34 | } -------------------------------------------------------------------------------- /Packager/Observers/IObserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Packager.Observers 4 | { 5 | public interface IObserver 6 | { 7 | void Log(string baseMessage, params object[] elements); 8 | void LogProcessingError(Exception issue, string barcode); 9 | void LogEngineError(Exception issue); 10 | void BeginSection(string sectionKey, string baseMessage, params object[] elements); 11 | void EndSection(string sectionKey, string newTitle = "", bool collapse = false); 12 | int UniqueIdentifier { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /Packager/Observers/IObserverCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Packager.Observers 5 | { 6 | public interface IObserverCollection : ICollection 7 | { 8 | void Log(string baseMessage, params object[] elements); 9 | void LogProcessingIssue(Exception issue, string barcode); 10 | string BeginProcessingSection(string barcode, string baseMessage, params object[] elements); 11 | string BeginSection(string baseMessage, params object[] elements); 12 | void EndSection(string sectionKey, string newTitle = "", bool collapse = false); 13 | void LogEngineIssue(Exception exception); 14 | } 15 | } -------------------------------------------------------------------------------- /Packager/Observers/LayoutRenderers/BarcodeLayoutRenderer.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using NLog; 3 | using NLog.LayoutRenderers; 4 | 5 | namespace Packager.Observers.LayoutRenderers 6 | { 7 | [LayoutRenderer("ProcessingDirectoryName")] 8 | public class BarcodeLayoutRenderer:LayoutRenderer 9 | { 10 | protected override void Append(StringBuilder builder, LogEventInfo logEvent) 11 | { 12 | if (logEvent.Properties.ContainsKey("Barcode")) 13 | { 14 | builder.Append(logEvent.Properties["Barcode"]); 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Packager/Observers/LayoutRenderers/LoggingDirectoryLayoutRenderer.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using NLog; 3 | using NLog.LayoutRenderers; 4 | 5 | namespace Packager.Observers.LayoutRenderers 6 | { 7 | [LayoutRenderer("LogDirectoryName")] 8 | public class LoggingDirectoryLayoutRenderer:LayoutRenderer 9 | { 10 | protected override void Append(StringBuilder builder, LogEventInfo logEvent) 11 | { 12 | if (logEvent.Properties.ContainsKey("LogDirectoryName")) 13 | { 14 | builder.Append(logEvent.Properties["LogDirectoryName"]); 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Packager/Observers/LayoutRenderers/ProcessingDirectoryNameLayoutRenderer.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using NLog; 3 | using NLog.LayoutRenderers; 4 | 5 | namespace Packager.Observers.LayoutRenderers 6 | { 7 | [LayoutRenderer("ProcessingDirectoryName")] 8 | public class ProcessingDirectoryNameLayoutRenderer : LayoutRenderer 9 | { 10 | protected override void Append(StringBuilder builder, LogEventInfo logEvent) 11 | { 12 | if (logEvent.Properties.ContainsKey("ProcessingDirectoryName")) 13 | { 14 | builder.Append(logEvent.Properties["ProcessingDirectoryName"]); 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Packager/Observers/LayoutRenderers/ProjectCodeLayoutRenderer.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using NLog; 3 | using NLog.LayoutRenderers; 4 | 5 | namespace Packager.Observers.LayoutRenderers 6 | { 7 | [LayoutRenderer("ProcessingDirectoryName")] 8 | public class ProjectCodeLayoutRenderer:LayoutRenderer 9 | { 10 | protected override void Append(StringBuilder builder, LogEventInfo logEvent) 11 | { 12 | if (logEvent.Properties.ContainsKey("ProjectCode")) 13 | { 14 | builder.Append(logEvent.Properties["ProjectCode"]); 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Packager/Observers/ObjectNLogObserver.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using Packager.Extensions; 3 | using Packager.Models.SettingsModels; 4 | 5 | namespace Packager.Observers 6 | { 7 | public class ObjectNLogObserver : AbstractNLogObserver 8 | { 9 | private const string ThisLoggerName = "ObjectFileLogger"; 10 | 11 | public string CurrentBarcode { private get; set; } 12 | 13 | private static readonly Logger Logger = LogManager.GetLogger(ThisLoggerName); 14 | 15 | public ObjectNLogObserver(IProgramSettings settings) : base(ThisLoggerName, settings) 16 | { 17 | 18 | } 19 | 20 | public void ClearBarcode() 21 | { 22 | CurrentBarcode = string.Empty; 23 | } 24 | 25 | protected override LogEventInfo GetLogEvent(string message) 26 | { 27 | var logEvent = base.GetLogEvent(message); 28 | logEvent.Properties["Barcode"] = CurrentBarcode; 29 | return logEvent; 30 | } 31 | 32 | protected override void LogEvent(LogEventInfo eventInfo) 33 | { 34 | if (CurrentBarcode.IsNotSet()) 35 | { 36 | return; 37 | } 38 | 39 | Logger.Log(eventInfo); 40 | } 41 | 42 | public override int UniqueIdentifier => 2; 43 | } 44 | } -------------------------------------------------------------------------------- /Packager/Observers/ObserverCollectionEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Packager.Observers 4 | { 5 | internal class ObserverCollectionEqualityComparer : IEqualityComparer 6 | { 7 | public bool Equals(IObserver x, IObserver y) 8 | { 9 | return x.GetType() == y.GetType(); 10 | } 11 | 12 | public int GetHashCode(IObserver obj) 13 | { 14 | return obj.UniqueIdentifier; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Packager/Processors/IProcessor.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Packager.Models.FileModels; 5 | using Packager.Models.ResultModels; 6 | using Packager.Validators; 7 | 8 | namespace Packager.Processors 9 | { 10 | public interface IProcessor 11 | { 12 | Task ProcessObject(IGrouping fileModels, CancellationToken cancellationToken); 13 | } 14 | } -------------------------------------------------------------------------------- /Packager/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Packager.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Packager/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Packager/Providers/IDirectoryProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Threading.Tasks; 5 | 6 | namespace Packager.Providers 7 | { 8 | public interface IDirectoryProvider 9 | { 10 | IEnumerable EnumerateFiles(string path); 11 | DirectoryInfo CreateDirectory(string path); 12 | Task MoveDirectoryAsync(string sourcePath, string destPath); 13 | void MoveDirectory(string sourcePath, string destPath); 14 | bool DirectoryExists(string value); 15 | 16 | Task DeleteDirectoryAsync(string path); 17 | 18 | IEnumerable> GetFolderNamesAndCreationDates(string parent); 19 | } 20 | } -------------------------------------------------------------------------------- /Packager/Providers/IFileProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.IO; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace Packager.Providers 7 | { 8 | public interface IFileProvider 9 | { 10 | Task CopyFileAsync(string sourceFileName, string destFileName, CancellationToken cancellationToken); 11 | Task MoveFileAsync(string sourceFileName, string destFileName, CancellationToken cancellationToken); 12 | bool FileExists(string path); 13 | bool FileDoesNotExist(string path); 14 | FileInfo GetFileInfo(string path); 15 | void AppendText(string path, string text); 16 | string ReadAllText(string path); 17 | Task ArchiveFile(string filePath, string archivePath, CancellationToken cancellationToken); 18 | T Deserialize(string filePath); 19 | } 20 | } -------------------------------------------------------------------------------- /Packager/Providers/IMediaInfoProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Packager.Models.FileModels; 4 | 5 | namespace Packager.Providers 6 | { 7 | public interface IMediaInfoProvider 8 | { 9 | Task GetMediaInfo(AbstractFile target, CancellationToken cancellationToken); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Packager/Providers/IPodMetadataProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Packager.Models.FileModels; 5 | using Packager.Models.PodMetadataModels; 6 | 7 | namespace Packager.Providers 8 | { 9 | public interface IPodMetadataProvider 10 | { 11 | Task GetObjectMetadata(string barcode, CancellationToken cancellationToken) where T : AbstractPodMetadata, new(); 12 | T AdjustMediaFormat(T podMetadata, List models) where T: AbstractPodMetadata; 13 | T AdjustDigitalProvenanceData(T podMetadata, List models) where T : AbstractPodMetadata; 14 | void Validate(T podMetadata, List models) where T : AbstractPodMetadata; 15 | void Log(T podMetadata) where T : AbstractPodMetadata; 16 | } 17 | } -------------------------------------------------------------------------------- /Packager/Providers/ISystemInfoProvider.cs: -------------------------------------------------------------------------------- 1 | using Packager.Engine; 2 | 3 | namespace Packager.Providers 4 | { 5 | public interface ISystemInfoProvider 6 | { 7 | string MachineName { get; } 8 | string CurrentSystemLogPath { get; } 9 | void ExitApplication(EngineExitCodes exitCode); 10 | } 11 | } -------------------------------------------------------------------------------- /Packager/UserInterface/CancelPanel.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Packager/UserInterface/CancelPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Packager.UserInterface 17 | { 18 | /// 19 | /// Interaction logic for CancelPanel.xaml 20 | /// 21 | public partial class CancelPanel : UserControl 22 | { 23 | public CancelPanel() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Packager/UserInterface/IViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.UserInterface 2 | { 3 | public interface IViewModel 4 | { 5 | void Initialize(OutputWindow outputWindow, string projectCode); 6 | bool Processing { get; set; } 7 | string ProcessingMessage { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Packager/UserInterface/LineGenerators/BarcodeSectionLineGenerator.cs: -------------------------------------------------------------------------------- 1 | using Common.UserInterface.LineGenerators; 2 | using Common.UserInterface.ViewModels; 3 | using ICSharpCode.AvalonEdit.Rendering; 4 | 5 | namespace Packager.UserInterface.LineGenerators 6 | { 7 | public class BarcodeElementGenerator:AbstractBarcodeElementGenerator 8 | { 9 | public BarcodeElementGenerator(ILogPanelViewModel viewModel) 10 | { 11 | ViewModel = viewModel; 12 | } 13 | 14 | public override VisualLineElement ConstructElement(int offset) 15 | { 16 | int matchOffset; 17 | var match = GetMatch(offset, out matchOffset); 18 | return match.Success 19 | ? new BarCodeLinkText(match.Value, CurrentContext.VisualLine, ViewModel) 20 | : null; 21 | } 22 | 23 | private ILogPanelViewModel ViewModel { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Packager/Utilities/Bext/BextFields.cs: -------------------------------------------------------------------------------- 1 | using Packager.Attributes; 2 | 3 | namespace Packager.Utilities.Bext 4 | { 5 | public enum BextFields 6 | { 7 | [FFMPEGArgument("description")] Description, 8 | [FFMPEGArgument("originator")] Originator, 9 | [FFMPEGArgument("originator_reference")] OriginatorReference, 10 | [FFMPEGArgument("origination_date")] OriginationDate, 11 | [FFMPEGArgument("origination_time")] OriginationTime, 12 | [FFMPEGArgument("time_reference")] TimeReference, 13 | [FFMPEGArgument("coding_history")] History, 14 | [FFMPEGArgument("umid")] UMID, 15 | IARL, 16 | IART, 17 | ICMS, 18 | ICMT, 19 | ICOP, 20 | ICRD, 21 | IENG, 22 | IGNR, 23 | IKEY, 24 | IMED, 25 | INAM, 26 | IPRD, 27 | ISBJ, 28 | ISFT, 29 | ISRC, 30 | ISRF, 31 | ITCH 32 | } 33 | } -------------------------------------------------------------------------------- /Packager/Utilities/Bext/IBextProcessor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Packager.Models.FileModels; 5 | 6 | namespace Packager.Utilities.Bext 7 | { 8 | public interface IBextProcessor 9 | { 10 | Task ClearMetadataFields(List instances, List fields, CancellationToken cancellationToken); 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Utilities/Email/IEmailSender.cs: -------------------------------------------------------------------------------- 1 | using Packager.Models.EmailMessageModels; 2 | 3 | namespace Packager.Utilities.Email 4 | { 5 | public interface IEmailSender 6 | { 7 | void Send(AbstractEmailMessage message); 8 | } 9 | } -------------------------------------------------------------------------------- /Packager/Utilities/FileSystem/ISuccessFolderCleaner.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Packager.Utilities.FileSystem 4 | { 5 | public interface ISuccessFolderCleaner 6 | { 7 | bool Enabled { get; } 8 | string ConfiguredInterval { get; } 9 | Task DoCleaning(); 10 | } 11 | } -------------------------------------------------------------------------------- /Packager/Utilities/Hashing/IHasher.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Packager.Models.FileModels; 4 | 5 | namespace Packager.Utilities.Hashing 6 | { 7 | public interface IHasher 8 | { 9 | Task Hash(AbstractFile model, CancellationToken cancellationToken); 10 | Task Hash(string path, CancellationToken cancellationToken); 11 | } 12 | } -------------------------------------------------------------------------------- /Packager/Utilities/Images/ILabelImageImporter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Packager.Models.FileModels; 5 | using Packager.Models.PodMetadataModels; 6 | 7 | namespace Packager.Utilities.Images 8 | { 9 | public interface ILabelImageImporter 10 | { 11 | Task> ImportMediaImages(string barcode, CancellationToken cancellationToken); 12 | bool LabelImagesPresent(AbstractPodMetadata metadata); 13 | } 14 | } -------------------------------------------------------------------------------- /Packager/Utilities/ProcessRunners/ArgumentBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Packager.Extensions; 5 | 6 | namespace Packager.Utilities.ProcessRunners 7 | { 8 | public class ArgumentBuilder : List 9 | { 10 | public ArgumentBuilder() 11 | { 12 | } 13 | 14 | public ArgumentBuilder(string arguments) 15 | { 16 | AddRange(arguments.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries)); 17 | } 18 | 19 | public ArgumentBuilder AddArguments(string arguments) 20 | { 21 | AddRange(arguments.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)); 22 | return this; 23 | } 24 | 25 | public ArgumentBuilder AddArguments(IEnumerable arguments) 26 | { 27 | AddRange(arguments.Select(a=>a.ToDefaultIfEmpty().Trim()).Where(a=>a.IsSet())); 28 | return this; 29 | } 30 | 31 | public ArgumentBuilder Clone() 32 | { 33 | return new ArgumentBuilder() 34 | .AddArguments(this); 35 | } 36 | 37 | public override string ToString() 38 | { 39 | return string.Join(" ", this); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Packager/Utilities/ProcessRunners/FileOutputBuffer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Packager.Providers; 4 | 5 | namespace Packager.Utilities.ProcessRunners 6 | { 7 | public class FileOutputBuffer : IOutputBuffer, IDisposable 8 | { 9 | private readonly string _path; 10 | private readonly IFileProvider _fileProvider; 11 | 12 | private readonly StringBuilder _buffer = new StringBuilder(); 13 | 14 | public FileOutputBuffer(string path, IFileProvider fileProvider) 15 | { 16 | _path = path; 17 | _fileProvider = fileProvider; 18 | } 19 | 20 | public void AppendLine(string value) 21 | { 22 | _buffer.AppendLine(value); 23 | if (_buffer.Length < 50000) 24 | { 25 | return; 26 | } 27 | 28 | Flush(); 29 | } 30 | 31 | public string GetContent() 32 | { 33 | return _fileProvider.ReadAllText(_path); 34 | } 35 | 36 | private void Flush() 37 | { 38 | _fileProvider.AppendText(_path, _buffer.ToString()); 39 | _buffer.Clear(); 40 | } 41 | 42 | public void Dispose() 43 | { 44 | Flush(); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /Packager/Utilities/ProcessRunners/IBwfMetaEditRunner.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Packager.Models.FileModels; 5 | using Packager.Models.ResultModels; 6 | using Packager.Utilities.Bext; 7 | 8 | namespace Packager.Utilities.ProcessRunners 9 | { 10 | public interface IBwfMetaEditRunner 11 | { 12 | string BwfMetaEditPath { get; } 13 | Task ClearMetadata(AbstractFile model, IEnumerable fields, CancellationToken cancellationToken); 14 | Task GetVersion(); 15 | } 16 | } -------------------------------------------------------------------------------- /Packager/Utilities/ProcessRunners/IFFMpegRunner.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Packager.Models.FileModels; 5 | 6 | namespace Packager.Utilities.ProcessRunners 7 | { 8 | public interface IFFMPEGRunner 9 | { 10 | string FFMPEGPath { get; set; } 11 | 12 | Task GetFFMPEGVersion(); 13 | 14 | Task Normalize(AbstractFile original, ArgumentBuilder arguments, CancellationToken cancellationToken); 15 | 16 | Task Verify(List originals, CancellationToken cancellationToken); 17 | 18 | Task CreateProdOrMezzDerivative(AbstractFile original, AbstractFile target, ArgumentBuilder arguments, IEnumerable notes, CancellationToken cancellationToken); 19 | 20 | Task CreateAccessDerivative(AbstractFile original, ArgumentBuilder arguments, IEnumerable notes, CancellationToken cancellationToken); 21 | } 22 | } -------------------------------------------------------------------------------- /Packager/Utilities/ProcessRunners/IFFProbeRunner.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Packager.Models.FileModels; 4 | 5 | namespace Packager.Utilities.ProcessRunners 6 | { 7 | public interface IFFProbeRunner 8 | { 9 | string FFProbePath { get; } 10 | string VideoQualityControlArguments { get; } 11 | Task GenerateQualityControlFile(AbstractFile target, CancellationToken cancellationToken); 12 | 13 | Task GetVersion(); 14 | 15 | Task GetMediaInfo(AbstractFile target, CancellationToken cancellation); 16 | } 17 | } -------------------------------------------------------------------------------- /Packager/Utilities/ProcessRunners/IOutputBuffer.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Utilities.ProcessRunners 2 | { 3 | public interface IOutputBuffer 4 | { 5 | void AppendLine(string value); 6 | string GetContent(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Packager/Utilities/ProcessRunners/IProcessRunner.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Packager.Models.ResultModels; 5 | 6 | namespace Packager.Utilities.ProcessRunners 7 | { 8 | public interface IProcessRunner 9 | { 10 | Task Run( 11 | ProcessStartInfo startInfo, 12 | CancellationToken cancellationToken, 13 | IOutputBuffer outputBuffer = null, 14 | IOutputBuffer errorBuffer = null); 15 | } 16 | } -------------------------------------------------------------------------------- /Packager/Utilities/ProcessRunners/StringOutputBuffer.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Packager.Utilities.ProcessRunners 4 | { 5 | public class StringOutputBuffer : IOutputBuffer 6 | { 7 | private readonly StringBuilder _buffer = new StringBuilder(); 8 | 9 | public void AppendLine(string value) 10 | { 11 | _buffer.AppendLine(value); 12 | } 13 | 14 | public string GetContent() 15 | { 16 | return _buffer.ToString(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Packager/Utilities/Reporting/IReportWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Packager.Models.ResultModels; 4 | using Packager.Validators; 5 | 6 | namespace Packager.Utilities.Reporting 7 | { 8 | public interface IReportWriter 9 | { 10 | void WriteResultsReport(Dictionary results, DateTime startTime); 11 | void WriteResultsReport(Exception e); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Packager/Utilities/Xml/IXmlExporter.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Utilities.Xml 2 | { 3 | public interface IXmlExporter 4 | { 5 | void ExportToFile(object o, string path); 6 | T ImportFromFile(string path) where T: class; 7 | } 8 | } -------------------------------------------------------------------------------- /Packager/Utilities/Xml/XmlExporter.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text; 3 | using System.Xml; 4 | using System.Xml.Serialization; 5 | 6 | namespace Packager.Utilities.Xml 7 | { 8 | public class XmlExporter : IXmlExporter 9 | { 10 | public void ExportToFile(object o, string path) 11 | { 12 | var settings = new XmlWriterSettings 13 | { 14 | Indent = true, 15 | Encoding = Encoding.UTF8 16 | }; 17 | var xmlSerializer = new XmlSerializer(o.GetType()); 18 | 19 | using (Stream stream = new FileStream(path, FileMode.Create)) 20 | using (var xmlWriter = XmlWriter.Create(stream, settings)) 21 | { 22 | xmlSerializer.Serialize(xmlWriter, o); 23 | } 24 | } 25 | 26 | public T ImportFromFile(string path) where T:class 27 | { 28 | var xmlSerializer = new XmlSerializer(typeof(T)); 29 | using (var stream = new FileStream(path, FileMode.Open)) 30 | { 31 | return xmlSerializer.Deserialize(stream) as T; 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Packager/Validators/Attributes/HasMembersAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Validators.Attributes 2 | { 3 | public class HasMembersAttribute : PropertyValidationAttribute 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Packager/Validators/Attributes/PropertyValidationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Packager.Validators.Attributes 4 | { 5 | public abstract class PropertyValidationAttribute:Attribute 6 | { 7 | 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Packager/Validators/Attributes/RequiredAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Validators.Attributes 2 | { 3 | public class RequiredAttribute:PropertyValidationAttribute 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Packager/Validators/Attributes/ValidateFileAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Validators.Attributes 2 | { 3 | public class ValidateFileAttribute:PropertyValidationAttribute 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Packager/Validators/Attributes/ValidateFolderAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Validators.Attributes 2 | { 3 | public class ValidateFolderAttribute:PropertyValidationAttribute 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Packager/Validators/Attributes/ValidateObjectAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Packager.Validators.Attributes 4 | { 5 | internal class ValidateObjectAttribute : Attribute 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /Packager/Validators/Attributes/ValidateUriAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Validators.Attributes 2 | { 3 | public class ValidateUriAttribute:PropertyValidationAttribute 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Packager/Validators/DirectoryExistsValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Packager.Extensions; 3 | using Packager.Providers; 4 | using Packager.Validators.Attributes; 5 | 6 | namespace Packager.Validators 7 | { 8 | public class DirectoryExistsValidator : IValidator 9 | { 10 | public DirectoryExistsValidator(IDirectoryProvider directoryProvider) 11 | { 12 | DirectoryProvider = directoryProvider; 13 | } 14 | 15 | private IDirectoryProvider DirectoryProvider { get; set; } 16 | 17 | public ValidationResult Validate(object value, string friendlyName) 18 | { 19 | return DirectoryProvider.DirectoryExists(value.ToDefaultIfEmpty()) 20 | ? ValidationResult.Success 21 | : new ValidationResult("Invalid path specified for {0}: {1}", friendlyName, value.ToDefaultIfEmpty("[not set]")); 22 | } 23 | 24 | public Type Supports => typeof (ValidateFolderAttribute); 25 | } 26 | } -------------------------------------------------------------------------------- /Packager/Validators/FileExistsValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Packager.Extensions; 3 | using Packager.Providers; 4 | using Packager.Validators.Attributes; 5 | 6 | namespace Packager.Validators 7 | { 8 | public class FileExistsValidator : IValidator 9 | { 10 | public FileExistsValidator(IFileProvider fileProvider) 11 | { 12 | FileProvider = fileProvider; 13 | } 14 | 15 | private IFileProvider FileProvider { get; set; } 16 | 17 | public ValidationResult Validate(object value, string friendlyName) 18 | { 19 | return FileProvider.FileExists(value.ToDefaultIfEmpty()) 20 | ? ValidationResult.Success 21 | : new ValidationResult("Invalid path specified for {0}: {1}", friendlyName, value.ToDefaultIfEmpty("[not set]")); 22 | } 23 | 24 | public Type Supports => typeof (ValidateFileAttribute); 25 | } 26 | } -------------------------------------------------------------------------------- /Packager/Validators/IValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Packager.Validators 4 | { 5 | public interface IValidator 6 | { 7 | Type Supports { get; } 8 | ValidationResult Validate(object value, string friendlyName); 9 | } 10 | } -------------------------------------------------------------------------------- /Packager/Validators/IValidatorCollection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Packager.Validators 4 | { 5 | public interface IValidatorCollection : ICollection 6 | { 7 | ValidationResults Validate(object instance); 8 | } 9 | } -------------------------------------------------------------------------------- /Packager/Validators/UriValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Packager.Extensions; 3 | using Packager.Validators.Attributes; 4 | 5 | namespace Packager.Validators 6 | { 7 | public class UriValidator : IValidator 8 | { 9 | public ValidationResult Validate(object value, string friendlyName) 10 | { 11 | return Uri.IsWellFormedUriString(value.ToDefaultIfEmpty(), UriKind.Absolute) 12 | ? ValidationResult.Success 13 | : new ValidationResult("Invalid uri specified for {0}: {1}", friendlyName, value.ToDefaultIfEmpty("[not set]")); 14 | } 15 | 16 | public Type Supports => typeof (ValidateUriAttribute); 17 | } 18 | } -------------------------------------------------------------------------------- /Packager/Validators/ValidationResult.cs: -------------------------------------------------------------------------------- 1 | namespace Packager.Validators 2 | { 3 | public class ValidationResult 4 | { 5 | public ValidationResult(string baseIssue, params object[] args) 6 | : this(false, string.Format(baseIssue, args)) 7 | { 8 | 9 | } 10 | 11 | protected ValidationResult(bool success, string issue) 12 | { 13 | Issue = issue; 14 | Result = success; 15 | } 16 | 17 | public static ValidationResult Success => new ValidationResult(true, ""); 18 | 19 | public bool Result { get; set; } 20 | public string Issue { get; set; } 21 | 22 | } 23 | } -------------------------------------------------------------------------------- /Packager/Validators/ValidationResults.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using Packager.Extensions; 5 | 6 | namespace Packager.Validators 7 | { 8 | public class ValidationResults : List 9 | { 10 | public bool Succeeded 11 | { 12 | get { return TrueForAll(r => r.Result); } 13 | } 14 | 15 | public IEnumerable Issues 16 | { 17 | get { return this 18 | .Where(v => v.Result == false) 19 | .Where(v => v.Issue.IsSet()) 20 | .Select(v => v.Issue) 21 | .ToList(); } 22 | } 23 | 24 | public void Add(string issue, params object[] args) 25 | { 26 | Add(new ValidationResult(issue, args)); 27 | } 28 | 29 | public string GetIssues(string baseMessage) 30 | { 31 | var builder = new StringBuilder(); 32 | builder.AppendLine(baseMessage); 33 | foreach (var issue in Issues) 34 | { 35 | builder.AppendFormat(" {0}/n", issue); 36 | } 37 | 38 | return builder.ToString(); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Packager/Validators/ValueRequiredValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Packager.Extensions; 3 | using Packager.Validators.Attributes; 4 | 5 | namespace Packager.Validators 6 | { 7 | public class ValueRequiredValidator : IValidator 8 | { 9 | public ValidationResult Validate(object value, string friendlyName) 10 | { 11 | return value.ToDefaultIfEmpty().IsSet() 12 | ? ValidationResult.Success 13 | : new ValidationResult("Value not set for {0}", friendlyName); 14 | } 15 | 16 | public Type Supports => typeof (RequiredAttribute); 17 | } 18 | } -------------------------------------------------------------------------------- /Packager/Verifiers/IBwfMetaEditResultsVerifier.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Packager.Observers; 3 | 4 | namespace Packager.Verifiers 5 | { 6 | public interface IBwfMetaEditResultsVerifier 7 | { 8 | bool Verify(string output, IEnumerable targetPaths); 9 | bool Verify(string output, string targetPath); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Packager/copy to input.bat: -------------------------------------------------------------------------------- 1 | FOR %%A IN (%*) DO (copy %%A c:\work\mdpi) 2 | -------------------------------------------------------------------------------- /Packager/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IUMediaHelperApps 2 | This is the repository for the MDPI utilities that are required to run on the desktop of media engineers and QC operators. 3 | 4 | The two core utilities in this repository are the [IU Media Helper Recorder](Recorder/README.md) and the [IU Media Helper Packager](Packager/readme.md): 5 | 6 | * the [IU Media Helper Recorder](Recorder/README.md) provides a graphical user shell for FFMPEG, allowing video engineers better control over the video capture and processing pipeline. 7 | * the [IU Media Helper Packager](Packager/readme.md) is a post-processor that normalizes and embeds metadata into files generated by the audio and video engineers. 8 | 9 | For more details about each of these applications, please see the readme files in their repective repository folders. 10 | -------------------------------------------------------------------------------- /Recorder/BarcodeScanner/Interop/RegistryAccess.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | 3 | // Adapted from https://github.com/aelij/RawInputProcessor 4 | // and http://www.codeproject.com/Articles/17123/Using-Raw-Input-from-C-to-handle-multiple-keyboard 5 | namespace Recorder.BarcodeScanner.Interop 6 | { 7 | internal static class RegistryAccess 8 | { 9 | private const string Prefix = @"\\?\"; 10 | 11 | internal static RegistryKey GetDeviceKey(string device) 12 | { 13 | if (device == null || !device.StartsWith(Prefix)) return null; 14 | var array = device.Substring(Prefix.Length).Split('#'); 15 | return array.Length < 3 16 | ? null 17 | : Registry.LocalMachine.OpenSubKey($@"System\CurrentControlSet\Enum\{array[0]}\{array[1]}\{array[2]}"); 18 | } 19 | 20 | internal static string GetClassType(string classGuid) 21 | { 22 | var registryKey = 23 | Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Class\\" + classGuid); 24 | if (registryKey == null) 25 | { 26 | return string.Empty; 27 | } 28 | return (string) registryKey.GetValue("Class"); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Recorder/BarcodeScanner/KeyPressState.cs: -------------------------------------------------------------------------------- 1 | namespace Recorder.BarcodeScanner 2 | { 3 | // Adapted from https://github.com/aelij/RawInputProcessor 4 | // and http://www.codeproject.com/Articles/17123/Using-Raw-Input-from-C-to-handle-multiple-keyboard 5 | public enum KeyPressState 6 | { 7 | Up, 8 | Down 9 | } 10 | } -------------------------------------------------------------------------------- /Recorder/BarcodeScanner/RawDeviceType.cs: -------------------------------------------------------------------------------- 1 | 2 | // Adapted from https://github.com/aelij/RawInputProcessor 3 | // and http://www.codeproject.com/Articles/17123/Using-Raw-Input-from-C-to-handle-multiple-keyboard 4 | namespace Recorder.BarcodeScanner 5 | { 6 | public enum RawDeviceType 7 | { 8 | Mouse, 9 | Keyboard, 10 | Hid 11 | } 12 | } -------------------------------------------------------------------------------- /Recorder/BarcodeScanner/RawInput.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | // Adapted from https://github.com/aelij/RawInputProcessor 4 | // and http://www.codeproject.com/Articles/17123/Using-Raw-Input-from-C-to-handle-multiple-keyboard 5 | namespace Recorder.BarcodeScanner 6 | { 7 | public abstract class RawInput : IDisposable 8 | { 9 | private readonly RawKeyboard _keyboardDriver; 10 | 11 | public event EventHandler KeyPressed 12 | { 13 | add { KeyboardDriver.KeyPressed += value; } 14 | remove { KeyboardDriver.KeyPressed -= value; } 15 | } 16 | 17 | public int NumberOfKeyboards 18 | { 19 | get { return KeyboardDriver.NumberOfKeyboards; } 20 | } 21 | 22 | protected RawKeyboard KeyboardDriver 23 | { 24 | get { return _keyboardDriver; } 25 | } 26 | 27 | protected RawInput(IntPtr handle, RawInputCaptureMode captureMode) 28 | { 29 | _keyboardDriver = new RawKeyboard(handle, captureMode == RawInputCaptureMode.Foreground); 30 | } 31 | 32 | public abstract void AddMessageFilter(); 33 | public abstract void RemoveMessageFilter(); 34 | 35 | public void Dispose() 36 | { 37 | KeyboardDriver.Dispose(); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Recorder/BarcodeScanner/RawInputCaptureMode.cs: -------------------------------------------------------------------------------- 1 | 2 | // Adapted from https://github.com/aelij/RawInputProcessor 3 | // and http://www.codeproject.com/Articles/17123/Using-Raw-Input-from-C-to-handle-multiple-keyboard 4 | namespace Recorder.BarcodeScanner 5 | { 6 | public enum RawInputCaptureMode 7 | { 8 | Foreground, 9 | ForegroundAndBackground, 10 | } 11 | } -------------------------------------------------------------------------------- /Recorder/BarcodeScanner/RawInputEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | 4 | // Adapted from https://github.com/aelij/RawInputProcessor 5 | // and http://www.codeproject.com/Articles/17123/Using-Raw-Input-from-C-to-handle-multiple-keyboard 6 | namespace Recorder.BarcodeScanner 7 | { 8 | public sealed class RawInputEventArgs : EventArgs 9 | { 10 | public RawKeyboardDevice Device { get; private set; } 11 | public KeyPressState KeyPressState { get; private set; } 12 | public uint Message { get; private set; } 13 | public Key Key { get; private set; } 14 | public int VirtualKey { get; private set; } 15 | public bool Handled { get; set; } 16 | 17 | internal RawInputEventArgs(RawKeyboardDevice device, KeyPressState keyPressState, uint message, Key key, 18 | int virtualKey) 19 | { 20 | Device = device; 21 | KeyPressState = keyPressState; 22 | Message = message; 23 | Key = key; 24 | VirtualKey = virtualKey; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Recorder/BarcodeScanner/RawKeyboardDevice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | // Adapted from https://github.com/aelij/RawInputProcessor 4 | // and http://www.codeproject.com/Articles/17123/Using-Raw-Input-from-C-to-handle-multiple-keyboard 5 | namespace Recorder.BarcodeScanner 6 | { 7 | public sealed class RawKeyboardDevice 8 | { 9 | public string Name { get; private set; } 10 | public RawDeviceType Type { get; private set; } 11 | public IntPtr Handle { get; private set; } 12 | public string Description { get; private set; } 13 | 14 | internal RawKeyboardDevice(string name, RawDeviceType type, IntPtr handle, string description) 15 | { 16 | Handle = handle; 17 | Type = type; 18 | Name = name; 19 | Description = description; 20 | } 21 | 22 | public override string ToString() 23 | { 24 | return string.Format("Device\n Name: {0}\n Type: {1}\n Handle: {2}\n Name: {3}\n", 25 | Name, 26 | Type, 27 | Handle.ToInt64().ToString("X"), 28 | Description); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Recorder/Controls/ActionButton.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Recorder.Controls 17 | { 18 | /// 19 | /// Interaction logic for ActionButton.xaml 20 | /// 21 | public partial class ActionButton : UserControl 22 | { 23 | public ActionButton() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Recorder/Controls/ActionPanel.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Recorder/Controls/ActionPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Recorder.Controls 17 | { 18 | /// 19 | /// Interaction logic for ActionPanel.xaml 20 | /// 21 | public partial class ActionPanel : UserControl 22 | { 23 | public ActionPanel() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Recorder/Controls/AudioMeter.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Recorder/Controls/AudioMeter.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Recorder.Controls 17 | { 18 | /// 19 | /// Interaction logic for AudioMeter.xaml 20 | /// 21 | public partial class AudioMeter : UserControl 22 | { 23 | public AudioMeter() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Recorder/Controls/BarcodePanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Recorder.Controls 17 | { 18 | /// 19 | /// Interaction logic for BarcodePanel.xaml 20 | /// 21 | public partial class BarcodePanel : UserControl 22 | { 23 | public BarcodePanel() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Recorder/Controls/FinishPanel.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 16 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Recorder/Controls/FinishPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Recorder.Controls 17 | { 18 | /// 19 | /// Interaction logic for FinishPanel.xaml 20 | /// 21 | public partial class FinishPanel : UserControl 22 | { 23 | public FinishPanel() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Recorder/Controls/FrameStats.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Recorder.Controls 17 | { 18 | /// 19 | /// Interaction logic for FrameStats.xaml 20 | /// 21 | public partial class FrameStats : UserControl 22 | { 23 | public FrameStats() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Recorder/Controls/NavigationPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Recorder.Controls 17 | { 18 | /// 19 | /// Interaction logic for NavigationPanel.xaml 20 | /// 21 | public partial class NavigationPanel : UserControl 22 | { 23 | public NavigationPanel() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Recorder/Controls/OutputPanel.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Recorder/Controls/OutputPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Recorder.Controls 17 | { 18 | /// 19 | /// Interaction logic for OutputPanel.xaml 20 | /// 21 | public partial class OutputPanel : UserControl 22 | { 23 | public OutputPanel() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Recorder/Controls/RecordPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Recorder.Controls 17 | { 18 | /// 19 | /// Interaction logic for RecordPanel.xaml 20 | /// 21 | public partial class RecordPanel : UserControl 22 | { 23 | public RecordPanel() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Recorder/Controls/YesNoQuestionPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace Recorder.Controls 17 | { 18 | /// 19 | /// Interaction logic for YesNoQuestionPanel.xaml 20 | /// 21 | public partial class YesNoQuestionPanel : UserControl 22 | { 23 | public YesNoQuestionPanel() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Recorder/Converters/BooleanToCollapsedConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace Recorder.Converters 7 | { 8 | internal class BooleanToCollapsedConverter : IValueConverter 9 | { 10 | #region IValueConverter Members 11 | 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | //reverse conversion (false=>Visible, true=>collapsed) on any given parameter 15 | var input = (null == parameter) ? (bool) value : !((bool) value); 16 | return (input) ? Visibility.Visible : Visibility.Collapsed; 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | 24 | #endregion 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Recorder/Converters/EmptyToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace Recorder.Converters 7 | { 8 | public class NullOrEmptyToVisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | return string.IsNullOrWhiteSpace(value?.ToString()) ? Visibility.Collapsed : Visibility.Visible; 13 | } 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | throw new NotImplementedException(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Recorder/Converters/TimespanToStringConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace Recorder.Converters 10 | { 11 | public class TimespanToStringConverter:IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | if (!(value is TimeSpan)) 16 | { 17 | return string.Empty; 18 | } 19 | 20 | var timespan = (TimeSpan) value; 21 | return $@"{timespan:hh\:mm\:ss\.ff}"; 22 | } 23 | 24 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 25 | { 26 | throw new NotImplementedException(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Recorder/Dialogs/UserControls.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Media; 4 | using Recorder.ViewModels; 5 | 6 | namespace Recorder.Dialogs 7 | { 8 | /// 9 | /// Interaction logic for MainWindow.xaml 10 | /// 11 | public partial class UserControls : Window 12 | { 13 | public UserControls() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | protected override void OnSourceInitialized(EventArgs e) 19 | { 20 | base.OnSourceInitialized(e); 21 | 22 | var handleInitialized = DataContext as IWindowHandleInitialized; 23 | handleInitialized?.WindowHandleInitialized(this); 24 | 25 | } 26 | 27 | private void OnWindowClosing(object sender, System.ComponentModel.CancelEventArgs e) 28 | { 29 | var onClosing = DataContext as IClosing; 30 | if (onClosing == null) 31 | { 32 | return; 33 | } 34 | 35 | e.Cancel = onClosing.CancelWindowClose(); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Recorder/Enums/FileUses.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Recorder.Enums 8 | { 9 | public class FileUses 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Recorder/Exceptions/AbstractHandledException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Recorder.Exceptions 4 | { 5 | public class AbstractHandledException : Exception 6 | { 7 | public AbstractHandledException() 8 | { 9 | } 10 | 11 | public AbstractHandledException(string message) : base(message) 12 | { 13 | } 14 | 15 | public AbstractHandledException(string message, Exception innerException) : base(message, innerException) 16 | { 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Recorder/Exceptions/CombiningException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Recorder.Exceptions 4 | { 5 | public class CombiningException : AbstractHandledException 6 | { 7 | public CombiningException() 8 | { 9 | } 10 | 11 | public CombiningException(string message) : base(message) 12 | { 13 | } 14 | 15 | public CombiningException(string message, Exception innerException) : base(message, innerException) 16 | { 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Recorder/Exceptions/ConfigurationException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Recorder.Exceptions 4 | { 5 | public class ConfigurationException : AbstractHandledException 6 | { 7 | public ConfigurationException() 8 | { 9 | } 10 | 11 | public ConfigurationException(string message) : base(message) 12 | { 13 | } 14 | 15 | public ConfigurationException(string message, Exception innerException) : base(message, innerException) 16 | { 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Recorder/Exceptions/RecordingException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Recorder.Exceptions 4 | { 5 | public class RecordingException : AbstractHandledException 6 | { 7 | public RecordingException() 8 | { 9 | } 10 | 11 | public RecordingException(string message) : base(message) 12 | { 13 | } 14 | 15 | public RecordingException(string message, Exception innerException) : base(message, innerException) 16 | { 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Recorder/Extensions/UserInterfaceExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Media; 3 | 4 | namespace Recorder.Extensions 5 | { 6 | public static class DependencyObjectExtensions 7 | { 8 | public static T FindDescendant(this DependencyObject target) where T : DependencyObject 9 | { 10 | if (target == null) return default(T); 11 | var numberChildren = VisualTreeHelper.GetChildrenCount(target); 12 | if (numberChildren == 0) return default(T); 13 | 14 | for (var i = 0; i < numberChildren; i++) 15 | { 16 | var child = VisualTreeHelper.GetChild(target, i); 17 | var instance = child as T; 18 | if (instance != null) 19 | { 20 | return instance; 21 | } 22 | } 23 | 24 | for (var i = 0; i < numberChildren; i++) 25 | { 26 | var child = VisualTreeHelper.GetChild(target, i); 27 | var potentialMatch = FindDescendant(child); 28 | if (potentialMatch.Equals(default(T)) == false) 29 | { 30 | return potentialMatch; 31 | } 32 | } 33 | 34 | return default(T); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Recorder/Handlers/AbstractProcessOutputHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace Recorder.Handlers 4 | { 5 | public abstract class AbstractProcessOutputHandler 6 | { 7 | public abstract void OnDataReceived(object sender, DataReceivedEventArgs args); 8 | 9 | public abstract void Reset(); 10 | } 11 | } -------------------------------------------------------------------------------- /Recorder/Handlers/CurrentFrameHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Text.RegularExpressions; 3 | using Recorder.ViewModels; 4 | 5 | namespace Recorder.Handlers 6 | { 7 | public class CurrentFrameHandler : AbstractProcessOutputHandler 8 | { 9 | private readonly Regex _currentFrameExpression = new Regex(@"frame=(.*\d+) fps"); 10 | private readonly FrameStatsViewModel _viewModel; 11 | 12 | public CurrentFrameHandler(FrameStatsViewModel viewModel) 13 | { 14 | _viewModel = viewModel; 15 | } 16 | 17 | public override void OnDataReceived(object sender, DataReceivedEventArgs args) 18 | { 19 | if (string.IsNullOrWhiteSpace(args.Data)) 20 | { 21 | return; 22 | } 23 | 24 | var match = _currentFrameExpression.Match(args.Data); 25 | if (match.Success == false) 26 | { 27 | return; 28 | } 29 | 30 | if (match.Groups.Count < 2) 31 | { 32 | return; 33 | } 34 | 35 | _viewModel.CurrentFrame = match.Groups[1].Value.Trim(); 36 | } 37 | 38 | public override void Reset() 39 | { 40 | _viewModel.CurrentFrame = "0"; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Recorder/Handlers/DroppedFramesHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Text.RegularExpressions; 3 | using Recorder.ViewModels; 4 | 5 | namespace Recorder.Handlers 6 | { 7 | public class DroppedFramesHandler:AbstractProcessOutputHandler 8 | 9 | { 10 | private readonly FrameStatsViewModel _viewModel; 11 | private readonly Regex _currentFrameExpression = new Regex(@"drop=(\d+)"); 12 | 13 | public DroppedFramesHandler(FrameStatsViewModel viewModel) 14 | { 15 | _viewModel = viewModel; 16 | } 17 | 18 | public override void OnDataReceived(object sender, DataReceivedEventArgs args) 19 | { 20 | if (string.IsNullOrWhiteSpace(args.Data)) 21 | { 22 | return; 23 | } 24 | 25 | var match = _currentFrameExpression.Match(args.Data); 26 | if (match.Success == false) 27 | { 28 | return; 29 | } 30 | 31 | if (match.Groups.Count < 2) 32 | { 33 | return; 34 | } 35 | 36 | _viewModel.DroppedFrames = match.Groups[1].Value.Trim(); 37 | } 38 | 39 | public override void Reset() 40 | { 41 | _viewModel.DroppedFrames = "0"; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Recorder/Handlers/DuplicateFrameHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Text.RegularExpressions; 3 | using Recorder.ViewModels; 4 | 5 | namespace Recorder.Handlers 6 | { 7 | public class DuplicateFrameHandler:AbstractProcessOutputHandler 8 | { 9 | private readonly FrameStatsViewModel _viewModel; 10 | private readonly Regex _currentFrameExpression = new Regex(@"dup=(\d+)"); 11 | 12 | public DuplicateFrameHandler(FrameStatsViewModel viewModel) 13 | { 14 | _viewModel = viewModel; 15 | } 16 | 17 | public override void OnDataReceived(object sender, DataReceivedEventArgs args) 18 | { 19 | if (string.IsNullOrWhiteSpace(args.Data)) 20 | { 21 | return; 22 | } 23 | 24 | var match = _currentFrameExpression.Match(args.Data); 25 | if (match.Success == false) 26 | { 27 | return; 28 | } 29 | 30 | if (match.Groups.Count < 2) 31 | { 32 | return; 33 | } 34 | 35 | _viewModel.DuplicateFrames = match.Groups[1].Value.Trim(); 36 | } 37 | 38 | public override void Reset() 39 | { 40 | _viewModel.DuplicateFrames = "0"; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Recorder/Handlers/OutputLogHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Text; 3 | using Recorder.ViewModels; 4 | 5 | namespace Recorder.Handlers 6 | { 7 | public class OutputLogHandler: AbstractProcessOutputHandler 8 | { 9 | public OutputLogHandler(OutputWindowViewModel viewModel) 10 | { 11 | ViewModel = viewModel; 12 | } 13 | 14 | private OutputWindowViewModel ViewModel { get; } 15 | 16 | public override void OnDataReceived(object sender, DataReceivedEventArgs args) 17 | { 18 | if (string.IsNullOrWhiteSpace(args.Data)) 19 | { 20 | return; 21 | } 22 | 23 | AppendLine(args.Data); 24 | } 25 | 26 | private void AppendLine(string text) 27 | { 28 | var builder = new StringBuilder(ViewModel.Text); 29 | builder.AppendLine(text); 30 | ViewModel.Text = builder.ToString(); 31 | } 32 | 33 | public override void Reset() 34 | { 35 | if (ViewModel.Clear == false) 36 | { 37 | AppendLine(""); 38 | AppendLine("------------------------------------------------------------------------"); 39 | return; 40 | } 41 | 42 | ViewModel.Text = string.Empty; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Recorder/Handlers/TimestampReceivedHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Text.RegularExpressions; 4 | using Recorder.Utilities; 5 | 6 | namespace Recorder.Handlers 7 | { 8 | public class TimestampReceivedHandler:AbstractProcessOutputHandler 9 | { 10 | private RecordingEngine Recorder { get; } 11 | private readonly Regex _timestampExpression = new Regex(@"time=(\d{2}:\d{2}:\d{2}\.\d{2})"); 12 | 13 | public TimestampReceivedHandler(RecordingEngine recorder) 14 | { 15 | Recorder = recorder; 16 | } 17 | 18 | public override void Reset() 19 | { 20 | Recorder.OnTimestampUpdated(new TimeSpan()); 21 | } 22 | 23 | public override void OnDataReceived(object sender, DataReceivedEventArgs args) 24 | { 25 | if (string.IsNullOrWhiteSpace(args.Data)) 26 | { 27 | return; 28 | } 29 | 30 | var match = _timestampExpression.Match(args.Data); 31 | if (match.Success == false) 32 | { 33 | return; 34 | } 35 | 36 | TimeSpan timeSpan; 37 | if (!TimeSpan.TryParse(match.Groups[1].ToString(), out timeSpan)) 38 | { 39 | return; 40 | } 41 | 42 | Recorder.OnTimestampUpdated(timeSpan); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Recorder/Models/AudioChannelsAndStreams.cs: -------------------------------------------------------------------------------- 1 | namespace Recorder.Models 2 | { 3 | public class AudioChannelsAndStreams 4 | { 5 | public string DisplayName { get; set; } 6 | public int Channels { get; set; } 7 | public int Streams { get; set; } 8 | public int Id { get; set; } 9 | 10 | public bool Is4Channels => Channels == 4; 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Recorder/NOTICE: -------------------------------------------------------------------------------- 1 | INDIANA UNIVERSITY MEDIA HELPER APPLICATIONS: RECORDER 2 | 3 | Provides a graphical user interface to help engineers use 4 | FFMPEG to digitize content from video media sources. 5 | 6 | Copyright (C) 2014-2017, The Trustees of Indiana University. 7 | -------------------------------------------------------------------------------- /Recorder/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Recorder.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Recorder/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Recorder/ReleaseNotes.txt: -------------------------------------------------------------------------------- 1 | 1.0.0.0 10/15/2015 initial release 2 | 1.1.0.0 10/15/2015 fixed issue displaying timestamps 3 | 1.2.0.0 10/22/2015 combiner should now write logs 4 | 1.3.0.0 11/03/2015 added audio meter 5 | added dropped, duplicate frames display 6 | 1.4.0.0 11/10/2015 changing how audio meter is configured 7 | adding configuration logging at startup 8 | removing unused dependencies 9 | 1.8.0.0 05/26/2016 Should now record 4 channels properly 10 | 1.9.0.0 05/27/2016 Should only keep first four channels of 8 channel input 11 | 2.0.0.0 06/20/2016 improvements to 4 channel recording 12 | 2.1.0.0 03/08/2017 add support for 2 channel, 2 mono streams recording 13 | 2.2.0.0 11/05/2018 add support for 1 channel mono stream recording -------------------------------------------------------------------------------- /Recorder/Scripts/Internal/betacam_fix_internal.bat: -------------------------------------------------------------------------------- 1 | %1 -y -loglevel error -i %2 -f lavfi -i anullsrc=r=48000:cl=mono -f lavfi -i anullsrc=r=48000:cl=mono -codec:a pcm_s24le -codec:v copy -filter_complex "[0:a]pan=mono|c0=c0[a0];[0:a]pan=mono|c0=c1[a1]" -map 0:v -map "[a0]" -map "[a1]" -map 1:0 -map 2:0 -shortest %3 2 | 3 | -------------------------------------------------------------------------------- /Recorder/Scripts/Internal/umatic_fix_internal.bat: -------------------------------------------------------------------------------- 1 | %1 -y -loglevel error -i %2 -y -codec:a pcm_s24le -codec:v copy -filter_complex "[0:a]pan=mono|c0=c0[a0];[0:a]pan=mono|c0=c1[a1]" -map 0:v -map "[a0]" -map "[a1]" %3 -------------------------------------------------------------------------------- /Recorder/Scripts/extract audio channels.bat: -------------------------------------------------------------------------------- 1 | c:\dependencies\ffmpeg\ffmpeg -i %1 -map 0:0 %~n1_0.wav 2 | c:\dependencies\ffmpeg\ffmpeg -i %1 -map 0:1 %~n1_1.wav 3 | c:\dependencies\ffmpeg\ffmpeg -i %1 -map 0:2 %~n1_2.wav 4 | c:\dependencies\ffmpeg\ffmpeg -i %1 -map 0:3 %~n1_3.wav 5 | 6 | pause -------------------------------------------------------------------------------- /Recorder/Scripts/extract stereo to mono.bat: -------------------------------------------------------------------------------- 1 | c:\dependencies\ffmpeg\ffmpeg.exe -i %1 -y -map_channel 0.1.0 %~n1_left.wav -map_channel 0.1.1 %~n1_right.wav 2 | pause -------------------------------------------------------------------------------- /Recorder/Scripts/umatic_fix.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | echo. 4 | echo *********************************************************** 5 | echo * * 6 | echo * Umatic Fix * 7 | echo * * 8 | echo * Converts a video file (.mkv) with one stereo audio * 9 | echo * stream to one with 2 mono audio streams containing * 10 | echo * the content of the original's stereo channels. * 11 | echo * * 12 | echo *********************************************************** 13 | echo. 14 | 15 | set baseScriptPath=%~dp0 16 | set commonCodePath="%baseScriptPath%\Shared\common.bat" 17 | set internalFixCode="%baseScriptPath%\Internal\umatic_fix_internal.bat" 18 | set outputPath="%~p1%~n1_umatic_fix\%~n1%~x1" 19 | 20 | call %commonCodePath% %1 %internalFixCode% %outputPath% 21 | 22 | :Err 23 | echo. 24 | 25 | pause 26 | 27 | exit /B -------------------------------------------------------------------------------- /Recorder/Utilities/ICanLogConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Recorder.ViewModels; 2 | 3 | namespace Recorder.Utilities 4 | { 5 | public interface ICanLogConfiguration 6 | { 7 | void LogConfiguration(OutputWindowViewModel outputModel); 8 | } 9 | } -------------------------------------------------------------------------------- /Recorder/ViewModels/AskExitViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using System.Windows; 4 | using System.Windows.Input; 5 | using Common.UserInterface.Commands; 6 | using JetBrains.Annotations; 7 | 8 | namespace Recorder.ViewModels 9 | { 10 | public class AskExitViewModel : AbstractNotifyModel, IClosing 11 | { 12 | 13 | private bool _exitNow; 14 | 15 | public AskExitViewModel() 16 | { 17 | YesText = "Yes"; 18 | NoText = "No"; 19 | Question = "Stop recording and exit?"; 20 | YesCommand = new RelayCommand( 21 | param => DoExit()); 22 | NoCommand = new RelayCommand( 23 | param => ShowPanel = false); 24 | 25 | } 26 | 27 | 28 | public bool CancelWindowClose() 29 | { 30 | FlashPanel = false; 31 | 32 | if (_exitNow) 33 | { 34 | return false; 35 | } 36 | 37 | ShowPanel = true; 38 | FlashPanel = true; 39 | 40 | return true; 41 | } 42 | 43 | private void DoExit() 44 | { 45 | _exitNow = true; 46 | Application.Current.MainWindow.Close(); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Recorder/ViewModels/IClosing.cs: -------------------------------------------------------------------------------- 1 | namespace Recorder.ViewModels 2 | { 3 | public interface IClosing 4 | { 5 | bool CancelWindowClose(); 6 | } 7 | } -------------------------------------------------------------------------------- /Recorder/ViewModels/IWindowHandleInitialized.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Media; 2 | 3 | namespace Recorder.ViewModels 4 | { 5 | public interface IWindowHandleInitialized 6 | { 7 | void WindowHandleInitialized(Visual client); 8 | } 9 | } -------------------------------------------------------------------------------- /Recorder/ViewModels/IssueNotifyModel.cs: -------------------------------------------------------------------------------- 1 | using Common.UserInterface.Commands; 2 | 3 | namespace Recorder.ViewModels 4 | { 5 | public class IssueNotifyModel : AbstractNotifyModel 6 | { 7 | public IssueNotifyModel() 8 | { 9 | YesText = "Ok"; 10 | YesCommand = new RelayCommand(param => 11 | { 12 | ShowPanel = false; 13 | Question = string.Empty; 14 | }); 15 | } 16 | 17 | 18 | public void Notify(string message) 19 | { 20 | FlashPanel = false; 21 | Question = message; 22 | ShowPanel = true; 23 | FlashPanel = true; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Recorder/ViewModels/VolumeMeterViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Configuration; 3 | using System.Runtime.CompilerServices; 4 | using System.Windows; 5 | using JetBrains.Annotations; 6 | 7 | namespace Recorder.ViewModels 8 | { 9 | public class VolumeMeterViewModel : INotifyPropertyChanged 10 | { 11 | private float _inputLevel; 12 | private Visibility _volumeMeterVisibility; 13 | 14 | public VolumeMeterViewModel() 15 | { 16 | VolumeMeterVisibility = Visibility.Collapsed; 17 | } 18 | 19 | public Visibility VolumeMeterVisibility 20 | { 21 | get { return _volumeMeterVisibility; } 22 | set { _volumeMeterVisibility = value; OnPropertyChanged(); } 23 | } 24 | 25 | public float InputLevel 26 | { 27 | get { return _inputLevel; } 28 | set 29 | { 30 | _inputLevel = value; 31 | OnPropertyChanged(); 32 | } 33 | } 34 | 35 | public event PropertyChangedEventHandler PropertyChanged; 36 | 37 | [NotifyPropertyChangedInvocator] 38 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 39 | { 40 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Recorder/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Reporter/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | c:\work\logs 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Reporter/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Reporter/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Configuration; 3 | using System.Windows; 4 | using Common.UserInterface.ViewModels; 5 | using Reporter.Models; 6 | using Reporter.Utilities; 7 | 8 | namespace Reporter 9 | { 10 | /// 11 | /// Interaction logic for App.xaml 12 | /// 13 | public partial class App : Application 14 | { 15 | private void InitializeApplication(object sender, StartupEventArgs e) 16 | { 17 | var logPanelViewModel = new LogPanelViewModel(); 18 | var settings = new ProgramSettings(ConfigurationManager.AppSettings); 19 | var reportReaders = new List() 20 | { 21 | new FileReportRenderer(settings, logPanelViewModel), 22 | new TaskSchedulerRenderer(logPanelViewModel) 23 | }; 24 | 25 | 26 | var viewModel = new ViewModel(settings, reportReaders, logPanelViewModel); 27 | var reportWindow = new ReporterWindow 28 | { 29 | DataContext = viewModel 30 | }; 31 | 32 | reportWindow.Show(); 33 | } 34 | 35 | private void ApplicationExitHandler(object sender, ExitEventArgs e) 36 | { 37 | 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Reporter/Converters/DisabledIfEmptyConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Windows.Data; 6 | using Reporter.Models; 7 | 8 | namespace Reporter.Converters 9 | { 10 | class DisabledIfEmptyConverter:IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | var list = value as BindingList; 15 | if (list == null) 16 | { 17 | return false; 18 | } 19 | 20 | return list.Any(); 21 | } 22 | 23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Reporter/LineGenerators/OpenObjectLogfileGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Dynamic; 2 | using Common.UserInterface.LineGenerators; 3 | using ICSharpCode.AvalonEdit.Rendering; 4 | using Reporter.Models; 5 | 6 | namespace Reporter.LineGenerators 7 | { 8 | public class OpenObjectLogfileGenerator:AbstractBarcodeElementGenerator 9 | { 10 | private ProgramSettings ProgramSettings { get; } 11 | 12 | public OpenObjectLogfileGenerator(ProgramSettings programSettings) 13 | { 14 | ProgramSettings = programSettings; 15 | } 16 | 17 | public override VisualLineElement ConstructElement(int offset) 18 | { 19 | int matchOffset; 20 | var match = GetMatch(offset, out matchOffset); 21 | return match.Success 22 | ? new OpenObjectLogFileLinkText(ProgramSettings.ReportFolder, match.Value, CurrentContext.VisualLine) 23 | : null; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Reporter/Models/AbstractReportEntry.cs: -------------------------------------------------------------------------------- 1 | namespace Reporter.Models 2 | { 3 | public abstract class AbstractReportEntry 4 | { 5 | public string DisplayName { get; set; } 6 | public long Timestamp { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /Reporter/Models/FileReportEntry.cs: -------------------------------------------------------------------------------- 1 | namespace Reporter.Models 2 | { 3 | public class FileReportEntry:AbstractReportEntry 4 | { 5 | public string Filename { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Reporter/Models/ProgramSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Specialized; 2 | using Common.Extensions; 3 | 4 | namespace Reporter.Models 5 | { 6 | public class ProgramSettings 7 | { 8 | public ProgramSettings(NameValueCollection settings) 9 | { 10 | ProjectCode = GetStringValue(settings, "ProjectCode"); 11 | } 12 | 13 | public string ProjectCode { get; } 14 | 15 | public string ReportFolder { 16 | get { return Properties.Settings.Default.ReportFolder; } 17 | set 18 | { 19 | Properties.Settings.Default.ReportFolder = value; 20 | Properties.Settings.Default.Save(); 21 | } 22 | } 23 | 24 | // todo: move to common 25 | private static string GetStringValue(NameValueCollection settings, string name) 26 | { 27 | return settings[name].ToDefaultIfEmpty().ToUpperInvariant(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Reporter/Models/TaskSchedulerEntry.cs: -------------------------------------------------------------------------------- 1 | namespace Reporter.Models 2 | { 3 | public class TaskSchedulerEntry:AbstractReportEntry 4 | { 5 | public string Contents { get; set; } 6 | public string TaskName { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Reporter/NOTICE: -------------------------------------------------------------------------------- 1 | INDIANA UNIVERSITY MEDIA HELPER APPLICATIONS: REPORTER 2 | 3 | Provides quick summaries of Packager logs. 4 | 5 | Copyright (C) 2014-2017, The Trustees of Indiana University. 6 | -------------------------------------------------------------------------------- /Reporter/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | c:\work\logs 7 | 8 | 9 | -------------------------------------------------------------------------------- /Reporter/ReleaseNotes.txt: -------------------------------------------------------------------------------- 1 | 1.0.0.0 2/13/2017 initial release 2 | 1.1.0.0 3/20/2017 add functionality to display task-scheduler 3 | logs in instances where scheduled task did 4 | not run; fix issue opening logs in notepad.exe 5 | 1.2.0.0 1/17/2018 add support for deferred reports 6 | -------------------------------------------------------------------------------- /Reporter/ReporterWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace Reporter 4 | { 5 | /// 6 | /// Interaction logic for MainWindow.xaml 7 | /// 8 | public partial class ReporterWindow : Window 9 | { 10 | public ReporterWindow() 11 | { 12 | InitializeComponent(); 13 | } 14 | 15 | private async void OnLoadedHandler(object sender, RoutedEventArgs e) 16 | { 17 | var viewModel = DataContext as ViewModel; 18 | if (viewModel == null) 19 | { 20 | return; 21 | } 22 | 23 | await viewModel.Initialize(ReportText); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Reporter/Utilities/IReportRenderer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Common.Models; 4 | using Common.UserInterface.ViewModels; 5 | using Reporter.Models; 6 | 7 | namespace Reporter.Utilities 8 | { 9 | public interface IReportRenderer 10 | { 11 | Task> GetReports(); 12 | Task Render(AbstractReportEntry reportEntry); 13 | bool CanRender(AbstractReportEntry report); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Reporter/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Scheduler/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Scheduler/NOTICE: -------------------------------------------------------------------------------- 1 | INDIANA UNIVERSITY MEDIA HELPER APPLICATIONS: SCHEDULER 2 | 3 | Command-line utility to configure Windows scheduled tasks. 4 | 5 | Copyright (C) 2014-2017, The Trustees of Indiana University. 6 | -------------------------------------------------------------------------------- /Scheduler/OpenTaskScheduler.bat: -------------------------------------------------------------------------------- 1 | start taskschd.msc -------------------------------------------------------------------------------- /Scheduler/Schedule.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: use schedule.exe 3 | scheduler.exe -days=monday,tuesday,wednesday,thursday,friday -start=19:00 4 | 5 | :: To use windows command, comment out following line 6 | :: schtasks /create /tn "Media Packager" /tr "%CD%\Packager.exe" /sc weekly /d MON,WED,THU,FRI /st 19:00 -------------------------------------------------------------------------------- /Scheduler/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /SetLogonAsBatchRight/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /SetLogonAsBatchRight/NOTICE: -------------------------------------------------------------------------------- 1 | INDIANA UNIVERSITY MEDIA HELPER APPLICATIONS: SET LOGON AS BATCH RIGHT 2 | 3 | Command-line utility to grant user logon-as-batch privileges. 4 | 5 | Copyright (C) 2014-2017, The Trustees of Indiana University. 6 | -------------------------------------------------------------------------------- /WaveInfo/AbstractChunk.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text; 3 | using WaveInfo.Extensions; 4 | 5 | namespace WaveInfo 6 | { 7 | public abstract class AbstractChunk 8 | { 9 | public string Id { get; set; } 10 | public uint Size { get; set; } 11 | public uint ReportedSize { get; set; } 12 | public long Offset { get; set; } 13 | 14 | public virtual void ReadChunk(BinaryReader reader) 15 | { 16 | SetOffset(reader); 17 | SetSize(reader); 18 | } 19 | 20 | private void SetSize(BinaryReader reader) 21 | { 22 | ReportedSize = reader.ReadUInt32(); 23 | Size = ReportedSize.Normalize(); 24 | } 25 | 26 | private void SetOffset(BinaryReader reader) 27 | { 28 | Offset = reader.BaseStream.Position - 4; 29 | } 30 | 31 | 32 | public virtual string GetReport() 33 | { 34 | var builder = new StringBuilder(); 35 | 36 | builder.AppendLine(); 37 | builder.AppendLine($"{Id} chunk"); 38 | builder.AppendLine(new string('-', 75)); 39 | builder.AppendLine(this.ToColumns("Size")); 40 | builder.AppendLine(this.ToColumns("ReportedSize")); 41 | builder.AppendLine(this.ToColumns("Offset")); 42 | 43 | return builder.ToString(); 44 | } 45 | 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /WaveInfo/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WaveInfo/DataChunk.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace WaveInfo 4 | { 5 | public class DataChunk:AbstractChunk 6 | { 7 | public string Md5Hash { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /WaveInfo/Ds64Chunk.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace WaveInfo 4 | { 5 | public class Ds64Chunk : AbstractChunk 6 | { 7 | public ulong RiffSize { get; set; } 8 | public ulong DataSize { get; set; } 9 | public ulong SampleCount { get; set; } 10 | public uint TableLength { get; set; } 11 | 12 | 13 | public override void ReadChunk(BinaryReader reader) 14 | { 15 | base.ReadChunk(reader); 16 | 17 | RiffSize = reader.ReadUInt64(); 18 | DataSize = reader.ReadUInt64(); 19 | SampleCount = reader.ReadUInt64(); 20 | TableLength = reader.ReadUInt32(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /WaveInfo/Extensions/Uint64Extensions.cs: -------------------------------------------------------------------------------- 1 | namespace WaveInfo.Extensions 2 | { 3 | public static class SizeExtensions 4 | { 5 | public static uint Normalize(this uint value) 6 | { 7 | if (value%2 == 0) 8 | { 9 | return value; 10 | } 11 | 12 | return value + 1; 13 | } 14 | 15 | 16 | public static ulong Normalize(this ulong value) 17 | { 18 | if (value%2 == 0) 19 | { 20 | return value; 21 | } 22 | 23 | return value + 1; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /WaveInfo/FactChunk.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace WaveInfo 4 | { 5 | public class FactChunk:AbstractChunk 6 | { 7 | public uint Samples; //Number of audio frames; 8 | public override void ReadChunk(BinaryReader reader) 9 | { 10 | base.ReadChunk(reader); 11 | 12 | Samples = reader.ReadUInt32(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /WaveInfo/FormatChunk.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace WaveInfo 4 | { 5 | public class FormatChunk : AbstractChunk 6 | { 7 | public uint AvgBytesPerSec; 8 | public ushort BitsPerSample; 9 | public ushort BlockAlign; 10 | public ushort Channels; 11 | public ushort FormatTag; 12 | public uint SamplesPerSec; 13 | public ushort ExtensionSize; 14 | public ushort ValidBitsPerSample; 15 | public uint ChannelMask; 16 | public byte[] SubFormat; 17 | public override void ReadChunk(BinaryReader reader) 18 | { 19 | base.ReadChunk(reader); 20 | 21 | FormatTag = reader.ReadUInt16(); 22 | Channels = reader.ReadUInt16(); 23 | SamplesPerSec = reader.ReadUInt32(); 24 | AvgBytesPerSec = reader.ReadUInt32(); 25 | BlockAlign = reader.ReadUInt16(); 26 | BitsPerSample = reader.ReadUInt16(); 27 | 28 | if (Size == 16) 29 | { 30 | return; 31 | } 32 | 33 | ExtensionSize = reader.ReadUInt16(); 34 | if (ExtensionSize == 0) 35 | { 36 | return; 37 | } 38 | 39 | ValidBitsPerSample = reader.ReadUInt16(); 40 | ChannelMask = reader.ReadUInt32(); 41 | SubFormat = reader.ReadBytes(16); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /WaveInfo/InfoChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using WaveInfo.Extensions; 5 | 6 | namespace WaveInfo 7 | { 8 | public class InfoChunk : AbstractChunk 9 | { 10 | public string Text { get; set; } 11 | 12 | public override void ReadChunk(BinaryReader reader) 13 | { 14 | base.ReadChunk(reader); 15 | 16 | Text = new string(reader.ReadChars(Convert.ToInt32(Size))).AppendEnd(); 17 | } 18 | 19 | public override string GetReport() 20 | { 21 | var builder = new StringBuilder(base.GetReport()); 22 | builder.AppendLine(this.ToColumns("Text")); 23 | 24 | return builder.ToString(); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /WaveInfo/ListChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace WaveInfo 10 | { 11 | public class ListChunk:AbstractChunk 12 | { 13 | public string ListType; 14 | public override void ReadChunk(BinaryReader reader) 15 | { 16 | base.ReadChunk(reader); 17 | 18 | ListType = new string(reader.ReadChars(4)); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WaveInfo/NOTICE: -------------------------------------------------------------------------------- 1 | INDIANA UNIVERSITY MEDIA HELPER APPLICATIONS: WAVEINFO 2 | 3 | Command-line utility to display embedded metadata properties in .WAV files. 4 | 5 | Copyright (C) 2014-2017, The Trustees of Indiana University. 6 | -------------------------------------------------------------------------------- /WaveInfo/OtherChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace WaveInfo 5 | { 6 | public class OtherChunk : AbstractChunk 7 | { 8 | public byte[] Data { get; set; } 9 | public override void ReadChunk(BinaryReader reader) 10 | { 11 | base.ReadChunk(reader); 12 | 13 | reader.BaseStream.Seek(Size, SeekOrigin.Current); 14 | //Data = reader.ReadBytes(Convert.ToInt32(Size)); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /WaveInfo/RiffChunk.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace WaveInfo 4 | { 5 | public class RiffChunk : AbstractChunk 6 | { 7 | public uint FileLength; //In bytes, measured from offset 8 8 | public string RiffType; //WAVE, usually 9 | 10 | public override void ReadChunk(BinaryReader reader) 11 | { 12 | base.ReadChunk(reader); 13 | 14 | RiffType = new string(reader.ReadChars(4)); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /WaveInfo/WaveFile.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace WaveInfo 5 | { 6 | public class WaveFile 7 | { 8 | public string FileName { get; set; } 9 | public long FileSize { get; set; } 10 | 11 | public List Chunks { get; set; } 12 | 13 | public T GetChunk() where T : AbstractChunk 14 | { 15 | if (Chunks == null || !Chunks.Any()) 16 | { 17 | return null; 18 | } 19 | 20 | return Chunks.FirstOrDefault(c => c.GetType() == typeof (T)) as T; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /deploy.bat: -------------------------------------------------------------------------------- 1 | rmdir %2 /s /q 2 | mkdir %2 3 | copy %1\*.exe %2 4 | copy %1\*.config %2 5 | copy %1\*.dll %2 6 | copy %1\*.doc %2 7 | copy %1\*.docx %2 8 | copy %1\*.txt %2 9 | copy %1\*.bat %2 10 | del %2\*.vshost.exe 11 | del %2\*.vshost.exe.config 12 | ren %2\*.exe.config *.config.dev 13 | -------------------------------------------------------------------------------- /example barcodes.txt: -------------------------------------------------------------------------------- 1 | 8 mm Video 40000000300063 https://pod.mdpi.iu.edu/responses/objects/40000000300063/metadata/digital_provenance 2 | Umatic 40000002133314 https://pod.mdpi.iu.edu/responses/objects/40000002133314/metadata/digital_provenance 3 | Betamax 40000002441915 https://pod.mdpi.iu.edu/responses/objects/40000002441915/metadata/digital_provenance 4 | Cylinder 40000001327644 https://pod.mdpi.iu.edu/responses/objects/40000001327644/metadata/digital_provenance 5 | Lacquer Disc 40000001312158 https://pod.mdpi.iu.edu/responses/objects/40000001312158/metadata/digital_provenance 6 | Open Reel Audio Tape 40000001211368 https://pod.mdpi.iu.edu/responses/objects/40000001211368/metadata/digital_provenance 7 | Open Reel Audio Tape 45000000243771 https://pod.mdpi.iu.edu/responses/objects/45000000243771/metadata/digital_provenance 8 | Open Reel Audio Tape (stereo) 40000000089633 https://pod.mdpi.iu.edu/responses/objects/40000000089633/metadata/digital_provenance 9 | -------------------------------------------------------------------------------- /reference/IU_PID_1.0_technical_only.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IUMDPI/IUMediaHelperApps/32afb704dc9c7691ca0b0f1c3ff01b8bbd451f53/reference/IU_PID_1.0_technical_only.docx -------------------------------------------------------------------------------- /reference/InputTemplate.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IUMDPI/IUMediaHelperApps/32afb704dc9c7691ca0b0f1c3ff01b8bbd451f53/reference/InputTemplate.xlsx -------------------------------------------------------------------------------- /reference/ReferenceInformation.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IUMDPI/IUMediaHelperApps/32afb704dc9c7691ca0b0f1c3ff01b8bbd451f53/reference/ReferenceInformation.txt -------------------------------------------------------------------------------- /reference/mdpi_embeddedMD_audio_20150519.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IUMDPI/IUMediaHelperApps/32afb704dc9c7691ca0b0f1c3ff01b8bbd451f53/reference/mdpi_embeddedMD_audio_20150519.docx --------------------------------------------------------------------------------