Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1ee47d2
Modified release-windows for automated releases
UnknownException Mar 2, 2025
a64bbc0
Initial implementation for Linux compatibility
UnknownException Mar 8, 2025
90d9530
CUERipper UI reimplemented in Avalonia
UnknownException Mar 8, 2025
10fb6d9
Enable Linux-specific code for drive detection
UnknownException Mar 9, 2025
922ae55
Update CHANGELOG.md
UnknownException Mar 9, 2025
0b4cbd9
Minor accessibility improvements
UnknownException Mar 9, 2025
b325341
Improved album art handling
UnknownException Mar 16, 2025
c595642
Prioritize primary Cover Art
UnknownException Mar 18, 2025
ff01a93
Build 'Inno Setup' installer in Windows workflow
UnknownException Mar 19, 2025
15b0682
Fix drive selection and in-app updater
UnknownException Mar 20, 2025
56faef0
Allow single letter in version string
UnknownException Mar 20, 2025
aae35f8
Add option to toggle updates off
UnknownException Mar 20, 2025
162dd56
Write to user dir. if user profiles are enabled
UnknownException Mar 20, 2025
c0e3e20
Write logs to user dir and update user agent
UnknownException Mar 23, 2025
26c5556
Fix drive detection on Linux
UnknownException Jun 25, 2025
2189f5a
Fix gap detection on Linux
UnknownException Jun 25, 2025
ba193f7
Use CUESheet for album lookup
UnknownException Jun 25, 2025
a5a8faa
Enable checking for updates on Linux
UnknownException Jun 25, 2025
9230110
Fix UI track progress on error correction passes
UnknownException Jun 25, 2025
6667ba8
Add CUERipper Linux build to github workflow
UnknownException Jun 25, 2025
c5976bf
Refactor and extend grid usability features
UnknownException Jul 13, 2025
6636ded
Fix .NET 4.7 compatibility in CUERipper.Avalonia
UnknownException Jul 19, 2025
7c2bb3b
Add libFLAC and LAME in Linux build
UnknownException Jul 23, 2025
2eb9e02
Split Linux and Windows into separate workflows
UnknownException Jul 25, 2025
50066d8
Fix disc repair when primary encoding is set to image
UnknownException Aug 2, 2025
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
49 changes: 49 additions & 0 deletions .github/workflows/release-linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
name: release-linux

# yamllint disable-line rule:truthy
on:
push:
tags:
- '*'
workflow_dispatch:

defaults:
run:
shell: bash

jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install build tools
run: |
sudo apt-get update
sudo apt-get install -y autoconf automake libtool-bin
- name: Apply Patches
run: ./git_init.sh
- name: Publish CUERipper.Avalonia
run: ./publish_linux64.sh
- name: Get CUETools Version
id: get_version
run: |
PRODUCTVER=$(grep 'CUEToolsVersion =' CUETools.Processor/CUESheet.cs | awk '{print $6}' | tr -d '";\r')
echo "CUETools version: $PRODUCTVER"
echo "CUETOOLS_VERSION=$PRODUCTVER" >> $GITHUB_ENV
- name: Package CUERipper.Avalonia
run: ./package_linux64.sh
- name: Add artifacts to Release
uses: softprops/action-gh-release@v2
with:
name: CUETools ${{ env.CUETOOLS_VERSION }}
body_path: CHANGELOG.md
draft: false
prerelease: false
tag_name: ${{ github.ref_name }}
files: |
CUERipper.Linux64_${{ env.CUETOOLS_VERSION }}.tar.gz
CUERipper.Linux64_${{ env.CUETOOLS_VERSION }}.tar.gz.sha256

