Foobar2000:Development:Services
Services
A service type is an interface class, deriving directly or indirectly from service_base class. A service type class must not have any data members; it can only provide virtual methods (to be overridden by service implementation), helper non-virtual methods built around virtual methods, static helper methods, and constants / enums. Each service interface class must have a static class_guid member, used for identification when enumerating services or querying for supported functionality. A service type declaration should declare a class with public virtual/helper/static methods, and use FB2K_MAKE_SERVICE_INTERFACE() / FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT()
macro to implement standard service behaviors for the class; additionally, class_guid needs to be defined outside class declaration (e.g. const GUID someclass::class_guid = {….};
). Note that most of components will not declare their own service types, they will only implement existing ones declared in the SDK.
A service implementation is a class derived from relevant service type class, implementing virtual methods declared by service type class. Note that service implementation class does not implement virtual methods declared by service_base; those are implemented automatically.
You cannot directly instantiate a service implementation object because it's still missing virtual methods of service_base.
class myworker : public threaded_process_callback { /* threaded_process_callback methods overridden here */ }; auto obj = new myworker; // error auto obj = fb2k::service_new<myworker>(); // good service_ptr_t<myworker> obj = new service_impl_t<myworker>; // longer equivalent of fb2k::service_new<>, commonly used in older code, not auto-friendly
fb2k::service_new<> takes care of implementing common methods (service_base) needed by all services and returns an autopointer object that manages reference counting for you.
Note that service_base methods:
service_add_ref()
service_release()
service_query()
... are only intended for autopointer classes and should never be called directly in your code.
See also: Auto Pointers
Entrypoint services
An entrypoint service type is a special case of a service type that can be registered using service_factory templates, and then accessed from any point of service system (excluding DLL startup/shutdown code, such as code inside static object constructors/destructors). An entrypoint service type class must directly derive from service_base.
Registered entrypoint services can be accessed using:
- For services types with variable number of implementations registered:
enumerate()
static methods of the service class>
for( auto ptr : someclass::enumerate() ) { /* do stuff with ptr */ }
- Or,
service_enum_t<>
, commonly used in older code:
service_enum_t<someclass> e; service_ptr_t<someclass> ptr; while(e.next(ptr)) ptr->dosomething();
- For services types with a single always-present implementation registered - such as core services like playlist_manager - using someclass::get(), e.g.:
auto api = someclass::get(); api->dosomething(); api->dosomethingelse();
Using per-service-type defined static helper functions, e.g. someclass::g_dosomething()
- those use relevant service enumeration methods internally.
An entrypoint service type must use FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT()
macro to implement standard entrypoint service behaviors, as opposed to all other service types that use FB2K_MAKE_SERVICE_INTERFACE()
macro instead.
You can register your own entrypoint service implementations using FB2K_SERVICE_FACTORY()
macro. It creates a static instance of your object and makes it available for everyone else to enumerate and access.
Some services need to be registered differently, see documentation of individual services for details.
A typical entrypoint service implementation looks like this:
class myinitquit : public initquit { public: void on_init() override {}; void on_quit() override {}; }; FB2K_SERVICE_FACTORY(myinitquit);