Tags with multiple values - #527
Conversation
|
Thanks for the fireworks 😊. I've implemented genre lists for all formats and it seems to work smoothly. Eeven for APE tags he tests work fine. Do you know why? I also started work on refactoring the image storage, with the goal to support multiple covers with descriptions. As for the questions
I think we should restrict ourselves to what is needed or actually requested from users. So I think at the moment genres and images should suffice.
Did not think of this initially but I'm working on it.
I agree.
Again, I agree. When we start using the list interface in other parts of beets we should try to avoid the singular property by all means and let the caller handle any kind of normalization. We can then deprecate singular access.
I'm not quite sure what you have in mind. If you want to persist lists as comma separated values, then obtaining the list would involve some custom (de)serialization logic. I don't think that's a viable option. I could imagine that storing text data as null-separated strings in the database might work. |
|
There is a new feature in town 👢. With 1f01997 media files are only written it the tags actually change |
Looking closer at the implementation, it looks like Mutagen will transparently insert null bytes to separate lists in APE tags. So we may need to be careful here about stripping these when accessing the plain
That sounds reasonable. FWIW, #505 notes that artist (and mb_artistid) could also benefit from multiple values.
Cool. We can also take care of album art fields in a future update too (if you want to just focus on the core functionality for now).
Sounds good. Let's worry about this later, though, and focus on the MediaFile stuff in this PR.
You're right; that proposal didn't really make sense. 😃 |
Mutagen already does this for us.
For the artist field this is a bit tricky since musicbrainz uses join phrases to generate a string for display; mb_artistid should work though. The composer field would be easier to handle. However right now i think we should add list fields only if code actually uses them. Otherwise we might get bloated code that is not usable.
I migrated the I also removed the LazySave feature which sure belongs in a separate PR. I will open it as soon as this PR is merged as the feature depends on the rewritten unittests. If there are no objections I think we are ready to merge this! |
|
All sounds good, and the PR is looking great! I agree that this is ready to merge. Would you mind, however, if we held off until after the 1.3.3 release? There are already lots of changes in this release and I'd like to finish things off and get it out the door in the next couple of days. If we can avoid rocking the boat with another major refactoring until after then, I think we can give this feature the love that it needs. I'll try to redouble my efforts to get 1.3.3 finished as soon as possible. |
That's fine by me. |
|
Merged for v1.3.4! Thanks again for all your effort on this. Here's what's still on my to-do list in this department:
I'll hack away on both of these over the next week or so. |
This script documents and verifies that MediaFile library already supports the genres field without requiring any changes. The script confirms: - MediaFile has supported genres since 2014 (PR beetbox#527) - Both reading and writing multiple genre tags works - All audio formats are supported (MP3, FLAC, M4A, etc.) - Our patch only adds beets-side support, not MediaFile changes This serves as documentation that no external library changes are needed.
These are first steps towards multivalued tags (see #505). As of now, the branch includes
StorageStyleimplementationIt does not break the current Mediafile API. It also doesn't interface the additions with other parts of beets*, e.g. the library.
Rationale
Lists are of prime importance for genres (see #119, #437). In addition, there are several fields not currently in the beets core that would benefit from lists. Most specifically MusicBrainz relations like "performer", "composer", etc.
I am pretty sure there are many more use cases out there and I would be glad to hear about them to inform the implementation.
Storing Lists in Tags
I am not yet sure how to implement this and there are many points that factor into the decision. Comments are highly appreciated.
As an example, I implemented genre lists for MP3 files. There is a new
genresproperty in theMediaFileAPI. It allows for getting and setting lists of genres. Tests can be found in theMP3Testclass. At the moment we use0x00seperated strings to store lists (see below).List of tags for ID3
ID3 has two different ways of storing lists. First, text frames (frames whose identifier starts with "T", excluding "TXXX", see Frames,4.2) may contain lists of strings seperated by the terminal character of the encoding (
0x00for UTF8). Secondly, there are several frames that can appear multiple times, but have to be unique up to an additional parameter (e.g. description for "TXXX"). This restricts storing lists severly.I know how mutagen handles this so writing code for this should not be an issue.
List of tags for VorbisComment
Storing lists is well defined for Vorbis comments. In fact storing single values is just a special case of storing a list with one element. Hence, we also should expect no issues here.
Other Formats
I have not yet looked into other tagging schemes. Any input would be appreciated.
Implementation details
Test refactoring
The tests in
test_mediafile_basic.pywere refactored to be more manageable. Each file type has its own test case with some general tests mixed in fromReadWriteTestBaseand possiblyPartialTestMixin. I also added more files with empty tags to test against.Mediafile refactoring
Previously, all the code responsible for interacting with mutagen was contained in the
MediaFieldclass. This was moved into theStorageStyleclass. Then, instead of checking fields likestyle.id3_desc, I used subclasses to implement the file type specific behaviour. I am not sure whether this refactoring did change the behaviour. If so, this is not covered by the test cases. Help in spotting bugs would be appreciated.