Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions CompactGUI.Core/WOFHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,46 @@ public static WOFCompressionAlgorithm WOFConvertCompressionLevel(CompressionMode
};
}

// Native WOF values are API identifiers, not an ordering by compression strength.
public static WOFCompressionAlgorithm GetDominantCompressionMode(
IEnumerable<AnalysedFileDetails>? analysedFiles,
WOFCompressionAlgorithm fallback = WOFCompressionAlgorithm.NO_COMPRESSION)
{
if (analysedFiles is null) return fallback;

var dominant = analysedFiles
.Where(file => file.CompressionMode is
WOFCompressionAlgorithm.XPRESS4K or
WOFCompressionAlgorithm.XPRESS8K or
WOFCompressionAlgorithm.XPRESS16K or
WOFCompressionAlgorithm.LZX)
.GroupBy(file => file.CompressionMode)
.Select(group => new
{
Mode = group.Key,
UncompressedBytes = group.Sum(file => file.UncompressedSize),
FileCount = group.Count()
})
.OrderByDescending(group => group.FileCount)
.ThenByDescending(group => group.UncompressedBytes)
.ThenByDescending(group => GetCompressionStrength(group.Mode))
.FirstOrDefault();

return dominant?.Mode ?? fallback;
}

private static int GetCompressionStrength(WOFCompressionAlgorithm mode)
{
return mode switch
{
WOFCompressionAlgorithm.XPRESS4K => 0,
WOFCompressionAlgorithm.XPRESS8K => 1,
WOFCompressionAlgorithm.XPRESS16K => 2,
WOFCompressionAlgorithm.LZX => 3,
_ => -1
};
}

