fossfreedom / coverart-browser

Browse your cover-art albums in Rhythmbox v2.96 - 3.0+
http://xpressubuntu.wordpress.com/
GNU General Public License v3.0
74 stars 19 forks source link

Cover Search Provider API #156

Closed fossfreedom closed 10 years ago

fossfreedom commented 11 years ago

discussion topic

Pulled from #152

re request to somehow give feedback on progress of searching and which albums did not find coverart.

Other posiblity could be to reestructurate the cover search plugin to make it usable as an standalone module/modules. This way, the plugin itself would still work as intended (it would work as a drop in replacement for the built-in one) and also provide an API that other plugins (as this one) could use directly instead of going through the cover database, to have more control on the cover search process.

Anyway, I think this particular feature should be taken aside for the moment (maybe make a separate issue to take care of it later) since it would take a good while to implement and needs to be discussed and defined with more detail before proceeding."

also

i.e. Potential extension to allow deletion of coverart

asermax commented 11 years ago

I think adding a call to clear a coverart is more work that's worth. What have been proposed is to have a way to force the search and replacement of a cover that's already on cache, which can be easily implemented if we design a different route to access to the search facilities (the API), other than the call to the covers db. I mean, why in the world would someone want to simply remove the cover? For what I understood of the discussion in the other topic, it would be always followed by a search for new covers.

fossfreedom commented 11 years ago

lets step back slightly -

My understanding of an API is some sort of shared module. Bare with me - I come from a C/C++ background not python.

In C/C++ we would have a header file with a corresponding shared object located in the filesystem. Two separate programs would include the header file in the source module and compile against the shared object library.

Lets consider python in the Peas plugin system - which I would readily say I'm fuzzy with.

Can you have this header/implementation split and if so where would we put the implementation to share between plugins?

I'm assuming not - thus is this "API" a complete python .py file that exists in both projects - or is this a .py file which will be installed somewhere in the filesystem python path which you can "import" from on both plugins?

asermax commented 11 years ago

Well, that's one big difference between compiled and interpreted languages. Actually, the strongly vs weakly typed nature of a language also plays a role in here. Since python is an interpreted (and weakly typed) language, you need not to compile it against header files to have access to a library or to another application of some sort; instead you can dinamically import any module that's already on memory or inside the python execution path. You can even dinamically add paths to the import path or open a path as a module, so the posibilities are unlimited here.

Peas makes it even easier, since it dinamically loads every plugin module that's within the plugins directories (~.local/share/rhythmbox/plugins and /usr/lib/rhythmbox/plugins), making them available to any other plugin on the same application extension context. The only thing you have to make sure is the order in which this modules are loaded, that's what the depends does on the plugin definition file.

So, there's no need of any formal definition of the API (e.g. a header defining the operations the module should have). The only thing that should be done is to reestructurate the plugin (add some calls to access specific things within the plugin, e.g a list of providers ordered by priority) and the providers modules/classes, to make them more friendly to use on other plugins.

To sum up, the API I was talking about isn't a new module; it is the same plugin but with some design changes to make it usable by other plugins.

fossfreedom commented 11 years ago

So - daft example I know ... if we wanted to fingerprint from the coverart entry view I would

from lastfm_extension/extensions.LastFMExtensionFingerprinter import Extension ?

and call the relevant API method/class - assuming that there was something to be called from that module?

Lets put this in the cover_search_providers concept.

Discogs is a provider would I similarly do

from coverart-search-provider.discogs_client import Search as discogs_search

and therefore just initialise provider = discogs_search() ?

So - each provider would need to have a method to request a cover and some-sort of custom signal which would be called when a cover is returned?

Thus on coverart_album would we just connect to that custom signal for the discogs provider?

asermax commented 11 years ago

Something among that lines, yes. The lastfm_extension example isn't quite right, because it does some dinamic loading too, and import statement doesn't allow / d:

But in the case of the cover_search_providers, it fits alright. I was thinking of a slightly different idea tho: the main plugin's module could have a method that returns a list of providers ordered by priority; this call would be used internally when doing the automatic search, and externally by other plugins that need to use the providers and want to keep the priority stablished by the user. This also abstract the providers creation, which could or could not be complicated, but that may introduce some concepts that there's no need for the API client to know. So, after calling this call, we have a list of providers and we can use them however we want.

And,

So - each provider would need to have a method to request a cover and some-sort of custom signal which would be called when a cover is returned?

yes, that's exactly it. That's what needs some thinking, designing and restructuring: defining and implementing the methods/properties/signals that have to be present on all providers to access them in a generic way.