Playing audio content

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.

An audio track can be a local file or a file or stream accessed over HTTP. These sources are all specified in the same way through the API, but their supported playback operations may differ. 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. When playing a stream, you might not be able to seek or pause 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):
// Define a structure to hold information about any context errors
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;
}

// Start playback
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 may likely 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.

We could also select an HTTP-accessible audio file or stream as our input; this is done in the same way as when playing video content.

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

Controlling playback

The mm-renderer API provides several functions for controlling playback. For files, we can change the playback speed:
if ( mmr_speed_set( ctxt_audioplay, 500 ) < 0 ) {
    errorInfo = mmr_error_info(ctxt_audioplay);
    /* Remaining error-handling code goes here */
    return EXIT_FAILURE;
}
The value used for the second argument must be in units of 1/1000 normal speed. So in our example, the value of 500 makes the track play at half of its normal speed (1000). We can set the speed to 0 to pause playback; there's no separate function for doing this. But there is a 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.