Playing audio content

Updated: April 19, 2023

By following the steps outlined in the introduction about client usage of mm-renderer, you can use the service to play a single audio track with certain parameter settings, such as volume.

Note: Playing an HTTP-accessible file or stream isn't supported in the shipped version of mm-renderer. If you need these capabilities, contact QNX Customer Support.

An audio track can be a locally accessible file, meaning it could be a file physically stored on your system or a file on an attached media device whose filesystem has been mounted. When playing a file, you can change the playback speed (including setting it to 0 to pause playback), seek to a new position, and stop playback.

Below, we provide code samples showing how to use mm-renderer for audio playback.

Creating an mm-renderer context

Before we can select and play an audio track, we must connect to the service and define a context:
// Connect to mm-renderer and use the default device path
mmr_connection_t* conn_dflt = mmr_connect(NULL);

if (conn_dflt == NULL) {
    fprintf(stderr, "Error connecting to mm-renderer service: %s\n",
            strerror(errno));
    /* Remaining error-handling code goes here */
    return EXIT_FAILURE;
}

// Create the context
mmr_context_t* ctxt_audioplay = mmr_context_create( conn_dflt, 
                                              "audioZone1", 
                                              0, 
                                              S_IRWXU|S_IRWXG|S_IRWXO );

if (ctxt_audioplay == NULL) {
    /* Error-handling code goes here */
    return EXIT_FAILURE;
}

Defining and configuring the audio output

We must now tell mm-renderer which hardware device will play the audio, and configure parameters to optimize playback (possibly based on user preferences):
const mmr_error_info_t* errorInfo;

// Attach an audio output with a URL of "snd:" to use the preferred device
int outputID = mmr_output_attach( ctxt_audioplay, "snd:", "audio" );

if (outputID == -1) {
    errorInfo = mmr_error_info(ctxt_audioplay);
    /* Remaining error-handling code goes here */
    return EXIT_FAILURE;
}

strm_dict_t* dict_output_params = strm_dict_new();
// Set the volume and audio_type parameters
if ( strm_dict_set( dict_output_params, "volume", "50" ) < 0 ) {
    /* Error-handling code goes here */
}
else if ( strm_dict_set( dict_output_params, 
                         "audio_type", 
                         "multimedia" ) < 0 ) {
    /* Error-handling code goes here */
}
else if ( mmr_output_parameters( ctxt_audioplay,
                                 outputID,
                                 dict_output_params ) < 0 ) {
    errorInfo = mmr_error_info(ctxt_audioplay);
    /* Remaining error-handling code goes here */
    return EXIT_FAILURE;
}
For an explanation of all supported audio output parameters, see Parameters that affect how the output is delivered.

Defining the input and starting playback

With the output attached to the context, we can now attach the input by providing a URL that names the file we want to play, and then start playback:
// Attach a local file as the input; use "track" as the type because
// we're playing a single audio track
int inputID = mmr_input_attach( ctxt_audioplay,
                                "/fs/usb0/cosmic_girl.mp3",
                                "track" );

if (inputID == -1) {
    errorInfo = mmr_error_info(ctxt_audioplay);
    /* Remaining error-handling code goes here */
    return EXIT_FAILURE;
}

if ( mmr_play( ctxt_audioplay ) < 0 ) {
    errorInfo = mmr_error_info(ctxt_audioplay);
    /* Remaining error-handling code goes here */
    return EXIT_FAILURE;
}

For the input URL, we provide a hard-coded path to a local MP3 audio file. In your program, you might need to use a variable; for instance, if the track to be played is based on user selection. Also, when naming a local file as input, you can prepend the URL with file: to make it clear that you're accessing a file in the filesystem. For the list of supported file extensions and associated audio formats, see the product release notes.

With the track input type, there are no parameters for audio files, so we can't configure the input.

Controlling playback

Note: Playing at non-standard speeds (i.e., trick play) isn't supported in the shipped version of mm-renderer. If you need this capability, contact QNX Customer Support. However, it's still possible to set a speed of 0 to pause playback.
The mm-renderer API provides several functions for controlling playback. We can set the playback speed to 0 to pause playback:
if ( mmr_speed_set( ctxt_audioplay, 0 ) < 0 ) {
    errorInfo = mmr_error_info(ctxt_audioplay);
    /* Remaining error-handling code goes here */
    return EXIT_FAILURE;
}
The value for the second argument must be in units of 1/1000th normal speed. We can specify a value of 500 to make the track play at half of its normal speed (1000).
There's a separate function for stopping playback (which works for any source type):
if ( mmr_stop( ctxt_audioplay ) < 0 ) {
    errorInfo = mmr_error_info(ctxt_audioplay);
    /* Remaining error-handling code goes here */
    return EXIT_FAILURE;
}
Suppose we want to seek (jump) to a new track position, based on a user action. This works for files and might work for some (but not all) streams. There's a function for doing this:
if ( mmr_seek( ctxt_audioplay, "30000" ) < 0 ) {
    errorInfo = mmr_error_info(ctxt_audioplay);
    /* Remaining error-handling code goes here */
    return EXIT_FAILURE;
}
Here, we jumped to 30 seconds into the track by specifying the corresponding number of milliseconds in the second argument.