Editing Documentation/Maemo 5 Developer Guide/Using Multimedia Components/Media Application Framework (MAFW)

Warning: You are not logged in. Your IP address will be recorded in this page's edit history.

Warning: This page is 90 kilobytes long; some browsers may have problems editing pages approaching or longer than 32kb. Please consider breaking the page into smaller sections.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 15: Line 15:
=== Pre-requisites ===
=== Pre-requisites ===
-
The examples given in this section are written in C using GLib to interact with MAFW which is built upon the <code>GObject</code> framework. The reader will need to be familiar with these subjects in order to understand these examples.
+
The examples given in this section are written in C using Glib to interact with MAFW which is built upon the <code>GObject</code> framework. The reader will need to be familiar with these subjects in order to understand these examples.
=== Examples ===
=== Examples ===
Line 41: Line 41:
MAFW is formed by the following packages:
MAFW is formed by the following packages:
-
* [http://maemo.org/packages/view/libmafw0/ MAFW Library]: The MAFW library contains the basic classes and interfaces defined in the framework. These expose the major elements of the framework, like the concepts of Extension, Source and Renderer and the APIs the developers will use to interact with them.
+
* MAFW Library: The MAFW library contains the basic classes and interfaces defined in the framework. These expose the major elements of the framework, like the concepts of Extension, Source and Renderer and the APIs the developers will use to interact with them.
* MAFW Shared: This package provides means of share components among different applications using MAFW. It implements the logic behind the wrapper objects, as well as the concept of Shared playlists. It is composed of:
* MAFW Shared: This package provides means of share components among different applications using MAFW. It implements the logic behind the wrapper objects, as well as the concept of Shared playlists. It is composed of:
-
** [http://maemo.org/packages/view/libmafw-shared0/ libmafw-shared]: A library to use the shared components exposed by sharing services (extensions and shared playlists).
+
** libmafw-shared: A library to use the shared components exposed by sharing services (extensions and shared playlists).
-
** [http://maemo.org/packages/view/mafw-dbus-daemon/ mafw-dbus-wrapper]: This service is the one responsible for loading extensions in separate processes and export their interfaces as [[Documentation/Maemo 5 Developer Guide/DBus|D-Bus]] services. These services are used by the wrapper objects defined in <code>libmafw-shared</code> in the out-of-process use case.
+
** mafw-dbus-wrapper: This service is the one responsible for loading extensions in separate processes and export their interfaces as D-BUS services. These services are used by the wrapper objects defined in libmafw-shared in the out-of-process use case.
-
** [http://maemo.org/packages/view/mafw-playlist-daemon/ mafw-playlist-daemon]: A daemon that provides an API for shared playlist manipulation and storage.
+
** mafw-playlist-daemon: A daemon that provides an API for shared playlist manipulation and storage.
* Extensions: Extensions are provided as separate packages.
* Extensions: Extensions are provided as separate packages.
=== Getting started ===
=== Getting started ===
-
MAFW is available as Debian packages, so it can be installed using tools like <code>dpkg</code> or <code>apt</code>.
+
MAFW is available as Debian packages, so it can be installed using tools like dpkg or apt.
MAFW can also be built from source. To build and install a MAFW package from source, move to the root directory of the source and build a MAFW package:
MAFW can also be built from source. To build and install a MAFW package from source, move to the root directory of the source and build a MAFW package:
Line 60: Line 60:
</pre>
</pre>
-
When building from source, one can also pass certain flags to the <code>autogen.sh</code> script. Check the <code>configure.ac</code> file for a list of available build flags for the module. Common and useful supported flags among all MAFW packages are:
+
When building from source, one can also pass certain flags to the autogen.sh script. Check the <code>configure.ac</code> file for a list of available build flags for the module. Common and useful supported flags among all MAFW packages are:
* <code>--prefix=PATH</code>, installs MAFW files into <code>PATH</code>.
* <code>--prefix=PATH</code>, installs MAFW files into <code>PATH</code>.
Line 119: Line 119:
====Loading out-of-process extensions====
====Loading out-of-process extensions====
-
As we already pointed out, with the out-of-process approach, extensions are loaded by the <code>mafw-dbus-wrapper</code> in a separate address space and they are shared by all applications, which use these extensions through D-Bus services. In order to use these out-of-process extensions, the first step is to discover their availability via the bus. This is done by invoking <code>mafw_shared_init</code> after getting a reference to the registry object with <code>mafw_registry_get_instance</code>. Once the discovery has been started, your application will be notified of newly available extensions through signals. Likewise, when a certain extension is no longer available, a signal is sent to the application so that it can properly handle this.
+
As we already pointed out, with the out-of-process approach, extensions are loaded by the mafw-dbus-wrapper in a separate address space and they are shared by all applications, which use these extensions through D-Bus services. In order to use these out-of-process extensions, the first step is to discover their availability via the bus. This is done by invoking mafw_shared_init after getting a reference to the registry object with <code>mafw_registry_get_instance</code>. Once the discovery has been started, your application will be notified of newly available extensions through signals. Likewise, when a certain extension is no longer available, a signal is sent to the application so that it can properly handle this.
The <code>MafwRegistry</code> object is a singleton instance where all the available extensions are registered. It provides an interface for application developers to access the available sources and renderers. In the case of out-of-process extensions, the registry will provide proxies to the actual remote extensions that handle the D-Bus communications transparently for you.
The <code>MafwRegistry</code> object is a singleton instance where all the available extensions are registered. It provides an interface for application developers to access the available sources and renderers. In the case of out-of-process extensions, the registry will provide proxies to the actual remote extensions that handle the D-Bus communications transparently for you.
Line 169: Line 169:
Because the playlists are always remote objects stored and handled by a separate process, whenever the application needs to deal with a playlist, there is a need for inter-process communication. However the communication is hidden from developers by using a proxy object. These proxy objects allow developers to interact with the playlists as if they were local objects, making the underlying communications with the playlist daemon transparent for the application developer.
Because the playlists are always remote objects stored and handled by a separate process, whenever the application needs to deal with a playlist, there is a need for inter-process communication. However the communication is hidden from developers by using a proxy object. These proxy objects allow developers to interact with the playlists as if they were local objects, making the underlying communications with the playlist daemon transparent for the application developer.
-
Operations like creating or removing a playlist or obtaining the list of available playlists, are done through the <code>MafwPlaylistManager</code> object. This object acts as a proxy of the playlist daemon for playlist-related operations that do not deal with a particular playlist. A reference to this object can be obtained using <code>mafw_playlist_manager_get</code>.
+
Operations like creating or removing a playlist or obtaining the list of available playlists, are done through the MafwPlaylistManager object. This object acts as a proxy of the playlist daemon for playlist-related operations that do not deal with a particular playlist. A reference to this object can be obtained using <code>mafw_playlist_manager_get</code>.
The following sections explain how to use the <code>MafwPlaylistManager</code> and proxy playlist objects in more detail.
The following sections explain how to use the <code>MafwPlaylistManager</code> and proxy playlist objects in more detail.
Line 183: Line 183:
Although new playlists can be used right away after calling <code>mafw_playlist_manager_create_playlist</code>, it is better to handle newly created playlists through the <code>playlist-created</code> callback, because this will work also for playlists created by other MAFW-based applications.
Although new playlists can be used right away after calling <code>mafw_playlist_manager_create_playlist</code>, it is better to handle newly created playlists through the <code>playlist-created</code> callback, because this will work also for playlists created by other MAFW-based applications.
-
It is possible to import an existing playlist file or the contents of a particular container of a source extension as a MAFW playlist with the help of <code>mafw_playlist_manager_import</code>. If this method is passed a URI as parameter, it will try to parse the file pointed by that URI and populate a playlist with the entries of the playlist file. Likewise, if a source object identifier is used instead of a URI, and it points to a valid source container, the container will be browsed, and the contents will be used to populate the playlist. If the object identifier points to a single media item instead of a container, the associated media will be treated as a playlist file, parsing the file it points to and adding its entries to the playlist.
+
It is possible to import an existing playlist file or the contents of a particular container of a source extension as a MAFW playlist with the help of <code>mafw_playlist_manager_import</code>. If this method is passed a URI as parameter, it will try to parse the file pointed by that URI and populate a playlist with the entries of the playlist file. Likewise, if a source object identifier is used instead of a URI, and it points to a valid source container, the container will be browsed, and the contents will be used to populate the playlist. If the object identifier points to a single media item instead of a container, the associated media will be treated as as a playlist file, parsing the file it points to and adding its entries to the playlist.
After a playlist has been imported, the framework will invoke the callback passed as parameter to <code>mafw_playlist_manager_import</code>, with a reference to the imported playlist proxy object. The name of the playlist will be the URI pointing to the file, or the source container title. If a playlist with this name existed already, then a number will be added after the name as a suffix to ensure a unique name is assigned. After this, the <code>MafwPlaylist::playlist-created</code> signal will be emitted.
After a playlist has been imported, the framework will invoke the callback passed as parameter to <code>mafw_playlist_manager_import</code>, with a reference to the imported playlist proxy object. The name of the playlist will be the URI pointing to the file, or the source container title. If a playlist with this name existed already, then a number will be added after the name as a suffix to ensure a unique name is assigned. After this, the <code>MafwPlaylist::playlist-created</code> signal will be emitted.
Line 247: Line 247:
=== Sources ===
=== Sources ===
-
This section explains how to use sources in a program. During this explanation it is recommended to follow the [[#Source browse example|source browse example]] and the [[#Source metadata example|source metadata example]] for complete source code examples illustrating most of the concepts explained below.
+
This section explains how to use sources in a program. During this explanation it is recommended to follow sections [[#Source browse example]] and [[#Source metadata example]] for complete source code example illustrating most of the concepts explained below.
====Introduction====
====Introduction====
Line 306: Line 306:
* Metadata, the metadata values associated to the current item.
* Metadata, the metadata values associated to the current item.
* User Data, user data of the callback.
* User Data, user data of the callback.
-
* Error, a <code>GError</code> that, if set, informs of an error in the browse operation.
+
* Error, a GError that, if set, informs of an error in the browse operation.
Also, in case that no results match the browse operation, the callback is invoked once, with the object ID parameter set to <code>NULL</code>.
Also, in case that no results match the browse operation, the callback is invoked once, with the object ID parameter set to <code>NULL</code>.
Line 332: Line 332:
====Using a source====
====Using a source====
-
Sources are extensions, therefore, the first step is to obtain a reference to them using the framework registry. Please see the section on [[#Loading extensions|loading extensions]] for more information on this topic.
+
Sources are extensions, therefore, the first step is to obtain a reference to them using the framework registry. Please check section [localhost#sec:mafw_loading_extensions 8.5.2] for more information on this topic.
Once a reference to the source of interest has been obtained, the developer can start to use it. The way sources are used is usually this:
Once a reference to the source of interest has been obtained, the developer can start to use it. The way sources are used is usually this:
Line 341: Line 341:
* The user can also request more metadata from a specific item obtained in the browse operation, to do so, the developer should use <code>mafw_source_get_metadata</code> passing the Object ID of the selected item.
* The user can also request more metadata from a specific item obtained in the browse operation, to do so, the developer should use <code>mafw_source_get_metadata</code> passing the Object ID of the selected item.
-
For more information about the source API, please check the MAFW API reference. The reader can also check the [[#Source browse example|source browse example]] and the [[#Source metadata example|source metadata example]].
+
For more information about the source API, please check the MAFW API reference. The reader can also check complete source code examples in sections [localhost#sec:mafw_examples_source_browse 8.5.3] and [localhost#sec:mafw_examples_source_metadata 8.5.3].
=== Renderers ===
=== Renderers ===
Line 353: Line 353:
<code>MafwRenderer</code> is a subclass of <code>MafwExtension</code>, so, it inherits its semantics. Thus, renderers have <code>name</code>, <code>uuid</code> and <code>plugin</code> properties and support run-time properties too. This class is intended to be an abstract base class for any renderer and it provides various playback-related operations: <code>mafw_renderer_play</code>, <code>mafw_renderer_stop</code>, <code>mafw_renderer_pause</code>, <code>mafw_renderer_resume</code>, etc. that any application can use to control media playback in a particular renderer.
<code>MafwRenderer</code> is a subclass of <code>MafwExtension</code>, so, it inherits its semantics. Thus, renderers have <code>name</code>, <code>uuid</code> and <code>plugin</code> properties and support run-time properties too. This class is intended to be an abstract base class for any renderer and it provides various playback-related operations: <code>mafw_renderer_play</code>, <code>mafw_renderer_stop</code>, <code>mafw_renderer_pause</code>, <code>mafw_renderer_resume</code>, etc. that any application can use to control media playback in a particular renderer.
-
An application can assign a playlist to a renderer. When this is done, the renderer will take over the responsibility for managing it properly, saving some effort from the application developer. For example, the renderer can detect an "end of stream" situation and move automatically to the next item in the playlist, it can readjust automatically when the playlist is being edited, rewind the playlist automatically when the end of the playlist has been reached or even restart playback if the user has enabled the repeat mode in the playlist.
+
An application can assign a playlist to a renderer. When this is done, the renderer will take over the responsibility for managing it properly, saving some effort to the application developer. For example, the renderer can detect an "end of stream" situation and move automatically to the next item in the playlist, it can readjust automatically when the playlist is being edited, rewind the playlist automatically when the end of the playlist has been reached or even restart playback if the user has enabled the repeat mode in the playlist.
The application can also control playlist playback, commanding the renderer to move to any item in the playlist at any moment.
The application can also control playlist playback, commanding the renderer to move to any item in the playlist at any moment.
Line 382: Line 382:
In order to play content in a renderer, a playlist should be created and assigned to it. For this purpose developers have to use <code>mafw_renderer_assign_playlist</code>. Once a playlist has been assigned to the renderer the user may choose to start playback right away (starting from the first item in the playlist) or choose a specific item to start from. For the latter case, the renderer offers the methods <code>mafw_renderer_next</code>, <code>mafw_renderer_previous</code> and <code>mafw_renderer_goto_index</code>, that allow the user to select the next and previous items to the one currently selected or move directly to a particular item in the playlist. Also, the currently selected media may change due to other factors, for example, when playback of the current item in the playlist finishes the renderer will move to the next automatically, it might also happen in the case of errors that do not allow to play the current item, in this scenario the renderer may choose to automatically move to the next item in the playlist too.
In order to play content in a renderer, a playlist should be created and assigned to it. For this purpose developers have to use <code>mafw_renderer_assign_playlist</code>. Once a playlist has been assigned to the renderer the user may choose to start playback right away (starting from the first item in the playlist) or choose a specific item to start from. For the latter case, the renderer offers the methods <code>mafw_renderer_next</code>, <code>mafw_renderer_previous</code> and <code>mafw_renderer_goto_index</code>, that allow the user to select the next and previous items to the one currently selected or move directly to a particular item in the playlist. Also, the currently selected media may change due to other factors, for example, when playback of the current item in the playlist finishes the renderer will move to the next automatically, it might also happen in the case of errors that do not allow to play the current item, in this scenario the renderer may choose to automatically move to the next item in the playlist too.
-
No matter the reason that has triggered a change in the current media selected in the renderer, it will notify the application about the change by emitting a <code>MafwRenderer::media-changed</code> signal. Application developers should connect to this signal to update the application accordingly whenever new media is selected in the renderer. It is also possible to query a renderer about its current media by using <code>mafw_renderer_get_status</code>.
+
No matter the reason that has triggered a change in the current media selected in the renderer, it will notify the application about the change by emitting a MafwRenderer::media-changed signal. Application developers should connect to this signal to update the application accordingly whenever new media is selected in the renderer. It is also possible to query a renderer about its current media by using <code>mafw_renderer_get_status</code>.
====Error management====
====Error management====
Line 392: Line 392:
====Using a renderer====
====Using a renderer====
-
Renderers are extensions, therefore, the first step is to obtain a reference to them using the framework registry. Please check the section on [[#Loading extensions|loading extensions]] for more information on this topic.
+
Renderers are extensions, therefore, the first step is to obtain a reference to them using the framework registry. Please check section [localhost#sec:mafw_loading_extensions 8.5.2] for more information on this topic.
Once a reference to a renderer has been obtained, the next step is to assign a playlist to it with <code>mafw_renderer_assign_playlist</code>. And start playing at any moment using <code>mafw_renderer_play</code>. From that moment on, other playback control functions like <code>mafw_renderer_pause</code> or <code>mafw_renderer_stop</code> can also be used.
Once a reference to a renderer has been obtained, the next step is to assign a playlist to it with <code>mafw_renderer_assign_playlist</code>. And start playing at any moment using <code>mafw_renderer_play</code>. From that moment on, other playback control functions like <code>mafw_renderer_pause</code> or <code>mafw_renderer_stop</code> can also be used.
Line 654: Line 654:
===Source browse example ===
===Source browse example ===
-
This program is a simple command line program that allows the user to browse the contents of arbitrary containers of the local filesystem source using the <code>mafw-tracker-source</code> plugin. So, be sure you have this plugin installed (and running if you want to use it in out-of-process mode)! <br /><br /><br />'''To build the example''': Source browse example
+
This program is a simple command line program that allows the user to browse the contents of arbitrary containers of the local filesystem source using the mafw-tracker-source plugin. So, be sure you have this plugin installed (and running if you want to use it in out-of-process mode)! <br /><br /><br />'''To build the example'''<nowiki>: </nowiki>Source browse example
<pre>
<pre>
Line 1,040: Line 1,040:
  run-standalone.sh ./mafw-metadata-example <object-id>
  run-standalone.sh ./mafw-metadata-example <object-id>
-
A valid object identifier can be obtained using the browse example, by browsing the all songs container (<code>localtagfs::music/songs</code>), and checking the object identifiers of the contained songs.  
+
A valid object identifier can be obtained using the browse example, by browsing the all songs container (localtagfs::music/songs), and checking the object identifiers of the contained songs.  
'''The source code''': Source metadata example
'''The source code''': Source metadata example
Line 1,758: Line 1,758:
=== Renderer example===
=== Renderer example===
-
This program is a simple command line program that allows the user to play arbitrary playlists in a renderer. It is necessary to have the <code>mafw-gst-renderer</code> plugin installed (and running in case you intend to run the program in out-of-process mode) in order to execute the program successfully.
+
This program is a simple command line program that allows the user to play arbitrary playlists in a renderer. It is necessary to have the mafw-gst-renderer plugin installed (and running in case you intend to run the program in out-of-process mode) in order to execute the program successfully.
'''To build the example''': Renderer example
'''To build the example''': Renderer example

Learn more about Contributing to the wiki.


Please note that all contributions to maemo.org wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see maemo.org wiki:Copyrights for details). Do not submit copyrighted work without permission!


Cancel | Editing help (opens in new window)