Saturday, January 17, 2009

Extending MediaBox: The Component System Explained

I am going to write a bit about extending MediaBox with new plugins. Let's start with the basics of the component system first. I will show you some code examples in a later article.

Since version 0.96 MediaBox uses a component system for extensions. It is essential to understand this system when implementing plugins.

Components in MediaBox are independent objects connected to a message bus, where they can send messages or listen to messages from other components. Every component gets connected to the bus automatically when created. You don't have to take care about this step.

A plugin is a collection of one or more components grouped into a directory. The YouTube plugin, for instance, consists of a YouTube device component and a component for the preferences dialog.

Plugins can also add new messages to the vocabulary of messages that can be sent across the message bus.

Here's a little ASCII-art to summarize this all.

consist of connect to
Plugins -------------> Components ---------------> Message Bus
| | | |
| emit | | listen for |
| | | |
| | | |
| define v v transports |
+------------------> Messages <----------------------+


Let's take a closer look at the message stuff now.
As explained above, the vocabulary of messages that can be sent across the message bus is defined by the plugins. Most of the messages are defined by the "core" plugin (which is not really a plugin but contains many of the core components of MediaBox).

Some messages are of type event. They are used to notify other components about something that has just happened, e.g. that a new UPnP device has been discovered.
Some messages are of type action. They are used by components to trigger actions in other components.
There are also messages of type service call. While events and messages may be handled by any component that listents for these messages, a service call is only sent to one component and not visible to others. The message bus remembers which component can handle a particular service call and will route all subsequent calls for the same service to the same component again.

To sum it up with ASCII-art:

+------> Event
is either of type |
Message -------------------+------> Action
|
+------> Service Call


When a plugin defines a new message, it has to give it a name. The name is all uppercase and consists of a domain name, the message type, and some descriptive name.
The domain name helps to avoid name clashes of messages defined by different plugins. It should be the name of your plugin.
The message type tells programmers about the type of message. It is one of EV for events, ACT for actions, and SVC for service calls.

These are some examples of actual messages defined by components belonging to MediaBox:

  • CORE_EV_APP_IDLE_BEGIN (event: MediaBox is announcing to go idle in order to save battery)

  • CORE_EV_APP_IDLE_END (event: MediaBox is announcing to wake up from idle state)

  • NOTIFY_SVC_SHOW_MESSAGE (service call: show a short message)

  • HWKEY_EV_UP (event: user pressed up on the d-pad)

  • HWKEY_EV_DOWN (event: user pressed down on the d-pad)

  • HWKEY_EV_LEFT (event: user pressed left on the d-pad)

  • HWKEY_EV_RIGHT (event: user pressed right on the d-pad)

  • UI_ACT_SELECT_VIEWER (action: select a viewer)


Some messages take parameters. NOTIFY_SVC_SHOW_MESSAGE, for instance, takes as parameter the text of the message to show. Some service calls even have a return value.

These are the basics of the component system. Next time I will show you how components are integrated in MediaBox, and how to create a simple plugin.

No comments: