Foobar2000:Development:Services

From Hydrogenaudio Knowledgebase
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.


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);

Examples of entrypoint services

initquit, init_stage_callback

  • Implemented by: everyone.
  • Called by: core, on app startup and shutdown.

input_entry

  • Implemented by: decoder components.
  • Called by: everyone decoding audio files.
  • This service is not implemented directly, but with help of input_factory_t<> templates that implement all input services using your supplied class.

playlist_loader

  • Implemented by: core (standard playlist format), you (if you want to add your own playlist format).
  • Called by: any code loading or saving a playlist file.

popup_message

  • Implemented by: core. Do not reimplement!
  • Called by: everyone.