State management

The renderers behave like state machines. Operations may or may not be valid depending on the renderer's state, or may change their behavior depending on it. For example, a STOP command may be ignored if the renderer is already stopped, but otherwise it should stop any ongoing playback.

The renderer's state machine has four states:

A renderer is Stopped if it is not playing any media. Whenever the renderer receives the order to play some media content, it moves to the Transitioning state. In this state, the renderer attempts to get anything it may need to play the selected item, for example, it may attempt to get an URI from the current item object identifier, so it can pass it to the underlying playback engine and actually start playing the content. Once the renderer has obtained the information it needs to play the media, it tries to play it. The renderer moves to the Playing state once playback has been started by the underlying playback engine. During this state, the user can issue a PAUSE command. This will make the renderer move to Paused state. Also, the user may issue a STOP command at any time, making the renderer move to the Stopped state again.

Application developers should react to state changes in the renderer and update their UIs accordingly. For example, when the renderer is in the Stopped state the UI developer may want to disable the Pause button, however if the renderer state is Playing it may be enabled.

Renderers inform about their state changes by means of the "state-changed" signal. Application developers should connect to this signal an place any state related management code there. It is also possible to query a renderer about its state by using mafw_renderer_get_status.

Here is a small code snippet illustrating these concepts:

static void
state_changed_cb(MafwRenderer *renderer, MafwPlayState state, gpointer user_data)
{
        switch (state) {
                case Playing:
                        /* Enable Pause button */
                        break;
                case Paused:
                        /* Enable Resume button */
                        break;
                case Stopped:
                        /* Disable Pause/Resume button */
                        break;
                default:
                        break;
        }
}

static void
set_state_changed_handler(MafwRenderer *renderer) 
{
        g_signal_connect(renderer, "state-changed",
                         G_CALLBACK(state_changed_cb), NULL);
}