Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Components using other components? (Read 3901 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Components using other components?

I'm writing a component that does quite a lot of stuff (specifically, I'm writing my own version of foo_softplaylists, which queries last.fm and matches the results against the local library as best it can). I think part of that stuff will be useful in and of itself (the part that finds the best version of a track), and may also be useful to other components (such as an XSPF playlist loader which would need to fuzzily match tracks), so I would like to separate it out (the fuzzy matching stuff) into its own component, and have the others use it. It's not purely algorithmic (there are some settings that control how the user would like the matching to be done) so it should definitely be a component rather than just a header file that each component can include.

My question is: how do I go about doing this? I know components like ColumnsUI exist that other components can 'plug in' to, which must be exposing some API, but I've no idea how the foobar API wants me to do that. I also have no idea what the policy on component dependencies is, and if there's any facility in foobar to ensure that users have dependent components. Any pointers would be greatly appreciated.

Components using other components?

Reply #1
You provide functionality to other components the same way the core and things like Columns do it, by exposing services.

I would strongly recommend against doing this unless you've got a real need to do this, as users will end up mismatching your components. I did this with early releases of foo_wave_seekbar, which has a companion foo_wave_cache component that handled the scanning and storage of waveforms, while the display component was just the UI bits and bobs. My competent testers constantly screwed this up to the grade that I realized that it would be completely unfeasible to release such an elegant scheme to the world.

Note that you shall not have more than one component DLL in a component archive, if you've got multiple components they shall be delivered in multiple fb2k-component archives. It's fine to bundle support files and libraries, but it's verboten to bunch up components.
Stay sane, exile.

Components using other components?

Reply #2
I'm writing a component that does quite a lot of stuff (specifically, I'm writing my own version of foo_softplaylists, which queries last.fm and matches the results against the local library as best it can). I think part of that stuff will be useful in and of itself (the part that finds the best version of a track), and may also be useful to other components (such as an XSPF playlist loader which would need to fuzzily match tracks)

If this is productive process, why are you doing it if such component exists?

I may drop two things out of space:

1. I have no idea what it takes, but make XSPF native to foobar, in a manner that I can double click XSPF playlist file and foobar will understand it

2. foo_softplaylist XSPF reader doesn't understand url links, maybe you can enhance it trivially like that, and overcome need of foo_xspf component

Of course these are not demands, but I can't see why you want to do something that already works

Components using other components?

Reply #3
My question is: how do I go about doing this? I know components like ColumnsUI exist that other components can 'plug in' to, which must be exposing some API, but I've no idea how the foobar API wants me to do that.
You define a service interface with a corresponding GUID. You need to provide the header files (and some static libraries for the GUIDs) to other components. You can take the foobar2000 SDK itself or the Columns UI SDK as examples. You should also provide documentation if you want to provide an official API to your component. Interface versioning works pretty much the same way as Microsoft COM. If you change the interface you have to change the GUID as service binding at runtime uses only the GUID. Otherwise bad things are bound to happen.

I also have no idea what the policy on component dependencies is,
The good part: you are free to plug into any component that exposes an official API. Using undocumented, reverse-engineered interfaces if frowned upon (at the least).

and if there's any facility in foobar to ensure that users have dependent components.
The bad part: there is no such facility. As Zao pointed out it is all up to the user to ensure a correct setup. As developer you can only build safety checks against missing dependencies.

Components using other components?

Reply #4
You would also have to be careful of not relying on any particular initialization order of your components. There's intentional randomization of such things to avoid accidental reliance on such.
Stay sane, exile.

Components using other components?

Reply #5
Wow, flood control is annoying. I understand not allowing people to post too often but I should at least be allowed to start writing my reply... Anyway...

I would strongly recommend against doing this unless you've got a real need to do this, as users will end up mismatching your components. I did this with early releases of foo_wave_seekbar, which has a companion foo_wave_cache component that handled the scanning and storage of waveforms, while the display component was just the UI bits and bobs. My competent testers constantly screwed this up to the grade that I realized that it would be completely unfeasible to release such an elegant scheme to the world.


Point very much taken. I suppose you then have to start dealing with versioning, and what happens when you have two components installed that each depend on different versions of the same component, which could only be suitably resolved by foobar having some system to deal with that, which is an unrealistic ask. I'll grit my teeth and stick them all in the same component

If this is productive process, why are you doing it if such component exists?


Because it doesn't quite do what I want, and the author seems to have dropped off the face of the internet. I asked to get the source (a few times) to save me some work but I got no reply. It doesn't seem like a huge component anyway so I thought I'd give it a bash.

1. I have no idea what it takes, but make XSPF native to foobar, in a manner that I can double click XSPF playlist file and foobar will understand it

2. foo_softplaylist XSPF reader doesn't understand url links, maybe you can enhance it trivially like that, and overcome need of foo_xspf component


This thread was really just a technical question about authoring components but I'll answer briefly since you seem interested: 1 seems like a nice enough feature. I'll see what it takes and add it if it's easy. If not, I'll be making source available so someone else can add it if they're interested enough. 2 is pretty trivial, I'll definitely give that a go.

You define a service interface with a corresponding GUID. You need to provide the header files (and some static libraries for the GUIDs) to other components. You can take the foobar2000 SDK itself or the Columns UI SDK as examples. You should also provide documentation if you want to provide an official API to your component. Interface versioning works pretty much the same way as Microsoft COM. If you change the interface you have to change the GUID as service binding at runtime uses only the GUID. Otherwise bad things are bound to happen.

The good part: you are free to plug into any component that exposes an official API. Using undocumented, reverse-engineered interfaces if frowned upon (at the least).

The bad part: there is no such facility. As Zao pointed out it is all up to the user to ensure a correct setup. As developer you can only build safety checks against missing dependencies.


Awesome, thanks for the detailed information! That's just what I was looking for.

You would also have to be careful of not relying on any particular initialization order of your components. There's intentional randomization of such things to avoid accidental reliance on such.


Point taken, though in this case the only use of the shared component would be on demand (not on initialisation), so I imagine it would be safe, even without safety checks.

Thanks guys