audio_manager_routing.h

Definitions for supported audio routing configurations.

The audio manager maintains the audio routing logic based on registered audio sources. This file defines routing properties and provides functions for them. The following are examples of using audio routing.

Setting an audio type from libasound

This example shows how to get an audio handle and set its type for a libasound channel. The example is for playback, but the audio manager specific steps are the same for recording. The example acquires an audio manager handle of type AUDIO_TYPE_ALERT, and sets it to become active only when PCM audio is actually playing (this is done via the suspended flag). The audio manager handle is bound to a libasound PCM handle, and freed when the program ends.

#include <audio/audio_manager_routing.h>
#include <sys/asoundlib.h>
 
void main(void)
{
  unsigned int audioman_handle;
  snd_pcm_t *pcm_handle;
 
  // Acquire an audioman handle. Start it "suspended", which means that its
  // ducking and routing rules only become active when the PCM channel is 
  // actually playing.
  if ( audio_manager_get_handle ( AUDIO_TYPE_ALERT,    // Audio Type
                                 0,                    // pid that owns handle. 0 = this process
                                 true,                 // Start "suspended"  
                                 &audioman_handle ) < 0 ) {   
    printf("Could not get an audioman handle of the requested type\n");
    return;
  }
 
  // Acquire a pcm channel from libasound for playback
  snd_pcm_open ( &pcm_handle, "/dev/snd/pcmPreferred", SND_PCM_OPEN_PLAYBACK );
 
  // Bind the pcm_handle with the audioman handle.
  if ( snd_pcm_set_audioman_handle( pcm_handle, audioman_handle ) < 0 ) {
    printf("Could not set the pcm_handle with the audioman_handle\n"); 
  }
 
  // Do what you would normally do here with libasound...
  // ...
 
  // Cleanup
  snd_pcm_close( pcm_handle );
  audio_manager_free_handle( audioman_handle );
} 

The audio type AUDIO_TYPE_ALERT, when active, will follow the routing of other active audio because it is lowest priority in the routing table. If nothing else is playing, it will force routing to be through the loud speaker, regardless of what other devices are connected.

For concurrency, if there is an AUDIO_TYPE_DEFAULT playing concurrently (which is the case for any stream that does not explicitly use the audio manager), when the AUDIO_TYPE_ALERT becomes active, it will cause the AUDIO_TYPE_DEFAULT stream to become attenuated.

Alernatively, you can use utility functions in audio_manager_routing.h to implicitly handle the setup in one call. Note that the audioman_handle starts up suspended:

#include <audio/audio_manager_routing.h>
#include <sys/libasound.h>
 
 
void main(void)
{
  unsigned int audioman_handle;
  snd_pcm_t *pcm_handle;
 
  if (audio_manager_snd_pcm_open_name( AUDIO_TYPE_ALERT,
                       &pcm_handle, 
                       &audioman_handle,
                       "/dev/snd/pcmPreferred",
                       SND_PCM_OPEN_PLAYBACK ) < 0 ) {
    printf("Failed to open an audioman pcm channel\n");
    return;
  }
 
 
  // Do what you would normally do with libasound...
  // ...
 
 
  // Cleanup
  snd_pcm_close( pcm_handle );
  audio_manager_free_handle( audioman_handle );
}

Setting an audio type from mm-renderer

This example shows how to set the audio type for an mm-renderer application. The code that follows sets the audio type of the mm-renderer context to AUDIO_TYPE_ALERT. Currently, the "audio_type" output parameter in mm-renderer is supported for playback only.

#include <mm/renderer.h>
#include <audio/audio_manager_routing.h>
 
{
    mmr_connection_t* connection;
    connection = mmr_connect(NULL);
 
 
    // Create a new mm-renderer context
    mmr_context_t* mmr_context;
    mmr_context = mmr_context_create(connection, context_name, 0, S_IRWXU|S_IRWXG|S_IRWXO);
 
    // Set audio type by setting "audio_type" when calling mmr_output_parameters()
    strm_dict_t* dict = strm_dict_new();
    dict = strm_dict_set( dict, "audio_type", audio_manager_get_name_from_type(AUDIO_TYPE_ALERT));
    mmr_output_parameters( context, output_id, dict );
 
    // 
    // Attach input here
    //
    // Play audio
    mmr_play( context );
 
    // ....
 
 
    //
    // Cleanup
    //
    strm_dict_destroy( dict );
    mmr_context_destroy(context);
    mmr_disconnect(connection);
 
}


