// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // Filename : MediaInfoViewModel.cs // Author(s) : Natalia Portillo // // Component : GUI view models. // // --[ Description ] ---------------------------------------------------------- // // View model and code for the media information panel. // // --[ License ] -------------------------------------------------------------- // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General public License for more details. // // You should have received a copy of the GNU General public License // along with this program. If not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2021 Natalia Portillo // ****************************************************************************/ using System; using System.Collections.Generic; using System.IO; using System.Reactive; using System.Text; using Aaru.Gui.ViewModels.Tabs; using Aaru.Gui.ViewModels.Windows; using Aaru.Gui.Views.Tabs; using Aaru.Gui.Views.Windows; using Avalonia; using Avalonia.Controls; using Avalonia.Media.Imaging; using Avalonia.Platform; using MessageBox.Avalonia; using MessageBox.Avalonia.Enums; using ReactiveUI; using ScsiInfo = Aaru.Core.Media.Info.ScsiInfo; namespace Aaru.Gui.ViewModels.Panels { public sealed class MediaInfoViewModel : ViewModelBase { readonly string _devicePath; readonly ScsiInfo _scsiInfo; readonly Window _view; BlurayInfo _blurayInfo; CompactDiscInfo _compactDiscInfo; string _densitySupport; DvdInfo _dvdInfo; DvdWritableInfo _dvdWritableInfo; string _generalVisible; Bitmap _mediaLogo; string _mediaSerial; string _mediaSize; string _mediaType; string _mediumSupport; bool _mmcVisible; bool _saveDensitySupportVisible; bool _saveGetConfigurationVisible; bool _saveMediumSupportVisible; bool _saveReadCapacity16Visible; bool _saveReadCapacityVisible; bool _saveReadMediaSerialVisible; bool _saveRecognizedFormatLayersVisible; bool _saveWriteProtectionStatusVisible; bool _sscVisible; XboxInfo _xboxInfo; public MediaInfoViewModel(ScsiInfo scsiInfo, string devicePath, Window view) { _view = view; SaveReadMediaSerialCommand = ReactiveCommand.Create(ExecuteSaveReadMediaSerialCommand); SaveReadCapacityCommand = ReactiveCommand.Create(ExecuteSaveReadCapacityCommand); SaveReadCapacity16Command = ReactiveCommand.Create(ExecuteSaveReadCapacity16Command); SaveGetConfigurationCommand = ReactiveCommand.Create(ExecuteSaveGetConfigurationCommand); SaveRecognizedFormatLayersCommand = ReactiveCommand.Create(ExecuteSaveRecognizedFormatLayersCommand); SaveWriteProtectionStatusCommand = ReactiveCommand.Create(ExecuteSaveWriteProtectionStatusCommand); SaveDensitySupportCommand = ReactiveCommand.Create(ExecuteSaveDensitySupportCommand); SaveMediumSupportCommand = ReactiveCommand.Create(ExecuteSaveMediumSupportCommand); DumpCommand = ReactiveCommand.Create(ExecuteDumpCommand); ScanCommand = ReactiveCommand.Create(ExecuteScanCommand); IAssetLoader assets = AvaloniaLocator.Current.GetService(); _devicePath = devicePath; _scsiInfo = scsiInfo; var mediaResource = new Uri($"avares://Aaru.Gui/Assets/Logos/Media/{scsiInfo.MediaType}.png"); MediaLogo = assets.Exists(mediaResource) ? new Bitmap(assets.Open(mediaResource)) : null; MediaType = scsiInfo.MediaType.ToString(); if(scsiInfo.Blocks != 0 && scsiInfo.BlockSize != 0) { ulong totalSize = scsiInfo.Blocks * scsiInfo.BlockSize; if(totalSize > 1099511627776) MediaSize = $"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize} bytes/each. (for a total of {totalSize / 1099511627776d:F3} TiB)"; else if(totalSize > 1073741824) MediaSize = $"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize} bytes/each. (for a total of {totalSize / 1073741824d:F3} GiB)"; else if(totalSize > 1048576) MediaSize = $"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize} bytes/each. (for a total of {totalSize / 1048576d:F3} MiB)"; else if(totalSize > 1024) MediaSize = $"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize} bytes/each. (for a total of {totalSize / 1024d:F3} KiB)"; else MediaSize = $"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize} bytes/each. (for a total of {totalSize} bytes)"; } if(scsiInfo.MediaSerialNumber != null) { var sbSerial = new StringBuilder(); for(int i = 4; i < scsiInfo.MediaSerialNumber.Length; i++) sbSerial.AppendFormat("{0:X2}", scsiInfo.MediaSerialNumber[i]); MediaSerial = sbSerial.ToString(); } SaveReadMediaSerialVisible = scsiInfo.MediaSerialNumber != null; SaveReadCapacityVisible = scsiInfo.ReadCapacity != null; SaveReadCapacity16Visible = scsiInfo.ReadCapacity16 != null; SaveGetConfigurationVisible = scsiInfo.MmcConfiguration != null; SaveRecognizedFormatLayersVisible = scsiInfo.RecognizedFormatLayers != null; SaveWriteProtectionStatusVisible = scsiInfo.WriteProtectionStatus != null; MmcVisible = SaveGetConfigurationVisible || SaveRecognizedFormatLayersVisible || SaveWriteProtectionStatusVisible; if(scsiInfo.DensitySupportHeader.HasValue) DensitySupport = Decoders.SCSI.SSC.DensitySupport.PrettifyDensity(scsiInfo.DensitySupportHeader); if(scsiInfo.MediaTypeSupportHeader.HasValue) MediumSupport = Decoders.SCSI.SSC.DensitySupport.PrettifyMediumType(scsiInfo.MediaTypeSupportHeader); SaveDensitySupportVisible = scsiInfo.DensitySupport != null; SaveMediumSupportVisible = scsiInfo.MediaTypeSupport != null; SscVisible = SaveDensitySupportVisible || SaveMediumSupportVisible; CompactDiscInfo = new CompactDiscInfo { DataContext = new CompactDiscInfoViewModel(scsiInfo.Toc, scsiInfo.Atip, scsiInfo.DiscInformation, scsiInfo.Session, scsiInfo.RawToc, scsiInfo.Pma, scsiInfo.CdTextLeadIn, scsiInfo.DecodedToc, scsiInfo.DecodedAtip, scsiInfo.DecodedSession, scsiInfo.FullToc, scsiInfo.DecodedCdTextLeadIn, scsiInfo.DecodedDiscInformation, scsiInfo.Mcn, scsiInfo.Isrcs, _view) }; DvdInfo = new DvdInfo { DataContext = new DvdInfoViewModel(scsiInfo.MediaType, scsiInfo.DvdPfi, scsiInfo.DvdDmi, scsiInfo.DvdCmi, scsiInfo.HddvdCopyrightInformation, scsiInfo.DvdBca, scsiInfo.DvdAacs, scsiInfo.DecodedPfi, _view) }; XboxInfo = new XboxInfo { DataContext = new XboxInfoViewModel(scsiInfo.XgdInfo, scsiInfo.DvdDmi, scsiInfo.XboxSecuritySector, scsiInfo.DecodedXboxSecuritySector, _view) }; DvdWritableInfo = new DvdWritableInfo { DataContext = new DvdWritableInfoViewModel(scsiInfo.MediaType, scsiInfo.DvdRamDds, scsiInfo.DvdRamCartridgeStatus, scsiInfo.DvdRamSpareArea, scsiInfo.LastBorderOutRmd, scsiInfo.DvdPreRecordedInfo, scsiInfo.DvdrMediaIdentifier, scsiInfo.DvdrPhysicalInformation, scsiInfo.HddvdrMediumStatus, scsiInfo.HddvdrLastRmd, scsiInfo.DvdrLayerCapacity, scsiInfo.DvdrDlMiddleZoneStart, scsiInfo.DvdrDlJumpIntervalSize, scsiInfo.DvdrDlManualLayerJumpStartLba, scsiInfo.DvdrDlRemapAnchorPoint, scsiInfo.DvdPlusAdip, scsiInfo.DvdPlusDcb, _view) }; BlurayInfo = new BlurayInfo { DataContext = new BlurayInfoViewModel(scsiInfo.BlurayDiscInformation, scsiInfo.BlurayBurstCuttingArea, scsiInfo.BlurayDds, scsiInfo.BlurayCartridgeStatus, scsiInfo.BluraySpareAreaInformation, scsiInfo.BlurayPowResources, scsiInfo.BlurayTrackResources, scsiInfo.BlurayRawDfl, scsiInfo.BlurayPac, _view) }; } public ReactiveCommand SaveReadMediaSerialCommand { get; } public ReactiveCommand SaveReadCapacityCommand { get; } public ReactiveCommand SaveReadCapacity16Command { get; } public ReactiveCommand SaveGetConfigurationCommand { get; } public ReactiveCommand SaveRecognizedFormatLayersCommand { get; } public ReactiveCommand SaveWriteProtectionStatusCommand { get; } public ReactiveCommand SaveDensitySupportCommand { get; } public ReactiveCommand SaveMediumSupportCommand { get; } public ReactiveCommand DumpCommand { get; } public ReactiveCommand ScanCommand { get; } public Bitmap MediaLogo { get => _mediaLogo; set => this.RaiseAndSetIfChanged(ref _mediaLogo, value); } public string GeneralVisible { get => _generalVisible; set => this.RaiseAndSetIfChanged(ref _generalVisible, value); } public string MediaType { get => _mediaType; set => this.RaiseAndSetIfChanged(ref _mediaType, value); } public string MediaSize { get => _mediaSize; set => this.RaiseAndSetIfChanged(ref _mediaSize, value); } public string MediaSerial { get => _mediaSerial; set => this.RaiseAndSetIfChanged(ref _mediaSerial, value); } public bool SaveReadMediaSerialVisible { get => _saveReadMediaSerialVisible; set => this.RaiseAndSetIfChanged(ref _saveReadMediaSerialVisible, value); } public bool SaveReadCapacityVisible { get => _saveReadCapacityVisible; set => this.RaiseAndSetIfChanged(ref _saveReadCapacityVisible, value); } public bool SaveReadCapacity16Visible { get => _saveReadCapacity16Visible; set => this.RaiseAndSetIfChanged(ref _saveReadCapacity16Visible, value); } public bool MmcVisible { get => _mmcVisible; set => this.RaiseAndSetIfChanged(ref _mmcVisible, value); } public bool SaveGetConfigurationVisible { get => _saveGetConfigurationVisible; set => this.RaiseAndSetIfChanged(ref _saveGetConfigurationVisible, value); } public bool SaveRecognizedFormatLayersVisible { get => _saveRecognizedFormatLayersVisible; set => this.RaiseAndSetIfChanged(ref _saveRecognizedFormatLayersVisible, value); } public bool SaveWriteProtectionStatusVisible { get => _saveWriteProtectionStatusVisible; set => this.RaiseAndSetIfChanged(ref _saveWriteProtectionStatusVisible, value); } public bool SscVisible { get => _sscVisible; set => this.RaiseAndSetIfChanged(ref _sscVisible, value); } public string DensitySupport { get => _densitySupport; set => this.RaiseAndSetIfChanged(ref _densitySupport, value); } public string MediumSupport { get => _mediumSupport; set => this.RaiseAndSetIfChanged(ref _mediumSupport, value); } public bool SaveDensitySupportVisible { get => _saveDensitySupportVisible; set => this.RaiseAndSetIfChanged(ref _saveDensitySupportVisible, value); } public bool SaveMediumSupportVisible { get => _saveMediumSupportVisible; set => this.RaiseAndSetIfChanged(ref _saveMediumSupportVisible, value); } public CompactDiscInfo CompactDiscInfo { get => _compactDiscInfo; set => this.RaiseAndSetIfChanged(ref _compactDiscInfo, value); } public DvdInfo DvdInfo { get => _dvdInfo; set => this.RaiseAndSetIfChanged(ref _dvdInfo, value); } public DvdWritableInfo DvdWritableInfo { get => _dvdWritableInfo; set => this.RaiseAndSetIfChanged(ref _dvdWritableInfo, value); } public XboxInfo XboxInfo { get => _xboxInfo; set => this.RaiseAndSetIfChanged(ref _xboxInfo, value); } public BlurayInfo BlurayInfo { get => _blurayInfo; set => this.RaiseAndSetIfChanged(ref _blurayInfo, value); } async void SaveElement(byte[] data) { var dlgSaveBinary = new SaveFileDialog(); dlgSaveBinary.Filters.Add(new FileDialogFilter { Extensions = new List(new[] { "*.bin" }), Name = "Binary" }); string result = await dlgSaveBinary.ShowAsync(_view); if(result is null) return; var saveFs = new FileStream(result, FileMode.Create); saveFs.Write(data, 0, data.Length); saveFs.Close(); } void ExecuteSaveReadMediaSerialCommand() => SaveElement(_scsiInfo.MediaSerialNumber); void ExecuteSaveReadCapacityCommand() => SaveElement(_scsiInfo.ReadCapacity); void ExecuteSaveReadCapacity16Command() => SaveElement(_scsiInfo.ReadCapacity16); void ExecuteSaveGetConfigurationCommand() => SaveElement(_scsiInfo.MmcConfiguration); void ExecuteSaveRecognizedFormatLayersCommand() => SaveElement(_scsiInfo.RecognizedFormatLayers); void ExecuteSaveWriteProtectionStatusCommand() => SaveElement(_scsiInfo.WriteProtectionStatus); void ExecuteSaveDensitySupportCommand() => SaveElement(_scsiInfo.DensitySupport); void ExecuteSaveMediumSupportCommand() => SaveElement(_scsiInfo.MediaTypeSupport); async void ExecuteDumpCommand() { if(_scsiInfo.MediaType == CommonTypes.MediaType.GDR || _scsiInfo.MediaType == CommonTypes.MediaType.GDROM) { await MessageBoxManager. GetMessageBoxStandardWindow("Error", "GD-ROM dump support is not yet implemented.", ButtonEnum.Ok, Icon.Error).ShowDialog(_view); return; } if((_scsiInfo.MediaType == CommonTypes.MediaType.XGD || _scsiInfo.MediaType == CommonTypes.MediaType.XGD2 || _scsiInfo.MediaType == CommonTypes.MediaType.XGD3) && _scsiInfo.DeviceInfo.ScsiInquiry?.KreonPresent != true) { await MessageBoxManager. GetMessageBoxStandardWindow("Error", "Dumping Xbox discs require a Kreon drive.", ButtonEnum.Ok, Icon.Error).ShowDialog(_view); return; } var mediaDumpWindow = new MediaDump(); mediaDumpWindow.DataContext = new MediaDumpViewModel(_devicePath, _scsiInfo.DeviceInfo, mediaDumpWindow, _scsiInfo); mediaDumpWindow.Show(); } async void ExecuteScanCommand() { switch(_scsiInfo.MediaType) { // TODO: GD-ROM case CommonTypes.MediaType.GDR: case CommonTypes.MediaType.GDROM: await MessageBoxManager. GetMessageBoxStandardWindow("Error", "GD-ROM scan support is not yet implemented.", ButtonEnum.Ok, Icon.Error).ShowDialog(_view); return; // TODO: Xbox case CommonTypes.MediaType.XGD: case CommonTypes.MediaType.XGD2: case CommonTypes.MediaType.XGD3: await MessageBoxManager. GetMessageBoxStandardWindow("Error", "Scanning Xbox discs is not yet supported.", ButtonEnum.Ok, Icon.Error).ShowDialog(_view); return; } var mediaScanWindow = new MediaScan(); mediaScanWindow.DataContext = new MediaScanViewModel(_devicePath, mediaScanWindow); mediaScanWindow.Show(); } } }