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.
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 ); }
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); }
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.
#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); }
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... // ... } }