Some questions re plugin development

I’ve recently developed the “Classical Extras” plugin, which has been an “interesting learning experience”. As a result I have a few questions for those with more experience.

  1. The API documentation is pretty sparse. Is there any plan to enhance this? I spent quite a bit of time scouring other plugins for clues.
  2. What has happened to the source code for Picard 1.4 - the GitHub now only seems to have 2.0? (There are 2 branches for plugins). This is important as some code has moved - it took me a while to realise that XmlNode was in webservice in 1.4 (is now in util.xml).
  3. What are the release plans for 2.0? And what does that mean for my (1.4-compatible) plugin?
  4. I would like to be able to access any existing file tags from my (track_metadata_processor) class - is there a way of doing this?
  5. How often does the “available plugins” page - https://picard.musicbrainz.org/plugins/ - get updated?

Any response on any list item gratefully received!

4 Likes

The plugin API is not well defined, in fact plugin writers tend to use whatever they want (that’s Python), which will lead to issues since the Picard code they use may not be stable.
This is why there’s a plugin API version, but imho we need a complete rework and proper documentation. Help is welcome.

We plan to release 2.0 this autumn. After the end of GSoC a beta version will be announced.
A lot of code changed compared to 1.4, and prolly even more will in near future. Picard 2 is a port of Picard 1.4 to Python3/Qt5, and a lot of code can now be simplified. Another major change is the move to json web service instead of xml.

See above for release plans.
Plugins aren’t compatible, but most will be ported. The plugin archive (zip) format will change too (manifest file instead of hacky header variables, python 3/Qt5 etc…)

You need to enable folksonomy_tags config option and then you should be able to access tags through Track.folksonomy_tags property.

It depends, that’s done manually for now, usually i do it after important changes, feel free to ping me on IRC (#metabrainz zas). It was done this morning (your plugin is available through plugin API now).
This should be improved in near future.

3 Likes

Many thanks for the comprehensive response! Only one unanswered question, I think - is there a copy of the v1.4 source somewhere? I need it while I continue to work on my plugin in branch 1.0.

The 1.4.x source is still available on GitHub, you just need to switch from master branch to the 1.4.x branch: GitHub - metabrainz/picard at 1.4.x

If you have a local clone of the repository, doing git checkout 1.4.x should switch your local copy of the code to the 1.4.x branch code.

3 Likes

I could be wrong, but I read @MetaTunes’s question as being about getting the tag fields from the local files, rather than the tags listed on the MB database, and “folksonomy” makes me think you answered the latter. Am I wrong about what either of you were saying?

You are right about my question - I was a bit puzzled by the answer, but hadn’t examined it closely. In particular, my plugin stores the options used in tags - which are then saved - and I want to be able to give the ability to read them and re-apply them on subsequent lookups. Clearly Picard does read the local file tags, but I don’t know if that can be made available to a track_metadata_processor.

I assume that the lack of replies to this indicates that it may not be possible, although I remain hopeful. As I mentioned, the main purpose of this would be to enable the user (optionally) to re-use the same Classical Extras options for a release as those which were used when it was last saved. I guess one approach is to use config.settings either as a substitute for the file tag or as a way of interfacing between the track_metadata_processor and the file operations. In the former case, it would result in Picard.ini holding a record (or dict item) for each of the user’s releases; I’m not sure whether that is wise. The latter approach requires me to get my head around how the file operations work and syncing everything, which is rather harder :pensive:

Picard reads the current tags from the file into a dictionary.
The contents of this dictionary are then used as the starting point for the metadata processor.
If you write a comment tag that has the settings you used when writing the tags you can check for this and use those settings.

Sorry if I’m being a bit dim, but I’m not sure how to access that from within my track_metadata_processor. The arguments passed to it are (album, metadata, track, release), all of which seem only to relate to the MB data, not the file data.

I think you are correct, the file metadata is not available here. The track_metadata_processor is called after data has been loaded from MB, there are no files attached to the metadata at that point. In general the track will have a list of files, and each file has metadata, but not at the time this processor gets called. That would need some sperate processor that gets called when a file gets attached to a track.

2 Likes

Actually I might be wrong. The files might be available. Have a look at the track.linked_files array.

But if at all this is only available for files matched by a lookup on first load of that album or when manually refreshing. If you attach files to the track later it is not run again.

Unfortunately that just returns an empty list.

Yes, I expected this. I think it only is filled in the manual reload case. Really a hook that gets called when matching files to tracks would be needed for your use case.

I can get the file list with
album.tagger.files
Still trying to work out how to get the metadata…

album.tagger.files will be all files loaded into Picard, not just those for the album. Not sure this will help you much.

A file has a metadata (the current metadata assigned to the file) and a orig_metadata (metadata as loaded from the file) property.

Correct. But at least I could try and match to the required album if only I can get at the metadata. Also might be able to use linked_files? At the moment, can’t get orig_metadata to work…

for file in album.tagger.files:
  orig_metadata=album.tagger.files[file].orig_metadata