Recently, I’ve been looking forward to create some plugins for Picard to supercharge my tagging setup. Now since the plugin APIs are barely documented, I tried to make sense of the whole thing by going through some other plugins and the threads tagged with
picard-plugin-development. This brings me to my queries that probably haven’t been answered publicly unless I missed some stuff.
- How do I offload blocking tasks off of the UI thread but be able to receive the changes within Picard? Is it not possible at all since the ReplayGain plugin mentioned here cites that as one of the issues of the plugin. Under the same thread Sophist mentions:
Instead the plan is to use ffmpeg to calculate the actual values and return them to Picard, which will put them into metadata waiting for a save.
I’m curious as to how that would work, using Python bindings for FFMPEG? Even then, there can be things that are native within the Picard plugin ecosystem itself (Dynamic range calculation, for example), but are heavy enough to block the UI thread and make Picard unresponsive. I’m looking for a way around that.
In reference to the last question, I want to use the
requestslibrary for certain plugins instead of Picard’s own WS API. (My Picard is installed using
pip) I’m trying to avoid using
requestsas much as possible but do keep in mind that a lot of the existing API wrappers use
requestsfor their WS and rewriting them from scratch is pretty much re-inventing the wheel. Here’s the dilemma: if I want to make a request that does extra optional queries based on the response of the previous queries, is my only option to keep on tacking separate functions as the callback for
tagger.webservice.get? Here’s something I already made using the template of the “Album Artist Website” plugin.
The only saving grace here is that each area query is structurally the same, so I was able to call the same methods in a cycle. But in future, I’m bound to expect conditional queries that have different structures (host/port/path) and I am wondering if there is a better way to streamline everything.
requestsmakes the code readable but I don’t want to block the UI.
In reference to the “Album Artist Website” plugin, in what cases would we use
register_track_metadata_processorand what other cases warrant
register_album_metadata_processor? An album artist is common to all the tracks in the album, so it made more sense intuitively for me to use
register_album_metadata_processor. But as I can see in the plugin mentioned above, the track API was used instead. If the data was found in the cache, it returned that to the track metadata immediately. But if it had to be fetched, it got the last track object and sent it to function that called the WS API. I’m still hazy on the details of the inner workings:
- Why was
add_artist_website()called for every track? If so, then would I be able to pass track metadata along the functions instead of creating a queueing mechanism? (Only asking as a question, doing so would probably result in lower code legibility)
- What’s the purpose of
album._requests += 1or
album._requests -= 1? My UI status bar does not increase the web request number even when this is kept. (I’m aware that the object is a tagger object)
- What’s the purpose of
track.iterfiles(True)and applying a separate file metadata in addition to the track metadata? Why was it not used when the data was fetched from the cache?
- Can I achieve granular control over plugin priorities without merging multiple plugins with different purposes into the same plugin?
HIGHare not enough to meet the order in which I want the plugins to execute reliably.
Thanks in advance. I’m aware that these are a ton of questions, but the Picard plugin creator community is so niche that I couldn’t find answers through searching.