Setting an audio manager handle from mm-renderer

There may be times when an application needs to do some advanced routing. For example, an application may want to do its own custom audio routing, instead of using the default audio routing provided by audio manager. In that case, an application may request a handle from audio manager and then pass this handle to mm-renderer. This way, the mm-renderer context is bound to the audio manager handle.

Your application can pass the audio manager handle to mm-renderer by calling the function mmr_output_parameters() and specifying "audioman_handle". Note that setting "audioman_handle" parameter on mm-renderer is supported for playback only.

Note: mm-renderer will not activate or suspend the audio manager handle. It is the responsibility of the application to activate and suspend audio manager. The audio routing and audio ducking will be in effect only when an audio manager handle is active. In other words; when audio manager handle is suspended, no audio routing and audio ducking effects will happen, even if the audio is already playing.
You can activate an audio manager handle by:
  • setting the suspended parameter to false when you request an audio manager handle by calling audio_manager_get_handle(). This will activate audio manager immediately.
  • calling audio_manager_activate_handle()
You can suspend an audio manager handle by:
  • freeing the audio manager handle by calling audio_manager_free_handle()
  • calling audio_manager_suspend_handle()
#include <mm/renderer.h>
#include <audio/audio_manager_routing.h>
 
{
    mmr_connection_t* connection;
    connection = mmr_connect(NULL);
 
    // Create a new mm-renderer context
    mmr_context_t* mmr_context;
    mmr_context = mmr_context_create(connection, context_name, 0, S_IRWXU|S_IRWXG|S_IRWXO);
 
    // Get an audio manager handle from Audio Manager handle and then convert it to a string
    // so that it can be passed to mm-renderer.
    // This call will activate audio manager handle immediately (notice the suspended parameter is
    // set to false).
    uint32_t audioman_handle; audio_manager_get_handle(AUDIO_TYPE_DEFAULT, getpid(), false, &audioman_handle);
    char audioman_handle_str[15];
    itoa(audioman_handle, audioman_handle_str, 10);
 
    // Set audio manager handle by setting "audioman_handle" when calling mmr_output_parameters()
    strm_dict_t* dict = strm_dict_new();
    dict = strm_dict_set( dict, "audioman_handle", audioman_handle_str);
    mmr_output_parameters( context, output_id, dict );
 
    //
    // Attach input here
    //
 
    // Play audio mmr_play( context );
 
    // ....
 
    //
    // Cleanup
    //
    strm_dict_destroy( dict );
    mmr_context_destroy(context);
    mmr_disconnect(connection); }


Forcing the audio routing

This example shows how to override the default routing for an audio type. In this example, because we are not actually binding a libasound pcm handle to the audioman handle, we start the audioman handle as not suspended so that the routing and concurrency policy changes take effect right away. This will force the output routing to speaker, and leave the input routing up to the default routing table. The routing override is in effect as long as the audioman_handle's type is the highest priority routing type currently active. Note that if there are multiple handles of the same type active at the same time, then it is a last-one-wins policy.

#include <audio/audio_manager_routing.h>
 
void main(void)
{
    unsigned int audioman_handle;
 
    // Acquire an audioman handle. Start it "unsuspended", which means that its
    // ducking and routing rules take effect immediately.
    if (audio_manager_get_handle(AUDIO_TYPE_DEFAULT, // Type default
                                 0,                  // This pid
                                 false,              // Start "unsuspended" 
                                 &audioman_handle) == EOK) {
 
        // Use audio_manager_set_handle_type to also override the routing paths
        if (audio_manager_set_handle_type(audioman_handle, // audioman handle
                  AUDIO_TYPE_DEFAULT,              // Use the same type
                  AUDIO_DEVICE_SPEAKER,            // Force routing to loud speaker for output
                  AUDIO_DEVICE_DEFAULT ) == EOK) { // No preference for the input routing.
       
            // Do what you would normally do here with libasound...
            // ...
       
        }
        audio_manager_free_handle(audioman_handle);
    } else {
        // Handle error as desired.
        // You may want to proceed with what you would normally do here
        // with libasound...
        // ...
        
    }    
}