Zeugma440 / atldotnet

Fully managed, portable and easy-to-use C# library to read and edit audio data and metadata (tags) from various audio formats, playlists and CUE sheets
MIT License
466 stars 63 forks source link

Incorrect Next track ID after import chapters #288

Closed sandreas closed 2 weeks ago

sandreas commented 3 weeks ago

A tone user found out, that the Next track ID is invalid after importing chapters in an m4b file, reference issue is: https://github.com/sandreas/tone/issues/51

After tagging you can check the file via:

>  mediainfo --Details=10 file_to_edit.m4b | grep "k ID"
0000094   Next track ID:                        2 (0x00000002)
00000B4    Track ID:                            1 (0x00000001)
0196850    Track ID:                            2 (0x00000002)
0196B62    Track ID:                            3 (0x00000003)

I reproduced this with the original atldotnet 6.7.0 Track class with the code below. Sample files can be downloaded from (you won't need the txt file, the code sample includes the chapters as json):

https://mega.nz/file/UiAVnKyK#A8AvSDr_k8u5LsBljLy4UmFcOCZ7-kh02LUTlLd3o-s

using ATL;
using Newtonsoft.Json;

var chaptersJson = """
                   [{"StartTime":0,"EndTime":158220,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"001","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":158220,"EndTime":1194248,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"002","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":1194248,"EndTime":2264363,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"003","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":2264363,"EndTime":3590501,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"004","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":3590501,"EndTime":5053776,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"005","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":5053776,"EndTime":6364868,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"006","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":6364868,"EndTime":6960552,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"007","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":6960552,"EndTime":7869614,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"008","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":7869614,"EndTime":8391645,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"009","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":8391645,"EndTime":8794650,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"010","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":8794650,"EndTime":9919657,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"011","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":9919657,"EndTime":10306083,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"012","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":10306083,"EndTime":10843625,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"013","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":10843625,"EndTime":11589311,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"014","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":11589311,"EndTime":12154903,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"015","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":12154903,"EndTime":12734659,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"016","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":12734659,"EndTime":14135193,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"017","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":14135193,"EndTime":14863325,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"018","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":14863325,"EndTime":15600187,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"019","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":15600187,"EndTime":16303751,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"020","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":16303751,"EndTime":17764333,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"021","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":17764333,"EndTime":18350730,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"022","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null},{"StartTime":18350730,"EndTime":19305210,"StartOffset":0,"EndOffset":0,"UseOffset":false,"Title":"023","UniqueID":"","UniqueNumericID":0,"Subtitle":"","Url":null,"Picture":null}]
                   """;

var chaps = JsonConvert.DeserializeObject<List<JsonSerializableChapterInfo>>(chaptersJson);

var originalFile = "file.m4b";
var fileToEdit = "file_to_edit.m4b";
if (File.Exists(fileToEdit))
{
    File.Delete(fileToEdit);
}
File.Copy(originalFile, fileToEdit);
var track = new Track(fileToEdit);
track.Chapters.Clear();

foreach (var chapter in chaps)
{
    track.Chapters.Add(chapter);
}

await track.SaveAsync();

return await Task.FromResult(0);

class JsonSerializableChapterInfo : ChapterInfo
{

}
Zeugma440 commented 2 weeks ago

Fixed by 63190a440cc0d892fe0d6bb48a94027b874d0387

Release should be up soon. I still have some general housekeeping to do here and there.

sandreas commented 2 weeks ago

I still have some general housekeeping to do here and there.

A few days ago I started an approach to implement my long suggested approach to an AdvancedTrack - if you are NOT interested in PRs, it would be great if you tell me beforehand :-)

I noticed, that you use a WinForms-Project to test the UI integration. This did not work on Linux. Did you look into MAUI or AvaloniaUI? Another thing I was missing was the nullable project setting (expecially T?), but this was not as important.

I hope I can support the project by submitting some code soon :-)

In case you want to keep track: https://github.com/Zeugma440/atldotnet/compare/main...sandreas:atldotnet:feature_map_field

Zeugma440 commented 2 weeks ago

A few days ago I started an approach to implement my long suggested approach to an AdvancedTrack - if you are NOT interested in PRs, it would be great if you tell me beforehand :-)

It's perfectly fine as long as you keep up with the latest commits (= no merging required on my side).

I noticed, that you use a WinForms-Project to test the UI integration. This did not work on Linux. Did you look into MAUI or AvaloniaUI?

I just needed a proof of concept to highlight how async / await are essential on UI-based apps. You can safely ignore that project when building / testing on Linux.

Another thing I was missing was the nullable project setting (expecially T?), but this was not as important.

I'll probably be switching to that for the next major version. I've been coding a lot with Kotlin lately and have grown accustomed to working with the nullable syntax 😄

I hope I can support the project by submitting some code soon :-) In case you want to keep track: https://github.com/Zeugma440/atldotnet/compare/main...sandreas:atldotnet:feature_map_field

Cheers!

Zeugma440 commented 2 weeks ago

The fix for the issue you reported has been delivered in today's v6.08

Please close the issue if it works on your side~

sandreas commented 2 weeks ago

Works as expected. Thank you very much.