46 changes: 43 additions & 3 deletions .github/workflows/release-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Inno Setup
run: pwsh -File ./install_inno.ps1
- name: Apply patches
# yamllint disable-line rule:line-length
run: |
Expand All @@ -53,7 +55,45 @@ jobs:
- name: Collect files
run: |
collect_files.bat
- uses: actions/upload-artifact@v4
- name: Collect files (Lite)
run: |
collect_files_lite.bat
- name: Package files
run: pwsh -File ./packaging.ps1
- name: Get CUETools Version
id: get_version
run: |
for /f "tokens=6 delims= " %%a in ('find "CUEToolsVersion =" .\CUETools.Processor\CUESheet.cs') do set PRODUCTVER=%%a
set PRODUCTVER=%PRODUCTVER:"=%
set PRODUCTVER=%PRODUCTVER:;=%
echo CUETools version: %PRODUCTVER%
echo CUETOOLS_VERSION=%PRODUCTVER%>>%GITHUB_ENV%
shell: cmd
- name: Build Windows installer
run: |
"C:\\Program Files (x86)\\Inno Setup 6\\ISCC.exe" "installer.iss"
shell: cmd
- name: Generate hash for Windows installer
run: |
$installer = "CUETools_Setup_${{ env.CUETOOLS_VERSION }}.exe"
$installerHash = (Get-FileHash $installer -Algorithm SHA256).Hash.ToLower()
"$installerHash *$installer" | Out-File -Encoding ASCII "$installer.sha256"
shell: pwsh
- name: Add artifacts to Release
uses: softprops/action-gh-release@v2
with:
name: deploy
path: bin/Release/CUETools_*/
name: CUETools ${{ env.CUETOOLS_VERSION }}
body_path: CHANGELOG.md
draft: false
prerelease: false
tag_name: ${{ github.ref_name }}
files: |
CUETools_Setup_${{ env.CUETOOLS_VERSION }}.exe
CUETools_Setup_${{ env.CUETOOLS_VERSION }}.exe.sha256
CUETools_${{ env.CUETOOLS_VERSION }}.zip
CUETools_${{ env.CUETOOLS_VERSION }}.zip.sha256
CUETools.Lite_${{ env.CUETOOLS_VERSION }}.zip
CUETools.Lite_${{ env.CUETOOLS_VERSION }}.zip.sha256
CUETools.CTDB.EACPlugin.${{ env.CUETOOLS_VERSION }}.zip
CUETools.CTDB.EACPlugin.${{ env.CUETOOLS_VERSION }}.zip.sha256

2 changes: 1 addition & 1 deletion Bwg.Logging/Bwg.Logging.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net47;net20</TargetFrameworks>
<TargetFrameworks>net47;net20;netstandard2.0</TargetFrameworks>
<Version>0.0.7.1</Version>
<AssemblyName>Bwg.Logging</AssemblyName>
<RootNamespace>Bwg.Logging</RootNamespace>
Expand Down
6 changes: 4 additions & 2 deletions Bwg.Scsi/Bwg.Scsi.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net47;net20</TargetFrameworks>
<TargetFrameworks>net47;net20;netstandard2.0</TargetFrameworks>
<Version>0.0.7.1</Version>
<AssemblyName>Bwg.Scsi</AssemblyName>
<RootNamespace>Bwg.Scsi</RootNamespace>
Expand All @@ -27,5 +27,7 @@
<ItemGroup>
<ProjectReference Include="..\Bwg.Logging\Bwg.Logging.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0' ">
<ProjectReference Include="..\CUETools.Interop\CUETools.Interop.csproj" />
</ItemGroup>
</Project>
15 changes: 15 additions & 0 deletions Bwg.Scsi/Command.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,22 @@ public Command(ScsiCommandCode code, byte cdbsize, int bufsize, CmdDirection dir
{
m_delete_buffer = true;
m_buffer = Marshal.AllocHGlobal(bufsize);
#if NETSTANDARD2_0
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
RtlZeroMemory(m_buffer, bufsize);
}
else
{
for(int i = 0; i < bufsize; ++i)
{
Marshal.WriteByte(m_buffer, i, 0x00);
}
}
#else
RtlZeroMemory(m_buffer, bufsize);

#endif
}

