![]() |
![]() |
![]() |
![]() |
The MME Bluetooth devices. This section describes how to integrate Bluetooth devices into the MME, and provides some basic information about accessing Bluetooth device functionality through the MME:
![]() |
For information about how to get configuration values from a Bluetooth device, see “Getting and setting external device options” in the chapter External Devices, CD Changers and Streamed Media. |
The MME uses the io-fs-media interface to control playback on remote devices. This interface permits device agnostic playback control and metadata extraction, and lets the MME control playback without detailed knowledge of the underlying device.
To control Bluetooth audio devices, the MME uses the MediaFS interface provided by io-fs-media.
The MME uses the io-fs interface to control a Bluetooth audio device.
See also io-fs-media in the MME Utilities Reference.
To use Bluetooth devices with the MME you must integrate them into the MME. This integration requires three tasks:
![]() |
You should be familiar with the QNX MediaFS (Media File System) Specification before starting work on integrating Bluetooth devices into the MME. If you do not have the latest MediaFS specification, contact your QNX representative. |
The Aviage Bluetooth Integration Kit provides the resource manager framework required for representing Bluetooth devices via io-fs-media. This resource manager provides the ability to load user-created modules that uses the MediaFS specification to describe devices.
Access to a control device is specific to that device and depends on how the device is represented by the system. The access interface can be via any of:
![]() |
You can also create your own resource manager to represent Bluetooth devices, following the MediaFS specification. |
To facilitate development of new io-fs-media AVRCP modules describing Bluetooth devices, the Aviage Bluetooth Integration Kit includes an io-fs-media module example that implements the Bluetooth AVRCP (Audio/Video Remote Control Profile).
This example contains the complete framework required for io-fs-media modules that describe devices. You only need to modify device-specific sections to change the module so that it can access your required underlying control devices.
![]() |
Before compiling and using the sample io-fs-media module example that implements the Bluetooth AVRCP, you must:
|
The io-fs-media AVRCP module is a plugin to the io-fs-media resource manager. When io-fs-media with an AVRCP module is started, it:
When it learns of a remote device, the io-fs-media resource manager registers a path, called the mountpoint, to the location of MediaFS filesystem. The default mountpoint used by the module provided with the Aviage Bluetooth Integration Kit is /fs/avrcp0. When you have configured the MCD, it will monitor the system for this path. See “Modifying the MCD configuration file for Bluetooth” below.
The io-fs-media MediaFS module hierarchy
Since the io-fs-media AVRCP module implements only a subset of the MediaFS filesystem hierarchy, the only item at this path is the .FS_info. directory.
The .FS_info. directory contains MediaFS entries used for playback control and device information extraction. The directory for the io-fs-media AVRCP module contains only the info.xml file. The first request to read the info.xml file causes avrcp_getinfo() function to populate the file's contents.
All playback and metadata extraction messages are issued through an open file descriptor to the info.xml file. These are handled by the function avrcp_devctl(). This function and other major functions in avrcpexample.c are described below. For more detailed information about these and other functions in avrcpexample.c, see the source file.
The avrcp_devctl() function is the workhorse for all device control messages. It translates MediaFS playback and metadata extraction commands, then transmits them to the remote device. All commands handled by the avrcp_devctl() function require the addition of device-specific control code to the io-fs-media module example.
See “Configuring the MME for Bluetooth support” for more information about available commands.
The avrcp_mount() function is the entrance point for the io-fs-media module. It allocates memory associated to the driver. After allocating memory and registering internal functions, avrcp_mount() enables a timer that handles polling for remote device insertions and removals.
You can modify the structure avrcp_device defined in the avrcpexample.h header file to store user data that persists for a mount period.
The avrcp_options() function passes arguments to the driver at the io-fs-media interface. The io-fs-media module example includes the following set of options:
The function avrcp_timer() is used to detect the presence of a remote device to mount and register its path. To use this function you must add device-specific code to the io-fs-media module that will communicate the presence of a remote device so that it can be mounted.
Because the mountpoint for the io-fs-media module can be registered and unregistered, if a remote device is present and available to play, avrcp_timer() registers its mount path. If the remote device is removed from the system, avrcp_timer() unregisters the mount path.
The mount process has two stages:
If the resource manager or the AVRCP controller is unavailable, the io-fs-media module uses the avrcp_timer() function's “poll” until it detects that the required resource is available for mounting.
The poll rate is set by the user in the configuration options. See above.
The avrcpexample.h defines the structure avrcp_device and several constants used by the io-fs-media AVRCP module.
#include <inttypes.h> #include "media.h" #define AVRCP_NAME "AVRCP" #define NAME_BUF_SIZE 512 #define AVCP_METADATA_MAX 1024 struct avrcp_device { struct mediafsdevice mediafs; char * devpath; int fd; char dname[AVCP_METADATA_MAX]; char dserial[AVCP_METADATA_MAX]; uint16_t verbose; };
The structure avrcp_device is the principle AVCP device structure. It is defined in the avrcpexample.h header file and carries information about these devices. It can be extended to hold data about an underlying device. Its standard members include:
Member | Type | Description |
---|---|---|
mediafs | struct mediafsdevice |
An opaque structure; it must be present and first. |
devpath | char | The pathname to the AVCP device resource manager. |
fd | int | The file descriptor connection to device resource manager, or -1 if not connected |
dname [AVCP_METADATA_MAX] |
char | Bluetooth-friendly name |
dserial [AVCP_METADATA_MAX] |
char | Bluetooth address (used as device serial number) |
verbose | uint16_t | The log level verbosity |
This section describes how to modify and build the io-fs-media module example.
The Aviage Bluetooth Integration Kit includes a set of files that make up the io-fs-media module. These files include:
The only file that requires changes for integration is the avrcpexample.c file. Sections of this file that require the addition of device-specific code are denoted by comments, as follows:
Below is an example of a section of the avrcpexample.c file that requires device-specific code:
case DCMD_MEDIA_PREV_TRACK: // -- START DEVICECODE // -- TASK: Issue command to skip to the previous track on // the remote device. // Device control may be supported. If not supported, // status=ENOTSUP. // Device control can fail. // -- PSEUDOCODE: // status = DEVICEFUNC_PREV_TRACK(); // -- END DEVICECODE break;
After you have added the required device-specific code to the io-fs-media module, you can build it as follows:
# cp -R $QNX_TARGET/examples ~/examples
# cd ~/examples/io-fs/drvr/media/avrcpexample # make install
To build all sample modules, you can make them from the ~/examples/io-fs directory, as follows:
# cd ~/examples/io-fs # make install
After you have added all your device-specific code to the io-fs-media module, you can use io-fs-media to load it. Starting the module is as simple as running an instance of io-fs-media with the driver, as follows:
# io-fs-media -davrcpexample
You can also pass options to the module, as follows:
# io-fs-media -davrcpexample,verbose=10,mount=/fs/alt/mount/point
See avrcp_options() for a list of options.
If the remote device is present, then your application should register a new mount point. You can use the ls commandline instruction to examine the mountpoint:
# ls /fs/avrcp0
You can add multiple devices by running separate instances of the module, as follows:
# io-fs-media -davrcpexample,dev=/dev/avrcp0,mount=/fs/avrcp0 # io-fs-media -davrcpexample,dev=/dev/avrcp1,mount=/fs/avrcp1 # io-fs-media -davrcpexample,dev=/dev/avrcp2,mount=/fs/avrcp2
This section lists the messages that you can send to Bluetooth devices to control playback and to extract metadata.
![]() |
|
Playback of media tracks on a Bluetooth device occurs on the device. The start and manage playback the io-fs-media module sends control messages to the Bluetooth device. The table below lists playback commands implemented for AVRCP 1.0 and 1.3 devices. Required commands are marked with an asterisk (*). All others are optional.
The io-fs-media driver implements the following playback devctls for AVRCP 1.0 devices:
In addition to the playback commands listed above, the following optional shuffle and repeat commands devctls are implemented for AVRCP 1.3 devices:
Metadata extraction commands retrieve metadata about the currently playing file. All strings returned by the metadata extraction commands must be UTF-8 encoded. All metadata extraction commands are optional.
This section describes:
After you have modified your io-fs-media module and have it running, you must configure the MME to enable Bluetooth support. You need to:
To enable Bluetooth support, add an entry to the MCD configuration file to instruct the MCD to monitor the path for Bluetooth devices. For example:
[/fs/avrcp*] Callout = PATH_MEDIA_PROCMGR Argument = /proc/mount Priority = 11,10 Start Rule = INSERTED Stop Rule = EJECTED
For more information about the MCD, see the MME Utilities Reference.
The Bluetooth slot type is MME_SLOTTYPE_MEDIAFS (4), and the storagetype is MME_STORAGETYPE_A2DP (12). To enable Bluetooth support, you need to add an entry such as the following in the slots table:
INSERT INTO slots(path,zoneid, name, slottype) VALUES('/fs/avrcp0', 1, 'Bluetooth', 4);
![]() |
The slottype for Bluetooth support must be 4. |
If you have configured the MME correctly to support Bluetooth devices, on learning of the insertion of a Bluetooth device, the MME:
You can use this file ID to create a track session with a single track for the device, then issue commands to start and manage playback. Playback remains on the Bluetooth device, and the MME does not have access to information about an individual track on the device unless the track is being played.
The MME supports calls to the following playback functions for Bluetooth devices:
![]() |
Do not set autopause (mme_setautopause()) for control contexts with a Bluetooth phone. Because Bluetooth phones control their own playback, if you set autopause for a control context with a Bluetooth phone:
|
Below are sample sequences showing how to use the MME commandline utility (mmecli)to:
# qdbc -d mme "select msid,slotid,storage_type, mountpath \ from mediastores" Rows: 2 Cols: 4 Names: +msid+slotid+storage_type+mountpath+ 00000: |1|1|2|/media/drive| 00001: |2|9|2|/fs/avrcp0|
# qdbc -d mme "select fid,msid,folderid,ftype,filename, title \ from library where msid=2" Rows: 1 Cols: 6 Names: +fid+msid+folderid+ftype+filename+title+ 00000: |2|2|2|5||Bluetooth|
# mmecli newtrksession l "Select fid from library where msid=2" (rc=0,errno=0) new trksessionid=2. Execution Time=0.010 # mmecli settrksession 2 (rc=0,errno=0) Set trksessionid=2. Execution Time=0.031 # mmecli play (rc=0,errno=i0) Playing from tracksession fid = 2. Execution Time=0.038
The MME has access to metadata for a track on a Bluetooth device only when the device is playing the track. To obtain this metadata, query the MME's nowplaying table.
The MME does not handle audio routing for the io-fs-media module. You must configure your system to properly route audio from Bluetooth devices to the desired output location.
![]() |
![]() |
![]() |
![]() |