[StructLayout(LayoutKind.Sequential)]
public struct WOF_FILE_COMPRESSION_INFO_V1
{
Expand Down
6 changes: 1 addition & 5 deletions CompactGUI.Watcher/BackgroundCompactor.vb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Public Class BackgroundCompactor
If folders.Contains(folder) Then
'Ensure the folder is still in the original collection before updating.
Using analyser As New Core.Analyser(folder.Folder, NullLogger(Of Core.Analyser).Instance)
Dim analysed = Await analyser.GetAnalysedFilesAsync(cancellationTokenSource.Token)
Await analyser.GetAnalysedFilesAsync(cancellationTokenSource.Token)

If cancellationTokenSource.IsCancellationRequested Then Return False

Expand All @@ -102,10 +102,6 @@ Public Class BackgroundCompactor
folder.LastCompressedSize = analyser.CompressedBytes
folder.LastSystemModifiedDate = DateTime.Now

If analysed IsNot Nothing AndAlso analysed.Count > 0 Then
folder.CompressionLevel = analysed.Select(Function(f) f.CompressionMode).Max
End If

folder.LastCompressedDate = DateTime.Now
folder.HasTargetChanged = False
End Using
Expand Down
15 changes: 9 additions & 6 deletions CompactGUI.Watcher/Watcher.vb
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ Partial Public Class Watcher : Inherits ObservableRecipient : Implements IRecipi

End Sub

Public Async Sub UpdateWatched(folder As String, analyser As Analyser, isFreshlyCompressed As Boolean, Optional immediateFlushToDisk As Boolean = True)
Public Async Function UpdateWatched(folder As String, analyser As Analyser, isFreshlyCompressed As Boolean, Optional immediateFlushToDisk As Boolean = True, Optional targetCompressionLevel As WOFCompressionAlgorithm = WOFCompressionAlgorithm.NO_COMPRESSION) As Task

Dim existingItem = WatchedFolders.FirstOrDefault(Function(f) f.Folder = folder)

Expand All @@ -288,8 +288,10 @@ Partial Public Class Watcher : Inherits ObservableRecipient : Implements IRecipi
existingItem.LastCheckedSize = analyser.CompressedBytes
existingItem.LastUncompressedSize = analyser.UncompressedBytes
existingItem.LastSystemModifiedDate = DateTime.Now
If analysedFiles?.Count <> 0 Then
existingItem.CompressionLevel = analysedFiles.Select(Function(f) f.CompressionMode).Max
If isFreshlyCompressed AndAlso targetCompressionLevel <> WOFCompressionAlgorithm.NO_COMPRESSION Then
existingItem.CompressionLevel = targetCompressionLevel
Else
existingItem.CompressionLevel = WOFHelper.GetDominantCompressionMode(analysedFiles)
End If

If isFreshlyCompressed Then
Expand All @@ -304,7 +306,7 @@ Partial Public Class Watcher : Inherits ObservableRecipient : Implements IRecipi
OnPropertyChanged(NameOf(TotalSaved))
If immediateFlushToDisk Then WriteToFile()
End If
End Sub
End Function

Private Sub UpdateFolderProperties(existingItem As WatchedFolder, newItem As WatchedFolder)
With existingItem
Expand Down Expand Up @@ -500,8 +502,9 @@ Partial Public Class Watcher : Inherits ObservableRecipient : Implements IRecipi
watched.LastSystemModifiedDate = watched.LastChangedDate

If analysedFiles?.Count <> 0 Then
Dim mainCompressionLVL = analysedFiles.Select(Function(f) f.CompressionMode).Max
watched.CompressionLevel = If(mainCompressionLVL <> WOFCompressionAlgorithm.NO_COMPRESSION, mainCompressionLVL, watched.CompressionLevel)
If watched.CompressionLevel = WOFCompressionAlgorithm.NO_COMPRESSION Then
watched.CompressionLevel = WOFHelper.GetDominantCompressionMode(analysedFiles)
End If

If checkDiskModified Then
Dim lastDiskWriteTime = analysedFiles.Select(Function(fl)
Expand Down
2 changes: 1 addition & 1 deletion CompactGUI/ViewModels/FolderViewModel.vb
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Public NotInheritable Class FolderViewModel : Inherits ObservableObject : Implem
<RelayCommand>
Private Async Function Uncompress() As Task
Await _compressableFolderService.UncompressFolder(Folder)
_watcher.UpdateWatched(Folder.FolderName, Folder.Analyser, False)
Await _watcher.UpdateWatched(Folder.FolderName, Folder.Analyser, False)
End Function

<RelayCommand>
Expand Down
17 changes: 13 additions & 4 deletions CompactGUI/ViewModels/HomeViewModel.vb
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,8 @@ Partial Public NotInheritable Class HomeViewModel : Inherits ObservableRecipient

End If

_watcher.UpdateWatched(folder.FolderName, folder.Analyser, True)
Dim targetCompressionLevel = Core.WOFHelper.WOFConvertCompressionLevel(folder.CompressionOptions.SelectedCompressionMode)
Await _watcher.UpdateWatched(folder.FolderName, folder.Analyser, ret, targetCompressionLevel:=targetCompressionLevel)

'For Each poorext In folder.PoorlyCompressedFiles
' Debug.WriteLine($"{poorext.extension} : {poorext.totalFiles} with ratio of {poorext.cRatio}")
Expand All @@ -264,7 +265,8 @@ Partial Public NotInheritable Class HomeViewModel : Inherits ObservableRecipient
Compressing = False

For Each folder In Folders.Where(Function(f) f.CompressionOptions.WatchFolderForChanges)
AddOrUpdateFolderWatcher(folder)
Dim wasCompressedInCurrentBatch = foldersToCompress.Contains(folder) AndAlso folder.IsFreshlyCompressed
AddOrUpdateFolderWatcher(folder, wasCompressedInCurrentBatch)
Next

RemoveFolderCommand.NotifyCanExecuteChanged()
Expand All @@ -278,7 +280,7 @@ Partial Public NotInheritable Class HomeViewModel : Inherits ObservableRecipient
End Function


Public Sub AddOrUpdateFolderWatcher(folder As CompressableFolder)
Public Sub AddOrUpdateFolderWatcher(folder As CompressableFolder, wasCompressedInCurrentBatch As Boolean)
HomeViewModelLog.AddingFolderToWatcher(_logger, folder.FolderName)

Dim newWatched = New Watcher.WatchedFolder(folder.FolderName, folder.DisplayName)
Expand All @@ -289,7 +291,14 @@ Partial Public NotInheritable Class HomeViewModel : Inherits ObservableRecipient
newWatched.LastCheckedDate = DateTime.Now
newWatched.LastCheckedSize = folder.CompressedBytes
newWatched.LastSystemModifiedDate = DateTime.Now
newWatched.CompressionLevel = If(folder.AnalysisResults.Any(), folder.AnalysisResults.Max(Function(f) f.CompressionMode), Core.WOFCompressionAlgorithm.NO_COMPRESSION)
Dim existingWatched = _watcher.WatchedFolders.FirstOrDefault(Function(w) w.Folder = folder.FolderName)
If wasCompressedInCurrentBatch Then
newWatched.CompressionLevel = Core.WOFHelper.WOFConvertCompressionLevel(folder.CompressionOptions.SelectedCompressionMode)
ElseIf existingWatched IsNot Nothing Then
newWatched.CompressionLevel = existingWatched.CompressionLevel
Else
newWatched.CompressionLevel = Core.WOFHelper.GetDominantCompressionMode(folder.AnalysisResults)
End If

_watcher.AddOrUpdateWatched(newWatched)

Expand Down