m_dir = dir;
Expand Down
63 changes: 40 additions & 23 deletions Bwg.Scsi/Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ namespace Bwg.Scsi
/// <summary>
///
/// </summary>
public unsafe class Device : WinDev
public sealed unsafe class Device : IDisposable
{
#region Structures for DeviceIoControl
[StructLayout(LayoutKind.Explicit)]
struct SCSI_PASS_THROUGH_DIRECT32
internal struct SCSI_PASS_THROUGH_DIRECT32
{
[FieldOffset(0)]public ushort Length;
[FieldOffset(2)]public byte ScsiStatus;
Expand All @@ -66,7 +66,7 @@ struct SCSI_PASS_THROUGH_DIRECT32
} ;

[StructLayout(LayoutKind.Explicit)]
struct SCSI_PASS_THROUGH_DIRECT64
internal struct SCSI_PASS_THROUGH_DIRECT64
{
[FieldOffset(0)]public ushort Length;
[FieldOffset(2)]public byte ScsiStatus;
Expand All @@ -85,7 +85,7 @@ struct SCSI_PASS_THROUGH_DIRECT64
} ;

[StructLayout(LayoutKind.Explicit)]
struct IO_SCSI_CAPABILITIES
internal struct IO_SCSI_CAPABILITIES
{
[FieldOffset(0)]public uint Length;
[FieldOffset(4)]public uint MaximumTransferLength;
Expand All @@ -98,7 +98,7 @@ struct IO_SCSI_CAPABILITIES
} ;

[StructLayout(LayoutKind.Explicit)]
private struct PREVENT_MEDIA_REMOVAL
internal struct PREVENT_MEDIA_REMOVAL
{
[FieldOffset(0)] public uint PreventMediaRemoval;
};
Expand All @@ -117,9 +117,9 @@ private struct PREVENT_MEDIA_REMOVAL
private int m_MaximumTransferLength;
#endregion

#region private static data structures
static ushort m_scsi_request_size_32 = 44;
static ushort m_scsi_request_size_64 = 56;
#region private constant data structure sizes
internal const ushort m_scsi_request_size_32 = 44;
internal const ushort m_scsi_request_size_64 = 56;
#endregion

#region public constants
Expand All @@ -131,9 +131,9 @@ private struct PREVENT_MEDIA_REMOVAL
#endregion

#region Private constants
private const uint IOCTL_SCSI_PASS_THROUGH_DIRECT = 0x4d014;
private const uint IOCTL_SCSI_GET_CAPABILITIES = 0x41010;
private const uint IOCTL_STORAGE_MEDIA_REMOVAL = 0x2D4804;
internal const uint IOCTL_SCSI_PASS_THROUGH_DIRECT = 0x4d014;
internal const uint IOCTL_SCSI_GET_CAPABILITIES = 0x41010;
internal const uint IOCTL_STORAGE_MEDIA_REMOVAL = 0x2D4804;

private const uint ERROR_NOT_SUPPORTED = 50 ;
#endregion
Expand Down Expand Up @@ -816,10 +816,10 @@ private CommandStatus SendCommand64(Command cmd)

// Send through ioctl field
IntPtr pt = new IntPtr(&f);
if (!Control(IOCTL_SCSI_PASS_THROUGH_DIRECT, pt, total, pt, total, ref ret, IntPtr.Zero))
if (!_sysDev.Control(IOCTL_SCSI_PASS_THROUGH_DIRECT, pt, total, pt, total, ref ret, IntPtr.Zero))
{
string str ;
str = "IOCTL_SCSI_PASS_THROUGH_DIRECT failed - " + Win32ErrorToString(LastError);
str = "IOCTL_SCSI_PASS_THROUGH_DIRECT failed - " + _sysDev.ErrorCodeToString(_sysDev.LastError);
m_logger.LogMessage(new UserMessage(UserMessage.Category.Error, 0, str));
return CommandStatus.IoctlFailed;
}
Expand Down Expand Up @@ -867,10 +867,10 @@ private CommandStatus SendCommand32(Command cmd)

// Send through ioctl field
IntPtr pt = new IntPtr(&f);
if (!Control(IOCTL_SCSI_PASS_THROUGH_DIRECT, pt, total, pt, total, ref ret, IntPtr.Zero))
if (!_sysDev.Control(IOCTL_SCSI_PASS_THROUGH_DIRECT, pt, total, pt, total, ref ret, IntPtr.Zero))
{
string str ;
str = "IOCTL_SCSI_PASS_THROUGH_DIRECT failed - " + Win32ErrorToString(LastError);
str = "IOCTL_SCSI_PASS_THROUGH_DIRECT failed - " + _sysDev.ErrorCodeToString(_sysDev.LastError);
m_logger.LogMessage(new UserMessage(UserMessage.Category.Error, 0, str));
return CommandStatus.IoctlFailed;
}
Expand Down Expand Up @@ -902,7 +902,7 @@ void QueryBufferSize()
uint ret = 0;
IntPtr pt = new IntPtr(&f);
uint total = (uint)Marshal.SizeOf(f);
if (Control(IOCTL_SCSI_GET_CAPABILITIES, pt, total, pt, total, ref ret, IntPtr.Zero))
if (_sysDev.Control(IOCTL_SCSI_GET_CAPABILITIES, pt, total, pt, total, ref ret, IntPtr.Zero))
{
if (f.MaximumTransferLength > Int32.MaxValue)
m_MaximumTransferLength = Int32.MaxValue;
Expand All @@ -927,6 +927,8 @@ void QueryBufferSize()

static global::System.Resources.ResourceManager messages;

private readonly ISysDev _sysDev;

#region constructor
/// <summary>
///
Expand All @@ -942,15 +944,29 @@ public Device(Logger l)
else
m_ossize = 64;


// m_logger.LogMessage(new UserMessage(UserMessage.Category.Info, 0, "Operating System Size: " + m_ossize.ToString()));
#if NETSTANDARD2_0
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
_sysDev = new WinDev();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
_sysDev = new LinDev();
}
else throw new NotSupportedException("This OS is currently not supported, feel free to add an implementation!");
#else
_sysDev = new WinDev();
#endif
}

