Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#624 support utf8 bom cue sheet #636

Merged
merged 16 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
d0a7370
chore(deps-dev): bump com.google.guava:guava
dependabot[bot] Sep 23, 2024
a8d65f4
chore(deps): bump lucene.version from 9.11.1 to 9.12.0
dependabot[bot] Sep 30, 2024
97d830e
chore(deps): bump io.fabric8:docker-maven-plugin from 0.45.0 to 0.45.1
dependabot[bot] Sep 30, 2024
4c1daab
chore(deps): bump aquasecurity/trivy-action from 0.24.0 to 0.28.0
dependabot[bot] Oct 15, 2024
b7c65b3
chore(deps): bump com.google.errorprone:error_prone_annotations
dependabot[bot] Oct 25, 2024
f94a7ef
feat: kagemomiji/airsonic-advanced#624 add BOM detection and correspo…
kagemomiji Nov 17, 2024
a9927bd
Merge remote-tracking branch 'origin/dependabot/maven/com.google.erro…
kagemomiji Nov 17, 2024
0430d67
Merge remote-tracking branch 'origin/dependabot/github_actions/aquase…
kagemomiji Nov 17, 2024
32e8524
Merge remote-tracking branch 'origin/dependabot/maven/io.fabric8-dock…
kagemomiji Nov 17, 2024
10758fb
Merge remote-tracking branch 'origin/dependabot/maven/lucene.version-…
kagemomiji Nov 17, 2024
0d745ec
Merge remote-tracking branch 'origin/dependabot/maven/com.google.guav…
kagemomiji Nov 17, 2024
08e9954
fix: kagemomiji/airsonic-advanced#624 Add method to resolve music cue…
kagemomiji Nov 17, 2024
6465e6d
chore(deps): bump com.google.errorprone:error_prone_annotations
dependabot[bot] Nov 19, 2024
64dfb6f
kagemomiji/airsonic-advanced#624 fix: Improve cuesheet parsing error…
kagemomiji Nov 20, 2024
b242de3
Merge remote-tracking branch 'origin/dependabot/maven/com.google.erro…
kagemomiji Nov 20, 2024
7cacdcf
kagemomiji/airsonic-advanced#624 fix: Enhance logging for cue sheet p…
kagemomiji Nov 20, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/trivy_scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
uses: actions/checkout@v4

- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@0.24.0
uses: aquasecurity/trivy-action@0.28.0
with:
scan-type: 'fs'
format: 'sarif'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ public class MediaFileService {

private final Map<Integer, Pair<Integer, Instant>> lastPlayed = new ConcurrentHashMap<>();

private boolean hasBOM(byte[] bom, int bytesRead) {
return bytesRead == 3 && bom[0] == (byte) 0xEF && bom[1] == (byte) 0xBB && bom[2] == (byte) 0xBF;
}

public MediaFile getMediaFile(String pathName) {
return getMediaFile(Paths.get(pathName));
}
Expand Down Expand Up @@ -1349,13 +1353,27 @@ private CueSheet getCueSheet(@Nonnull Path cueFile) {
if (cm != null && cm.getConfidence() > THRESHOLD) {
cs = Charset.forName(cm.getName());
}
LOG.debug("Detected charset for cuesheet file {}: Charset detected as {}", cueFile, cs);
bis.mark(3);

// check for BOM
byte[] bom = new byte[3];
int bytesRead = bis.read(bom, 0, 3);
if (!hasBOM(bom, bytesRead)) {
bis.reset();
}
cueSheet = CueParser.parse(bis, cs);
} catch (IOException e) {
LOG.warn("Defaulting to UTF-8 for cuesheet {}", cueFile);
}
cueSheet = CueParser.parse(cueFile, cs);
if (cueSheet.getMessages().stream().filter(m -> m.toString().toLowerCase().contains("warning")).findFirst().isPresent()) {
LOG.warn("Error parsing cuesheet {}", cueFile);
return null;
if (cueSheet != null) {
if (cueSheet.getMessages().stream().filter(m -> m.toString().toLowerCase().contains("warning"))
.map(m -> {
LOG.warn("Parsing {} at line {} : {}", cueFile, m.getLineNumber(), m.getMessage());
return m;
}).findFirst().isPresent()) {
cueSheet = null;
}
}
break;
case "flac":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,70 @@ public void testMusicCue() {
assertEquals(0.0d, track1.getStartPosition(), 0.0d);
}

@Test
public void testMusicCueWithBOM() {
LOG.info("start testMusicCueWithBOM");

// Add the "cue" folder to the database
Path musicFolderFile = MusicFolderTestData.resolveMusicCueWithBOMFolderPath();
MusicFolder musicFolder = new MusicFolder(musicFolderFile, "Cue", Type.MEDIA, true, Instant.now().truncatedTo(ChronoUnit.MICROS));
testFolders.add(musicFolder);
musicFolderRepository.saveAll(testFolders);
TestCaseUtils.execScan(mediaScannerService);

// Retrieve the "Cue" folder from the database to make
// sure that we don't accidentally operate on other folders
// from previous tests.
musicFolder = musicFolderRepository.findById(musicFolder.getId()).get();
List<MusicFolder> folders = new ArrayList<>();
folders.add(musicFolder);

// Test that the artist is correctly imported
List<Artist> allArtists = artistService.getAlphabeticalArtists(folders);
assertEquals(1, allArtists.size());
Artist artist = allArtists.get(0);
assertEquals("TestCueArtist", artist.getName());
assertEquals(1, artist.getAlbumCount());


// Test that the album is correctly imported
List<Album> allAlbums = albumService.getAlphabeticalAlbums(true, true, folders);
assertEquals(1, allAlbums.size());
Album album = allAlbums.get(0);
assertEquals("AirsonicTest", album.getName());
assertEquals("TestCueArtist", album.getArtist());
assertEquals(2, album.getSongCount());

// Test that the music file is correctly imported
List<MediaFile> albumFiles = mediaFileRepository.findByFolderAndParentPath(allAlbums.get(0).getFolder(), allAlbums.get(0).getPath(), Sort.by("startPosition"));
assertEquals(3, albumFiles.size());
MediaFile file = albumFiles.get(0);
assertEquals("airsonic-test", file.getTitle());
assertEquals("wav", file.getFormat());
assertNull(file.getAlbumName());
assertNull(file.getArtist());
assertNull(file.getAlbumArtist());
assertNull(file.getTrackNumber());
assertNull(file.getYear());
assertEquals(album.getPath(), file.getParentPath());
assertEquals(Paths.get(album.getPath()).resolve("airsonic-test.wav").toString(), file.getPath());
assertTrue(file.getIndexPath().contains("airsonic-test.cue"));
assertEquals(-1.0d, file.getStartPosition(), 0.0d);

MediaFile track1 = albumFiles.get(1);
assertEquals("Handel", track1.getTitle());
assertEquals("wav", track1.getFormat());
assertEquals(track1.getAlbumName(), "AirsonicTest");
assertEquals("Beecham", track1.getArtist());
assertEquals("TestCueArtist", track1.getAlbumArtist());
assertEquals(1L, (long)track1.getTrackNumber());
assertNull(track1.getYear());
assertEquals(album.getPath(), track1.getParentPath());
assertEquals(Paths.get(album.getPath()).resolve("airsonic-test.wav").toString(), track1.getPath());
assertNull(track1.getIndexPath());
assertEquals(0.0d, track1.getStartPosition(), 0.0d);
}

@Test
public void testMusicCueWithDisableCueIndexing() {
LOG.info("start testMusicCueWithDisableCueIndexing");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public static Path resolveMusicCueFolderPath() {
return resolveBaseMediaPath().resolve("cue");
}

public static Path resolveMusicCueWithBOMFolderPath() {
return resolveBaseMediaPath().resolve("cueBom");
}

public static Path resolveMusicDisableCueFolderPath() {
return resolveBaseMediaPath().resolve("disableCue");
}
Expand Down
13 changes: 13 additions & 0 deletions airsonic-main/src/test/resources/MEDIAS/cueBom/airsonic-test.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FILE "airsonic-test.wav" MOTOROLA
PERFORMER "TestCueArtist"
TITLE "AirsonicTest"
REM DATE 2023
REM GENRE "Classic"
TRACK 01 AUDIO
TITLE "Handel"
PERFORMER "Beecham"
INDEX 01 00:00:00
TRACK 02 AUDIO
TITLE "Jesu, Joy of Man's Desiring"
PERFORMER "Lipatti"
INDEX 01 04:01:31
Binary file not shown.
8 changes: 4 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<java.version>17</java.version>
<cxf.version>4.0.5</cxf.version>
<snakeyaml.version>2.3</snakeyaml.version>
<lucene.version>9.11.1</lucene.version>
<lucene.version>9.12.0</lucene.version>
<docker.container.repo>ghcr.io/kagemomiji/airsonic-advanced</docker.container.repo>
<docker.java.version>17.0.10_7</docker.java.version>
</properties>
Expand Down Expand Up @@ -111,7 +111,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.3.0-jre</version>
<version>33.3.1-jre</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
Expand Down Expand Up @@ -161,7 +161,7 @@
<dependency>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
<version>2.32.0</version>
<version>2.36.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
Expand Down Expand Up @@ -222,7 +222,7 @@
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.45.0</version>
<version>0.45.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down