static Device()
{
messages = new global::System.Resources.ResourceManager("Bwg.Scsi.Messages", typeof(Device).Assembly);
}

#endregion
#endregion

#region Public Functions

Expand All @@ -971,9 +987,9 @@ public static bool IsLongWriteInProgress(byte asc, byte ascq)
/// </summary>
/// <param name="name">name of the SCSI device</param>
/// <returns>true if the open succeeded</returns>
public override bool Open(string name)
public bool Open(string name)
{
if (!base.Open(name))
if (!_sysDev.Open(name))
return false;

QueryBufferSize();
Expand All @@ -986,9 +1002,9 @@ public override bool Open(string name)
/// </summary>
/// <param name="letter"></param>
/// <returns></returns>
public override bool Open(char letter)
public bool Open(char letter)
{
if (!base.Open(letter))
if (!_sysDev.Open(letter))
return false ;

QueryBufferSize();
Expand Down Expand Up @@ -3713,15 +3729,16 @@ public bool DisableEjectDisc(bool bDisable)
{
uint uiReturnedBytes = 0;
IntPtr pt = new IntPtr(&pmr);
bResult = Control(IOCTL_STORAGE_MEDIA_REMOVAL, pt, uiPmrSize, pt, uiPmrSize, ref uiReturnedBytes, IntPtr.Zero);
bResult = _sysDev.Control(IOCTL_STORAGE_MEDIA_REMOVAL, pt, uiPmrSize, pt, uiPmrSize, ref uiReturnedBytes, IntPtr.Zero);
if (!bResult)
{
string str = "IOCTL_STORAGE_MEDIA_REMOVAL failed - " + Win32ErrorToString(LastError);
string str = "IOCTL_STORAGE_MEDIA_REMOVAL failed - " + _sysDev.ErrorCodeToString(_sysDev.LastError);
m_logger.LogMessage(new UserMessage(UserMessage.Category.Error, 0, str));
}
}
return bResult;
}

public void Dispose() => _sysDev.Dispose();
}
}
6 changes: 5 additions & 1 deletion Bwg.Scsi/DeviceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ public void ScanForDevices()
Device dev = new Device(m_logger) ;
if (!dev.Open(name))
{
dev.Dispose();

m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, dlev, " ... device open failed"));
continue ;
}
Expand All @@ -117,6 +119,8 @@ public void ScanForDevices()
DeviceInfo info = DeviceInfo.CreateDevice(name, letter);
if (!info.ExtractInfo(dev))
{
dev.Dispose();

m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, dlev, " ... cannot extract inquiry information from the drive"));

string str = "The drive '" + letter + "' (" + name + ") is a CD/DVD driver, but is not a valid MMC device.";
Expand All @@ -128,7 +132,7 @@ public void ScanForDevices()

m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, dlev, " ... device added to device list"));
m_devices_found.Add(info) ;
dev.Close() ;
dev.Dispose();
}

if (AfterScan != null)
Expand Down
15 changes: 15 additions & 0 deletions Bwg.Scsi/ISysDev.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;

namespace Bwg.Scsi
{
internal interface ISysDev : IDisposable
{
int LastError { get; }

void Close();
bool Control(uint code, IntPtr inbuf, uint insize, IntPtr outbuf, uint outsize, ref uint ret, IntPtr overlapped);
bool Open(string name);
bool Open(char letter);
string ErrorCodeToString(int error);
}
}
Loading