Support new features for sound policy 93/41093/2
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 10 Feb 2015 13:28:35 +0000 (22:28 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 8 Jul 2015 05:37:50 +0000 (14:37 +0900)
Public header: Stream Information and Focus
Internal header: Virtual stream and getter methods

[Version] 0.3.0
[Profile] Common
[Issue Type] New feature

Change-Id: I3aca6780d1c80ffe111096ca4df4030b8682229a

CMakeLists.txt
include/sound_manager.h
include/sound_manager_internal.h
include/sound_manager_private.h
packaging/capi-media-sound-manager.spec
src/sound_manager.c
src/sound_manager_internal.c [new file with mode: 0644]
src/sound_manager_private.c
test/sound_manager_test.c

index 05a3d0aa66ce084d9e78ad89bf8ce670befbefe5..e0b87d0da84c8441a9e9ddf24b22a22311b874f9 100644 (file)
@@ -23,7 +23,7 @@ SET(service "media")
 SET(submodule "sound-manager")
 
 # for package file
-SET(dependents "mm-sound dlog capi-base-common mm-session")
+SET(dependents "mm-sound dlog capi-base-common mm-session libpulse gio-2.0")
 SET(pc_dependents "capi-base-common")
 
 # for deb
index fa1386634ce387ad93b452b3d4326dc881e818a7..0507fa2ef08d572169b6ede9607df0a21fd6aa52 100644 (file)
@@ -40,16 +40,17 @@ extern "C"
  */
 typedef enum
 {
-    SOUND_MANAGER_ERROR_NONE              = TIZEN_ERROR_NONE,                    /**< Successful */
-    SOUND_MANAGER_ERROR_OUT_OF_MEMORY     = TIZEN_ERROR_OUT_OF_MEMORY,           /**< Out of memory */
-    SOUND_MANAGER_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER,       /**< Invalid parameter */
-    SOUND_MANAGER_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION,       /**< Invalid operation */
-    SOUND_MANAGER_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED,       /**< Permission denied */
-    SOUND_MANAGER_ERROR_NOT_SUPPORTED     = TIZEN_ERROR_NOT_SUPPORTED,           /**< Not supported */
-    SOUND_MANAGER_ERROR_NO_DATA           = TIZEN_ERROR_NO_DATA,                 /**< No data */
-    SOUND_MANAGER_ERROR_INTERNAL          = TIZEN_ERROR_SOUND_MANAGER | 01,      /**< Internal error inside the sound system */
-    SOUND_MANAGER_ERROR_POLICY            = TIZEN_ERROR_SOUND_MANAGER | 02,      /**< Noncompliance with the sound system policy */
-    SOUND_MANAGER_ERROR_NO_PLAYING_SOUND  = TIZEN_ERROR_SOUND_MANAGER | 03,      /**< No playing sound */
+       SOUND_MANAGER_ERROR_NONE              = TIZEN_ERROR_NONE,                    /**< Successful */
+       SOUND_MANAGER_ERROR_OUT_OF_MEMORY     = TIZEN_ERROR_OUT_OF_MEMORY,           /**< Out of memory */
+       SOUND_MANAGER_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER,       /**< Invalid parameter */
+       SOUND_MANAGER_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION,       /**< Invalid operation */
+       SOUND_MANAGER_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED,       /**< Permission denied */
+       SOUND_MANAGER_ERROR_NOT_SUPPORTED     = TIZEN_ERROR_NOT_SUPPORTED,           /**< Not supported */
+       SOUND_MANAGER_ERROR_NO_DATA           = TIZEN_ERROR_NO_DATA,                 /**< No data */
+       SOUND_MANAGER_ERROR_INTERNAL          = TIZEN_ERROR_SOUND_MANAGER | 01,      /**< Internal error inside the sound system */
+       SOUND_MANAGER_ERROR_POLICY            = TIZEN_ERROR_SOUND_MANAGER | 02,      /**< Noncompliance with the sound system policy */
+       SOUND_MANAGER_ERROR_NO_PLAYING_SOUND  = TIZEN_ERROR_SOUND_MANAGER | 03,      /**< No playing sound */
+       SOUND_MANAGER_ERROR_INVALID_STATE     = TIZEN_ERROR_SOUND_MANAGER | 04,      /**< Invalid state (Since 2.4) */
 } sound_manager_error_e;
 
 /**
@@ -63,16 +64,111 @@ typedef enum
  */
 typedef enum
 {
-    SOUND_TYPE_SYSTEM,          /**< Sound type for system */
-    SOUND_TYPE_NOTIFICATION,    /**< Sound type for notifications */
-    SOUND_TYPE_ALARM,           /**< Sound type for alarm */
-    SOUND_TYPE_RINGTONE,        /**< @internal Sound type for ringtones */
-    SOUND_TYPE_MEDIA,           /**< Sound type for media */
-    SOUND_TYPE_CALL,            /**< @internal Sound type for call */
-    SOUND_TYPE_VOIP,            /**< @internal Sound type for voip */
-    SOUND_TYPE_VOICE,           /**< Sound type for voice */
+       SOUND_TYPE_SYSTEM,          /**< Sound type for system */
+       SOUND_TYPE_NOTIFICATION,    /**< Sound type for notifications */
+       SOUND_TYPE_ALARM,           /**< Sound type for alarm */
+       SOUND_TYPE_RINGTONE,        /**< @internal Sound type for ringtones */
+       SOUND_TYPE_MEDIA,           /**< Sound type for media */
+       SOUND_TYPE_CALL,            /**< @internal Sound type for call */
+       SOUND_TYPE_VOIP,            /**< @internal Sound type for voip */
+       SOUND_TYPE_VOICE,           /**< Sound type for voice */
 } sound_type_e;
 
+/**
+ * @}
+ */
+
+/**
+ * @addtogroup CAPI_MEDIA_SOUND_MANAGER_STREAM_POLICY_MODULE
+ * @{
+ */
+
+/**
+ * @brief Sound stream information handle.
+ * @since_tizen 2.4
+ */
+typedef struct sound_stream_info_s* sound_stream_info_h;
+
+/**
+ * @brief Enumeration for sound stream type.
+ * @since_tizen 2.4
+ */
+typedef enum {
+       SOUND_STREAM_TYPE_MEDIA,              /**< Sound stream type for media */
+       SOUND_STREAM_TYPE_SYSTEM,             /**< Sound stream type for system */
+       SOUND_STREAM_TYPE_ALARM,              /**< Sound stream type for alarm */
+       SOUND_STREAM_TYPE_NOTIFICATION,       /**< Sound stream type for notification */
+       SOUND_STREAM_TYPE_EMERGENCY,          /**< Sound stream type for emergency */
+       SOUND_STREAM_TYPE_VOICE_INFORMATION,  /**< Sound stream type for voice information */
+       SOUND_STREAM_TYPE_VOICE_RECOGNITION,  /**< Sound stream type for voice recognition */
+       SOUND_STREAM_TYPE_RINGTONE_VOIP,      /**< Sound stream type for ringtone for VoIP */
+       SOUND_STREAM_TYPE_VOIP,               /**< Sound stream type for VoIP */
+} sound_stream_type_e;
+
+/**
+ * @brief Enumeration for change reason of sound stream focus state.
+ * @since_tizen 2.4
+ */
+typedef enum {
+       SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA,             /**< Changed by the stream type for media */
+       SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM,            /**< Changed by the stream type for system */
+       SOUND_STREAM_FOCUS_CHANGED_BY_ALARM,             /**< Changed by the stream type for alarm */
+       SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION,      /**< Changed by the stream type for notification */
+       SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY,         /**< Changed by the stream type for emergency */
+       SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION, /**< Changed by the stream type for voice information */
+       SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION, /**< Changed by the stream type for voice recognition */
+       SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE,          /**< Changed by the stream type for ringtone */
+       SOUND_STREAM_FOCUS_CHANGED_BY_VOIP,              /**< Changed by the stream type for VoIP */
+       SOUND_STREAM_FOCUS_CHANGED_BY_CALL,              /**< Changed by the stream type for voice-call or video-call */
+} sound_stream_focus_change_reason_e;
+
+/**
+ * @brief Enumeration for sound stream focus mask.
+ * @since_tizen 2.4
+ */
+typedef enum {
+       SOUND_STREAM_FOCUS_FOR_PLAYBACK    = 0x0001,   /**< Mask for playback focus */
+       SOUND_STREAM_FOCUS_FOR_RECORDING   = 0x0002,   /**< Mask for recording focus */
+} sound_stream_focus_mask_e;
+
+/**
+ * @brief Enumeration for sound stream focus state.
+ * @since_tizen 2.4
+ */
+typedef enum {
+       SOUND_STREAM_FOCUS_STATE_RELEASED,   /**< Focus state for release */
+       SOUND_STREAM_FOCUS_STATE_ACQUIRED,   /**< Focus state for acquisition */
+} sound_stream_focus_state_e;
+
+/**
+ * @brief Called when the state of focus that belongs to the stream_info is changed.
+ * @since_tizen 2.4
+ * @param[in]   stream_info    The handle of stream information
+ * @param[in]   reason_for_change      The reason for state change of the focus
+ * @param[in]   additional_info        The additional information
+ * @param[in]   user_data      The user data passed from the callback registration function
+ *
+ * @pre You should register this callback using sound_manager_create_stream_information().
+ * @post Use sound_manager_get_focus_state() in this callback to figure out how the focus state of the stream_info has been changed.
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ */
+typedef void (* sound_stream_focus_state_changed_cb) (sound_stream_info_h stream_info, sound_stream_focus_change_reason_e reason_for_change, const char *additional_info, void *user_data);
+
+/**
+ * @brief Called when the focus state for each sound stream type is changed regardless of the process.
+ * @since_tizen 2.4
+ * @param[in]   changed_focus_mask     The changed focus mask
+ * @param[in]   changed_focus_state    The changed focus state
+ * @param[in]   reason_for_change      The reason for state change of the focus
+ * @param[in]   additional_info        The additional information
+ * @param[in]   user_data      The user data passed from the callback registration function
+ * @pre You should register this callback using sound_manager_set_focus_state_watch_cb().
+ * @see sound_manager_set_focus_state_watch_cb()
+ * @see sound_manager_unset_focus_state_watch_cb()
+ */
+typedef void (* sound_stream_focus_state_watch_cb) (sound_stream_focus_mask_e changed_focus_mask, sound_stream_focus_state_e changed_focus_state, sound_stream_focus_change_reason_e reason_for_change, const char *additional_info, void *user_data);
+
 /**
  * @}
  */
@@ -83,11 +179,11 @@ typedef enum
  */
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_create_stream_information() and sound_stream_type_e instead.
  * @brief Enumeration for session type.
  * @since_tizen 2.3
  */
-typedef enum
-{
+typedef enum {
        SOUND_SESSION_TYPE_MEDIA = 0,           /**< Media type */
        SOUND_SESSION_TYPE_ALARM,                       /**< Alarm type */
        SOUND_SESSION_TYPE_NOTIFICATION,                /**< Notification type */
@@ -97,41 +193,41 @@ typedef enum
 } sound_session_type_e;
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_acquire_focus() or not instead.
  * @brief Enumeration for session option for starting.
  * @since_tizen 2.3
  */
-typedef enum
-{
+typedef enum {
        SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START = 0, /**< This session will be mixed with others when starting (default) */
        SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START,        /**< This session will interrupt other sessions when starting */
 } sound_session_option_for_starting_e;
 
 /**
+ * @deprecated Deprecated since 2.4. In sound_stream_focus_state_changed_cb, you can choose to stop playing or not.
  * @brief Enumeration for session option during play.
  * @since_tizen 2.3
  */
-typedef enum
-{
+typedef enum {
        SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY = 0,  /**< This session will be interrupted by other sessions during play (default) */
        SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY,    /**< This session will not be interrupted by other media sessions */
 } sound_session_option_for_during_play_e;
 
 /**
+ * @deprecated Deprecated since 2.4. In sound_stream_focus_state_changed_cb, you can choose to resume playing or not.
  * @brief Enumeration for session option for resumption.
  * @since_tizen 2.3
  */
-typedef enum
-{
+typedef enum {
        SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM = 0,             /**< This session will be resumed according to system policy (default) */
        SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED, /**< This session will be resumed according to system policy and when the media session which interrupted this session is paused */
 } sound_session_option_for_resumption_e;
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_apply_stream_routing() instead.
  * @brief Enumeration for voip session mode.
  * @since_tizen 2.3
  */
-typedef enum
-{
+typedef enum {
        SOUND_SESSION_VOIP_MODE_RINGTONE = 0,                /**< voip mode for ringtone */
        SOUND_SESSION_VOIP_MODE_VOICE_WITH_BUILTIN_RECEIVER, /**< voip mode for during call with built-in receiver */
        SOUND_SESSION_VOIP_MODE_VOICE_WITH_BUILTIN_SPEAKER,  /**< voip mode for during call with built-in speaker */
@@ -142,10 +238,9 @@ typedef enum
 /**
  * @internal
  * @brief Enumeration for call session mode.
- * @since_tizen 2.3
+ * @since_tizen 2.3.1
  */
-typedef enum
-{
+typedef enum {
        SOUND_SESSION_CALL_MODE_RINGTONE = 0,                /**< call mode for ringtone */
        SOUND_SESSION_CALL_MODE_VOICE_WITH_BUILTIN_RECEIVER, /**< call mode for during call with built-in receiver */
        SOUND_SESSION_CALL_MODE_VOICE_WITH_BUILTIN_SPEAKER,  /**< call mode for during call with built-in speaker */
@@ -154,22 +249,23 @@ typedef enum
 } sound_session_call_mode_e;
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_stream_focus_state_changed_cb instead.
  * @brief Enumeration for sound session interrupted type.
  * @since_tizen 2.3
  */
-typedef enum
-{
-       SOUND_SESSION_INTERRUPTED_COMPLETED = 0,                                /**< Interrupt completed*/
-       SOUND_SESSION_INTERRUPTED_BY_MEDIA,                             /**< Interrupted by media application*/
-       SOUND_SESSION_INTERRUPTED_BY_CALL,                                              /**< Interrupted by an incoming call*/
-       SOUND_SESSION_INTERRUPTED_BY_EARJACK_UNPLUG,                    /**< Interrupted by unplugging headphones*/
-       SOUND_SESSION_INTERRUPTED_BY_RESOURCE_CONFLICT,         /**< Interrupted by a resource conflict*/
-       SOUND_SESSION_INTERRUPTED_BY_ALARM,                                     /**< Interrupted by an alarm*/
-       SOUND_SESSION_INTERRUPTED_BY_EMERGENCY,                                 /**< Interrupted by an emergency*/
-       SOUND_SESSION_INTERRUPTED_BY_NOTIFICATION,                                      /**< Interrupted by a notification*/
+typedef enum {
+       SOUND_SESSION_INTERRUPTED_COMPLETED = 0,        /**< Interrupt completed*/
+       SOUND_SESSION_INTERRUPTED_BY_MEDIA,             /**< Interrupted by media application*/
+       SOUND_SESSION_INTERRUPTED_BY_CALL,                    /**< Interrupted by an incoming call*/
+       SOUND_SESSION_INTERRUPTED_BY_EARJACK_UNPLUG,    /**< Interrupted by unplugging headphones*/
+       SOUND_SESSION_INTERRUPTED_BY_RESOURCE_CONFLICT, /**< Interrupted by a resource conflict*/
+       SOUND_SESSION_INTERRUPTED_BY_ALARM,             /**< Interrupted by an alarm*/
+       SOUND_SESSION_INTERRUPTED_BY_EMERGENCY,         /**< Interrupted by an emergency*/
+       SOUND_SESSION_INTERRUPTED_BY_NOTIFICATION,      /**< Interrupted by a notification*/
 } sound_session_interrupted_code_e;
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_stream_focus_state_changed_cb instead.
  * @brief Called when the playing sound session is interrupted.
  * @since_tizen 2.3
  * @param[in]   code   The interrupted code
@@ -178,7 +274,7 @@ typedef enum
  * @see sound_manager_set_session_interrupted_cb()
  * @see sound_manager_unset_session_interrupted_cb()
  */
-typedef void(* sound_session_interrupted_cb)(sound_session_interrupted_code_e code, void *user_data);
+typedef void (* sound_session_interrupted_cb) (sound_session_interrupted_code_e code, void *user_data);
 
 /**
  * @}
@@ -190,13 +286,13 @@ typedef void(* sound_session_interrupted_cb)(sound_session_interrupted_code_e co
  */
 
 /**
- * @brief sound device handle
+ * @brief Sound device handle.
  * @since_tizen 2.3
  */
 typedef void* sound_device_h;
 
 /**
- * @brief sound device list handle
+ * @brief Sound device list handle.
  * @since_tizen 2.3
  */
 typedef void* sound_device_list_h;
@@ -205,14 +301,15 @@ typedef void* sound_device_list_h;
 * @brief Enumeration for sound device type.
 * @since_tizen 2.3
 */
-typedef enum{
+typedef enum {
        SOUND_DEVICE_BUILTIN_SPEAKER,   /**< Built-in speaker */
        SOUND_DEVICE_BUILTIN_RECEIVER,  /**< Built-in receiver */
        SOUND_DEVICE_BUILTIN_MIC,       /**< Built-in mic */
        SOUND_DEVICE_AUDIO_JACK,        /**< Audio jack that can be connected to wired accessory such as headphone, headset, and so on */
        SOUND_DEVICE_BLUETOOTH,         /**< Bluetooth */
        SOUND_DEVICE_HDMI,              /**< HDMI */
-       SOUND_DEVICE_MIRRORING,         /**< MIRRORING */
+       SOUND_DEVICE_MIRRORING,         /**< MIRRORING (Deprecated since 2.4) */
+       SOUND_DEVICE_FORWARDING = SOUND_DEVICE_MIRRORING,    /**< Device for forwarding (Since 2.4) */
        SOUND_DEVICE_USB_AUDIO,         /**< USB Audio */
 } sound_device_type_e;
 
@@ -264,13 +361,13 @@ typedef enum {
  * @brief Called when the state of connection of a sound device was changed.
  * @since_tizen 2.3
  * @param[in]   sound_device_h The sound_device
- * @param[in]   is_connected   The state of device connection
+ * @param[in]   is_connected   The state of device connection: (@c true = connected, @c false = disconnected)
  * @param[in]   user_data      The user data passed from the callback registration function
  * @pre You should register this callback using sound_manager_set_device_connected_cb().
  * @see sound_manager_set_device_connected_cb()
  * @see sound_manager_unset_device_connected_cb()
  */
-typedef void(* sound_device_connected_cb)(sound_device_h device, bool is_connected, void *user_data);
+typedef void (* sound_device_connected_cb) (sound_device_h device, bool is_connected, void *user_data);
 
 /**
  * @brief Called when the information of a sound device was changed.
@@ -282,7 +379,7 @@ typedef void(* sound_device_connected_cb)(sound_device_h device, bool is_connect
  * @see sound_manager_set_device_information_changed_cb()
  * @see sound_manager_unset_device_information_changed_cb()
  */
-typedef void(* sound_device_information_changed_cb)(sound_device_h device, sound_device_changed_info_e changed_info, void *user_data);
+typedef void (* sound_device_information_changed_cb) (sound_device_h device, sound_device_changed_info_e changed_info, void *user_data);
 
 /**
  * @}
@@ -303,7 +400,7 @@ typedef void(* sound_device_information_changed_cb)(sound_device_h device, sound
  * @see sound_manager_set_volume_changed_cb()
  * @see sound_manager_unset_volume_changed_cb()
  */
-typedef void (*sound_manager_volume_changed_cb)(sound_type_e type, unsigned int volume, void *user_data);
+typedef void (*sound_manager_volume_changed_cb) (sound_type_e type, unsigned int volume, void *user_data);
 
 /**
  * @brief Gets the maximum volume level supported for a particular sound type.
@@ -317,7 +414,7 @@ typedef void (*sound_manager_volume_changed_cb)(sound_type_e type, unsigned int
  * @see sound_manager_set_volume()
  * @see sound_manager_get_volume()
  */
-int sound_manager_get_max_volume(sound_type_e type, int *max);
+int sound_manager_get_max_volume (sound_type_e type, int *max);
 
 /**
  * @brief Sets the volume level specified for a particular sound type.
@@ -335,7 +432,7 @@ int sound_manager_get_max_volume(sound_type_e type, int *max);
  * @see sound_manager_get_max_volume()
  * @see sound_manager_get_volume()
  */
-int sound_manager_set_volume(sound_type_e type, int volume);
+int sound_manager_set_volume (sound_type_e type, int volume);
 
 /**
  * @brief Gets the volume level specified for a particular sound type.
@@ -350,7 +447,7 @@ int sound_manager_set_volume(sound_type_e type, int volume);
  * @see sound_manager_get_max_volume()
  * @see sound_manager_set_volume()
  */
-int sound_manager_get_volume(sound_type_e type, int *volume);
+int sound_manager_get_volume (sound_type_e type, int *volume);
 
 /**
  * @brief Sets the type of the sound being currently played.
@@ -364,7 +461,7 @@ int sound_manager_get_volume(sound_type_e type, int *volume);
  * @see sound_manager_get_current_sound_type()
  * @see sound_manager_unset_current_sound_type()
  */
-int sound_manager_set_current_sound_type(sound_type_e type);
+int sound_manager_set_current_sound_type (sound_type_e type);
 
 /**
  * @brief Gets the type of the sound being currently played.
@@ -379,7 +476,7 @@ int sound_manager_set_current_sound_type(sound_type_e type);
  * @see sound_manager_set_current_sound_type()
  * @see sound_manager_unset_current_sound_type()
  */
-int sound_manager_get_current_sound_type(sound_type_e *type);
+int sound_manager_get_current_sound_type (sound_type_e *type);
 
 /**
  * @brief Unsets the type of the sound being currently played.
@@ -391,7 +488,7 @@ int sound_manager_get_current_sound_type(sound_type_e *type);
  * @see sound_manager_set_current_sound_type()
  * @see sound_manager_get_current_sound_type()
  */
-int sound_manager_unset_current_sound_type(void);
+int sound_manager_unset_current_sound_type (void);
 
 /**
  * @brief Registers a callback function to be invoked when the volume level is changed.
@@ -407,7 +504,7 @@ int sound_manager_unset_current_sound_type(void);
  * @see sound_manager_unset_volume_changed_cb()
  * @see sound_manager_volume_changed_cb()
  */
-int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void *user_data);
+int sound_manager_set_volume_changed_cb (sound_manager_volume_changed_cb callback, void *user_data);
 
 /**
  * @brief Unregisters the volume change callback.
@@ -417,7 +514,219 @@ int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback
  * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
  * @see sound_manager_set_volume_changed_cb()
  */
-int sound_manager_unset_volume_changed_cb(void);
+int sound_manager_unset_volume_changed_cb (void);
+
+/**
+ * @}
+ */
+
+/**
+ * @addtogroup CAPI_MEDIA_SOUND_MANAGER_STREAM_POLICY_MODULE
+ * @{
+ */
+
+/**
+ * @brief Creates a handle for stream information.
+ * @since_tizen 2.4
+ * @details    To apply the stream policy according to this stream information, this handle should be passed to other APIs\n
+ *     related to playback or recording. (e.g., player, wav-player, audio-io, etc.)
+ * @param[in]  stream_type     The type of stream
+ * @param[in]  callback        The focus state change callback function (mandatory)
+ * @param[in]  user_data       The user data to be passed to the callback function
+ * @param[out] stream_info     The handle of stream information
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_add_device_for_stream_routing()
+ * @see sound_manager_remove_device_for_stream_routing()
+ * @see sound_manager_apply_stream_routing()
+ * @see sound_manager_acquire_focus()
+ * @see sound_manager_destroy_focus()
+ * @see sound_manager_get_focus_state()
+ */
+int sound_manager_create_stream_information (sound_stream_type_e stream_type, sound_stream_focus_state_changed_cb callback, void *user_data, sound_stream_info_h *stream_info);
+
+/**
+ * @brief Destroys the handle for stream information.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_add_device_for_stream_routing()
+ * @see sound_manager_remove_device_for_stream_routing()
+ * @see sound_manager_apply_stream_routing()
+ * @see sound_manager_acquire_focus()
+ * @see sound_manager_destroy_focus()
+ * @see sound_manager_get_focus_state()
+ */
+int sound_manager_destroy_stream_information (sound_stream_info_h stream_info);
+
+/**
+ * @brief Adds the device to the stream information for the stream routing.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[in]  device          The device item from sound_device_list_h
+ *
+ * @remarks    @a Use sound_manager_get_current_device_list() and sound_manager_get_next_device() to get the device.\n
+ *     SOUND_MANAGER_ERROR_POLICY could be returned according to the stream type of the stream_info.\n
+ *     The available type of the stream_info for this API is SOUND_STREAM_TYPE_VOIP.
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_POLICY Noncompliance with the sound system policy
+ * @pre Call sound_manager_create_stream_information() before calling this function.
+ * @post You can apply this setting by calling sound_manager_apply_stream_routing().
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_remove_device_for_stream_routing()
+ * @see sound_manager_apply_stream_routing()
+ */
+int sound_manager_add_device_for_stream_routing (sound_stream_info_h stream_info, sound_device_h device);
+
+/**
+ * @brief Removes the device to the stream information for the stream routing.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[in]  device          The device item from sound_device_list_h
+ *
+ * @remarks    @a Use sound_manager_get_current_device_list() and sound_manager_get_next_device() to get the device.\n
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Call sound_manager_create_stream_information()/sound_manager_add_device_for_stream_routing() before calling this function.
+ * @post You can apply this setting by calling sound_manager_apply_stream_routing().
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_add_device_for_stream_routing()
+ * @see sound_manager_apply_stream_routing()
+ */
+int sound_manager_remove_device_for_stream_routing (sound_stream_info_h stream_info, sound_device_h device);
+
+/**
+ * @brief Applies the stream routing.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ *
+ * @remarks    @a If the stream has not been made yet, this setting will be applied when the stream starts to play.\n
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INVALID_STATE Invalid state
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @pre Call sound_manager_create_stream_information()/sound_manager_add_device_for_stream_routing() before calling this function.
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_add_device_for_stream_routing()
+ * @see sound_manager_remove_device_for_stream_routing()
+ */
+int sound_manager_apply_stream_routing (sound_stream_info_h stream_info);
+
+/**
+ * @brief Acquires the stream focus.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[in]  focus_mask              The focus mask that user wants to acquire
+ * @param[in]  additional_info Additional information for this request (optional, this can be null)
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INVALID_STATE Invalid state
+ * @retval #SOUND_MANAGER_ERROR_POLICY Noncompliance with the sound system policy
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @pre Call sound_manager_create_stream_information() before calling this function.
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_release_focus()
+ * @see sound_manager_get_focus_state()
+ */
+int sound_manager_acquire_focus (sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info);
+
+/**
+ * @brief Releases the acquired focus.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[in]  focus_mask              The focus mask that user wants to release
+ * @param[in]  additional_info Additional information for this request (optional, this can be null)
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INVALID_STATE Invalid state
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @pre Call sound_manager_create_stream_information()/sound_manager_acquire_focus() before calling this function.
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_acquire_focus()
+ * @see sound_manager_get_focus_state()
+ */
+int sound_manager_release_focus (sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info);
+
+/**
+ * @brief Gets the state of focus.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[out] state_for_playback      The state of playback focus
+ * @param[out] state_for_recording     The state of recording focus
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Call sound_manager_create_stream_information() before calling this function.
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_acquire_focus()
+ * @see sound_manager_release_focus()
+ */
+int sound_manager_get_focus_state (sound_stream_info_h stream_info, sound_stream_focus_state_e *state_for_playback, sound_stream_focus_state_e *state_for_recording);
+
+/**
+ * @brief Registers the watch callback function to be invoked when the focus state for each sound stream type is changed regardless of the process.
+ * @since_tizen 2.4
+ * @param[in]  focus_mask              The focus mask that user wants to watch
+ * @param[in]  callback        The focus state change watch callback function
+ * @param[in]  user_data       The user data to be passed to the callback function
+ *
+ * @remarks    @a You can set this callback only once per process.
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @see sound_manager_unset_focus_state_watch_cb()
+ */
+int sound_manager_set_focus_state_watch_cb (sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data);
+
+/**
+ * @brief Unregisters the focus state watch callback.
+ * @since_tizen 2.4
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @see sound_manager_set_focus_state_watch_cb()
+ */
+int sound_manager_unset_focus_state_watch_cb (void);
 
 /**
  * @}
@@ -429,6 +738,7 @@ int sound_manager_unset_volume_changed_cb(void);
  */
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_create_stream_information() instead.
  * @brief Sets the application's sound session type.
  * @since_tizen 2.3
  * @param[in] type The session type to set
@@ -447,9 +757,10 @@ int sound_manager_unset_volume_changed_cb(void);
  * @see sound_manager_set_voip_session_mode()
  * @see sound_manager_get_voip_session_mode()
  */
-int sound_manager_set_session_type(sound_session_type_e type);
+int sound_manager_set_session_type (sound_session_type_e type);
 
 /**
+ * @deprecated Deprecated since 2.4
  * @brief Gets the application's sound session type.
  * @since_tizen 2.3
  * @param[in] type The session type
@@ -465,9 +776,10 @@ int sound_manager_set_session_type(sound_session_type_e type);
  * @see sound_manager_set_voip_session_mode()
  * @see sound_manager_get_voip_session_mode()
  */
-int sound_manager_get_session_type(sound_session_type_e *type);
+int sound_manager_get_session_type (sound_session_type_e *type);
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_create_stream_information() instead.
  * @brief Sets the media sound session option.
  * @since_tizen 2.3
  * @param[in] s_option The session option for starting
@@ -485,9 +797,10 @@ int sound_manager_get_session_type(sound_session_type_e *type);
  * @see sound_manager_set_media_session_resumption_option()
  * @see sound_manager_get_media_session_resumption_option()
  */
-int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option);
+int sound_manager_set_media_session_option (sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option);
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_create_stream_information() instead.
  * @brief Gets the media sound session option.
  * @since_tizen 2.3
  * @param[out] s_option The session option for starting
@@ -504,9 +817,10 @@ int sound_manager_set_media_session_option(sound_session_option_for_starting_e s
  * @see sound_manager_set_media_session_resumption_option()
  * @see sound_manager_get_media_session_resumption_option()
  */
-int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option);
+int sound_manager_get_media_session_option (sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option);
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_create_stream_information() instead.
  * @brief Sets the media sound session resumption option.
  * @since_tizen 2.3
  * @param[in] option The session resumption option
@@ -523,9 +837,10 @@ int sound_manager_get_media_session_option(sound_session_option_for_starting_e *
  * @see sound_manager_get_media_session_option()
  * @see sound_manager_get_media_session_resumption_option()
  */
-int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option);
+int sound_manager_set_media_session_resumption_option (sound_session_option_for_resumption_e option);
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_create_stream_information() instead.
  * @brief Gets the media sound session resumption option.
  * @since_tizen 2.3
  * @param[out] option The session resumption option
@@ -541,9 +856,10 @@ int sound_manager_set_media_session_resumption_option(sound_session_option_for_r
  * @see sound_manager_get_media_session_option()
  * @see sound_manager_set_media_session_resumption_option()
  */
-int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option);
+int sound_manager_get_media_session_resumption_option (sound_session_option_for_resumption_e *option);
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_create_stream_information() instead.
  * @brief Sets the mode of the voip sound session.
  * @since_tizen 2.3
  * @param[in] mode The voip session mode
@@ -559,9 +875,10 @@ int sound_manager_get_media_session_resumption_option(sound_session_option_for_r
  * @see sound_manager_get_session_type()
  * @see sound_manager_get_voip_session_mode()
 */
-int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode);
+int sound_manager_set_voip_session_mode (sound_session_voip_mode_e mode);
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_create_stream_information() instead.
  * @brief Gets the mode of the voip sound session.
  * @since_tizen 2.3
  * @param[out] mode The voip session mode
@@ -577,12 +894,12 @@ int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode);
  * @see sound_manager_get_session_type()
  * @see sound_manager_set_voip_session_mode()
 */
-int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode);
+int sound_manager_get_voip_session_mode (sound_session_voip_mode_e *mode);
 
 /**
  * @internal
  * @brief Sets the mode of the call sound session.
- * @since_tizen 2.3
+ * @since_tizen 2.3.1
  * @param[in] mode The call session mode
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -596,12 +913,12 @@ int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode);
  * @see sound_manager_get_session_type()
  * @see sound_manager_get_call_session_mode()
 */
-int sound_manager_set_call_session_mode(sound_session_call_mode_e mode);
+int sound_manager_set_call_session_mode (sound_session_call_mode_e mode);
 
 /**
  * @internal
  * @brief Gets the mode of the call sound session.
- * @since_tizen 2.3
+ * @since_tizen 2.3.1
  * @param[out] mode The call session mode
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -615,9 +932,10 @@ int sound_manager_set_call_session_mode(sound_session_call_mode_e mode);
  * @see sound_manager_get_session_type()
  * @see sound_manager_set_call_session_mode()
 */
-int sound_manager_get_call_session_mode(sound_session_call_mode_e *mode);
+int sound_manager_get_call_session_mode (sound_session_call_mode_e *mode);
 
 /**
+ * @deprecated Deprecated since 2.4. Use sound_manager_create_stream_information() instead.
  * @brief Registers a callback function to be invoked when the sound session being played was interrupted.
  * @since_tizen 2.3
  * @param[in]  callback        The interrupted callback function
@@ -631,9 +949,10 @@ int sound_manager_get_call_session_mode(sound_session_call_mode_e *mode);
  * @see sound_manager_unset_session_interrupted_cb()
  * @see sound_session_interrupted_cb()
  */
-int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data);
+int sound_manager_set_session_interrupted_cb (sound_session_interrupted_cb callback, void *user_data);
 
 /**
+ * @deprecated Deprecated since 2.4
  * @brief Unregisters the callback function which is called when the sound session being played is interrupted.
  * @since_tizen 2.3
  * @return 0 on success,
@@ -642,7 +961,7 @@ int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callba
  * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
  * @see sound_manager_set_session_interrupted_cb()
  */
-int sound_manager_unset_session_interrupted_cb(void);
+int sound_manager_unset_session_interrupted_cb (void);
 
 /**
  * @}
@@ -675,7 +994,7 @@ int sound_manager_unset_session_interrupted_cb(void);
  * @see sound_manager_get_device_name()
  * @see sound_manager_get_device_state()
  */
-int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list);
+int sound_manager_get_current_device_list (sound_device_mask_e device_mask, sound_device_list_h *device_list);
 
 /**
  * @brief Gets the next item of the device list.
index c79a1cfe992c07c147d4f63d59ff7c4b6187952e..568d8df7c01b076cc08ad5665479158d0d2df451 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -22,11 +22,265 @@ extern "C"
 {
 #endif
 
+/**
+ * @file sound_manager_internal.h
+ * @brief This file contains the Sound Manager Internal API.
+ */
+
+/**
+ * @addtogroup CAPI_MEDIA_SOUND_MANAGER_MODULE
+ * @{
+ */
+
 #define SOUND_TYPE_NUM                SOUND_TYPE_VOICE + 1
 
 /**
- * @file sound_manager_internal.h
- * @brief This file contains the Sound Manager API (internal header)
+ * @internal
+ * @brief Virtual sound stream handle.
+ * @since_tizen 2.4
+ */
+typedef struct virtual_sound_stream_s* virtual_sound_stream_h;
+
+/**
+ * @internal
+ * @brief Enumeration for Native API.
+ * @since_tizen 2.4
+ */
+typedef enum {
+       NATIVE_API_SOUND_MANAGER,   /**< Sound-manager Native API */
+       NATIVE_API_PLAYER,          /**< Player Native API */
+       NATIVE_API_WAV_PLAYER,      /**< Wav-player Native API */
+       NATIVE_API_TONE_PLAYER,     /**< Tone-player Native API */
+       NATIVE_API_AUDIO_IO,        /**< Audio-io Native API */
+       NATIVE_API_RECORDER,        /**< Recorder Native API */
+} native_api_e;
+
+/**
+ * @internal
+ * @brief Enumeration for sound stream type for internal.
+ * @since_tizen 2.4
+ */
+typedef enum {
+       SOUND_STREAM_TYPE_RINGTONE_CALL = 100, /**< Sound stream type for ringtone for call */
+       SOUND_STREAM_TYPE_VOICE_CALL,          /**< Sound stream type for voice-call */
+       SOUND_STREAM_TYPE_VIDEO_CALL,          /**< Sound stream type for video-call */
+       SOUND_STREAM_TYPE_RADIO,               /**< Sound stream type for radio */
+       SOUND_STREAM_TYPE_LOOPBACK,            /**< Sound stream type for loopback */
+} sound_stream_type_internal_e;
+
+/**
+ * @internal
+ * @brief Creates a handle for stream information.
+ * @since_tizen 2.4
+ * @details    To apply the stream policy according to this stream information, this handle should be passed to other APIs\n
+ *     related to playback or recording. (e.g., player, wav-player, audio-io, etc.)
+ * @param[in]  stream_type     The type of stream for internal usage
+ * @param[in]  callback        The focus state change callback function (mandatory)
+ * @param[in]  user_data       The user data to be passed to the callback function
+ * @param[out] stream_info     The handle of stream information
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_add_device_for_stream_routing()
+ * @see sound_manager_remove_device_for_stream_routing()
+ * @see sound_manager_apply_stream_routing()
+ * @see sound_manager_acquire_focus()
+ * @see sound_manager_destroy_focus()
+ * @see sound_manager_get_focus_state()
+ */
+int sound_manager_create_stream_information_internal (sound_stream_type_internal_e stream_type, sound_stream_focus_state_changed_cb callback, void *user_data, sound_stream_info_h *stream_info);
+
+/**
+ * @internal
+ * @brief Adds the option to the stream information for the stream routing.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[in]  option          The option for the stream routing
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @pre Call sound_manager_create_stream_information() or sound_manager_create_stream_information_internal() before calling this function.
+ * @post You can apply this setting by calling sound_manager_apply_stream_routing_options().
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_create_stream_information_internal()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_remove_option_for_stream_routing()
+ * @see sound_manager_apply_stream_routing_options()
+ */
+int sound_manager_add_option_for_stream_routing (sound_stream_info_h stream_info, const char *option);
+
+/**
+ * @brief Removes the option to the stream information for the stream routing.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[in]  option          The option for the stream routing
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Call sound_manager_create_stream_information()/sound_manager_add_option_for_stream_routing() before calling this function.
+ * @post You can apply this setting by calling sound_manager_apply_stream_routing_options().
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_create_stream_information_internal()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_remove_option_for_stream_routing()
+ * @see sound_manager_apply_stream_routing_options()
+ */
+int sound_manager_remove_option_for_stream_routing (sound_stream_info_h stream_info, const char *option);
+
+/**
+ * @brief Applies the stream routing options.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ *
+ * @remarks    @a If the stream has not been made yet, this setting will be applied when the stream starts to play.\n
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @pre Call sound_manager_create_stream_information()/sound_manager_add_option_for_stream_routing() before calling this function.
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_create_stream_information_internal()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_add_option_for_stream_routing()
+ * @see sound_manager_remove_option_for_stream_routing()
+ */
+int sound_manager_apply_stream_routing_options (sound_stream_info_h stream_info);
+
+/**
+ * @internal
+ * @brief Queries if this stream information handle is available for the API.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[in]  api_name        The native API name
+ * @param[out] is_available    If @c true the api_name is available, @c false the api_name is not available for this strema_info
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ */
+int sound_manager_is_available_stream_information (sound_stream_info_h stream_info, native_api_e api_name, bool *is_available);
+
+/**
+ * @internal
+ * @brief Gets stream type from the stream information handle.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[out] type    The stream type
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ */
+int sound_manager_get_type_from_stream_information (sound_stream_info_h stream_info, char **type);
+
+/**
+ * @internal
+ * @brief Gets the index of the stream information handle.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[out] index   The unique index
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ */
+int sound_manager_get_index_from_stream_information (sound_stream_info_h stream_info, int *index);
+
+/**
+ * @internal
+ * @brief Creates a virtual stream handle.
+ * @since_tizen 2.4
+ * @param[in]  stream_info     The handle of stream information
+ * @param[out] virtual_stream  The handle of virtual stream
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @retval #SOUND_MANAGER_ERROR_NOT_SUPPORTED Not supported
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_destroy_virtual_stream()
+ * @see sound_manager_start_virtual_stream()
+ * @see sound_manager_stop_virtual_stream()
+ */
+int sound_manager_create_virtual_stream (sound_stream_info_h stream_info, virtual_sound_stream_h *virtual_stream);
+
+/**
+ * @internal
+ * @brief Destroys the virtual stream handle.
+ * @since_tizen 2.4
+ * @param[in]  virtual_stream  The handle of virtual stream
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INVALID_STATE Invalid state
+ * @see sound_manager_create_virtual_stream()
+ * @see sound_manager_start_virtual_stream()
+ * @see sound_manager_stop_virtual_stream()
+ */
+int sound_manager_destroy_virtual_stream (virtual_sound_stream_h virtual_stream);
+
+/**
+ * @internal
+ * @brief Starts the virtual stream.
+ * @since_tizen 2.4
+ * @param[in]  virtual_stream  The handle of virtual stream
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INVALID_STATE Invalid state
+ * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @see sound_manager_create_virtual_stream()
+ * @see sound_manager_destroy_virtual_stream()
+ * @see sound_manager_stop_virtual_stream()
+ */
+int sound_manager_start_virtual_stream (virtual_sound_stream_h virtual_stream);
+
+/**
+ * @internal
+ * @brief Stops the virtual stream.
+ * @since_tizen 2.4
+ * @param[in]  virtual_stream  The handle of virtual stream
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INVALID_STATE Invalid state
+ * @see sound_manager_create_virtual_stream()
+ * @see sound_manager_destroy_virtual_stream()
+ * @see sound_manager_start_virtual_stream()
+ */
+int sound_manager_stop_virtual_stream (virtual_sound_stream_h virtual_stream);
+
+/**
+ * @}
  */
 
 #ifdef __cplusplus
index 78acfad85b2c3acd0640f156c22506cd2a60b5eb..d44a002d22cf190e8102d1f01210b332c65d3e83 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
 extern "C"
 {
 #endif
+#define LOG_TAG "TIZEN_N_SOUND_MANAGER"
 
 #include <stdio.h>
 #include <limits.h>
@@ -28,16 +29,103 @@ extern "C"
 #include <malloc.h>
 #include <unistd.h>
 #include <dlog.h>
+#include <pulse/error.h>
+#include <pulse/proplist.h>
+#include <pulse/channelmap.h>
+#include <pulse/pulseaudio.h>
+
+#include <gio/gio.h>
+#include <glib.h>
 #include <mm_session.h>
 #include <mm_session_private.h>
 #include <mm_sound.h>
+#include <mm_sound_focus.h>
 #include <mm_sound_private.h>
 #include "sound_manager_internal.h"
 
+#define _CHECK_CONDITION(condition,error,msg)     \
+    if(condition) {} else \
+    { LOGE("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;}; \
+
+#define SM_INSTANCE_CHECK(handle)   \
+        _CHECK_CONDITION(handle != NULL, SOUND_MANAGER_ERROR_INVALID_PARAMETER,"SOUND_MANAGER_ERROR_INVALID_PARAMETER")
+
+#define SM_NULL_ARG_CHECK(arg)      \
+        _CHECK_CONDITION(arg != NULL,SOUND_MANAGER_ERROR_INVALID_PARAMETER,"SOUND_MANAGER_ERROR_INVALID_PARAMETER")
+
+#define SM_STATE_CHECK(handle,expected_state)       \
+        _CHECK_CONDITION(handle->state == expected_state,SOUND_MANAGER_ERROR_INVALID_STATE,"SOUND_MANAGER_ERROR_INVALID_STATE")
+
+#define SM_RANGE_ARG_CHECK(arg, min, max)      \
+        _CHECK_CONDITION(arg <= max,SOUND_MANAGER_ERROR_INVALID_PARAMETER,"SOUND_MANAGER_ERROR_INVALID_PARAMETER") \
+        _CHECK_CONDITION(arg >= min,SOUND_MANAGER_ERROR_INVALID_PARAMETER,"SOUND_MANAGER_ERROR_INVALID_PARAMETER")
+
 #define SOUND_SESSION_TYPE_DEFAULT SOUND_SESSION_TYPE_MEDIA
+#define SOUND_STREAM_INFO_ARR_MAX 128
+#define SOUND_STREAM_TYPE_LEN 64
+#define SOUND_STREAM_DIRECTION_MAX 2
+#define SOUND_DEVICE_TYPE_LEN 64
 
-typedef enum
-{
+typedef enum _sound_stream_direction {
+       SOUND_STREAM_DIRECTION_OUTPUT = 1,
+       SOUND_STREAM_DIRECTION_INPUT
+} sound_stream_direction_e;
+
+/* it should be synchronized with pulseaudio's */
+typedef enum stream_route_type {
+       STREAM_ROUTE_TYPE_AUTO,     /* the policy of decision device(s) is automatic and it's routing path is particular to one device */
+       STREAM_ROUTE_TYPE_AUTO_ALL, /* the policy of decision device(s) is automatic and it's routing path can be several devices */
+       STREAM_ROUTE_TYPE_MANUAL,   /* the policy of decision device(s) is manual */
+} stream_route_type;
+#define AVAIL_DEVICES_MAX 16
+#define AVAIL_FRAMEWORKS_MAX 16
+#define ROUTE_OPTIONS_MAX 16
+
+typedef struct _stream_conf_info_s {
+       int priority;
+       int route_type;
+       gchar *avail_in_devices[AVAIL_DEVICES_MAX];
+       gchar *avail_out_devices[AVAIL_DEVICES_MAX];
+       gchar *avail_frameworks[AVAIL_FRAMEWORKS_MAX];
+} stream_conf_info_s;
+
+typedef struct _manual_route_info_s {
+       char *route_in_devices[AVAIL_DEVICES_MAX];
+       char *route_out_devices[AVAIL_DEVICES_MAX];
+       int route_in_devices_idx[AVAIL_DEVICES_MAX];
+       int route_out_devices_idx[AVAIL_DEVICES_MAX];
+} manual_route_info_s;
+
+typedef struct _sound_stream_info_s {
+       unsigned int index;
+       char stream_type[SOUND_STREAM_TYPE_LEN];
+       pa_threaded_mainloop *pa_mainloop;
+       pa_context *pa_context;
+       stream_conf_info_s stream_conf_info;
+       sound_stream_focus_mask_e acquired_focus;
+       sound_stream_focus_state_changed_cb user_cb;
+       void *user_data;
+       manual_route_info_s manual_route_info;
+       char *route_options[ROUTE_OPTIONS_MAX];
+} sound_stream_info_s;
+sound_stream_info_s *sound_stream_info_arr[SOUND_STREAM_INFO_ARR_MAX];
+
+typedef enum {
+       _VSTREAM_STATE_READY,
+       _VSTREAM_STATE_RUNNING,
+} _vstream_state;
+
+typedef struct _virtual_stream_info_s {
+       _vstream_state state;
+       char stream_type[SOUND_STREAM_TYPE_LEN];
+       pa_threaded_mainloop *pa_mainloop;
+       pa_context *pa_context;
+       pa_stream *pa_stream[SOUND_STREAM_DIRECTION_MAX];
+       pa_proplist *pa_proplist;
+       stream_conf_info_s *stream_conf_info;
+} virtual_sound_stream_info_s;
+
+typedef enum {
        _SESSION_MODE_RINGTONE = 0,                /**< session mode(voip/call) for ringtone */
        _SESSION_MODE_VOICE_WITH_BUILTIN_RECEIVER, /**< session mode(voip/call) for during call with built-in receiver */
        _SESSION_MODE_VOICE_WITH_BUILTIN_SPEAKER,  /**< session mode(voip/call) for during call with built-in speaker */
@@ -56,6 +144,11 @@ typedef struct {
        sound_manager_volume_changed_cb user_cb;
 }_volume_changed_info_s;
 
+typedef struct {
+       void *user_data;
+       sound_stream_focus_state_watch_cb user_cb;
+}_focus_watch_info_s;
+
 typedef struct {
        void *user_data;
        sound_device_connected_cb user_cb;
@@ -66,13 +159,62 @@ typedef struct {
        sound_device_information_changed_cb user_cb;
 }_device_changed_info_s;
 
-int __convert_sound_manager_error_code(const char *func, int code);
+#define SOUND_STRNCPY(dst,src,size,err) \
+do { \
+       if(src != NULL && dst != NULL && size > 0) { \
+               strncpy(dst,src,size); \
+               dst[size-1] = '\0'; \
+       } else if(dst == NULL) { \
+               LOGE("STRNCPY ERROR: Destination String is NULL\n"); \
+               err = MM_ERROR_SOUND_INTERNAL; \
+       } else if(size <= 0) { \
+               LOGE("STRNCPY ERROR: Destination String is NULL\n"); \
+               err = MM_ERROR_SOUND_INTERNAL; \
+       } else { \
+               LOGE("STRNCPY ERROR: Destination String is NULL\n"); \
+               err = MM_ERROR_SOUND_INTERNAL; \
+       } \
+} while(0)
+
+void _focus_state_change_callback (int index, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data);
+
+void _focus_watch_callback (mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data);
+
+int __convert_sound_manager_error_code (const char *func, int code);
+
+int __find_empty_slot (int *index);
+
+int __convert_stream_type (sound_stream_type_e enum_type, char *stream_type);
+
+int __convert_stream_type_for_internal (sound_stream_type_internal_e stream_type_enum, char *stream_type);
+
+int __convert_stream_type_to_change_reason (const char *stream_type, sound_stream_focus_change_reason_e *change_reason);
+
+int __convert_device_type (sound_device_type_e device_type_enum, char *device_type);
+
+int __convert_device_type_to_enum (char *device_type, sound_device_type_e *device_type_enum);
+
+const char* __convert_api_name (native_api_e api_name);
+
+int __get_stream_conf_info (const char *stream_type, stream_conf_info_s *info);
+
+int __set_manual_route_info (unsigned int index, manual_route_info_s *info);
+
+int __set_route_options (unsigned int index, char **route_options);
+
+void _pa_context_state_cb (pa_context *c, void *userdata);
+
+void _pa_stream_state_cb (pa_stream *s, void * userdata);
+
+void _session_interrupt_cb (session_msg_t msg, session_event_t event, void *user_data);
+
+int __set_session_mode (_session_mode_e mode);
 
-void __session_interrupt_cb(session_msg_t msg, session_event_t event, void *user_data);
+int __get_session_mode (_session_mode_e *mode);
 
-int __set_session_mode(_session_mode_e mode);
+int _make_pa_connection_and_register_focus(sound_stream_info_s *stream_h, sound_stream_focus_state_changed_cb callback, void *user_data);
 
-int __get_session_mode(_session_mode_e *mode);
+int _destroy_pa_connection_and_unregister_focus(sound_stream_info_s *stream_h);
 
 #ifdef __cplusplus
 }
index daf0fade6a50512b114c01e73f295619b5b34385..9093111339506ec77688faa6e5d8c7161b9cc41c 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       capi-media-sound-manager
 Summary:    Sound Manager library
-Version:    0.2.28
+Version:    0.3.0
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
@@ -12,6 +12,8 @@ BuildRequires:  pkgconfig(mm-sound)
 BuildRequires:  pkgconfig(mm-session)
 BuildRequires:  pkgconfig(capi-base-common)
 BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(libpulse)
+BuildRequires:  pkgconfig(gio-2.0)
 Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
 Requires(post): libprivilege-control
index a1a8d9690c26d9cc451ae42c9556a3e03ef1056a..f7126da91b5fb4f8cc6cb6dfdf8cd0390f3bc0b8 100644 (file)
 * limitations under the License.
 */
 
-
-#define LOG_TAG "TIZEN_N_SOUND_MANAGER"
-
-#include <sound_manager.h>
-#include <sound_manager_private.h>
-
-typedef struct {
-       void *user_data;
-       sound_manager_volume_changed_cb user_cb;
-}_changed_volume_info_s;
+#include "sound_manager.h"
+#include "sound_manager_private.h"
 
 _session_interrupt_info_s g_session_interrupt_cb_table = {0, NULL, NULL};
 _volume_changed_info_s g_volume_changed_cb_table = {NULL, NULL};
+_focus_watch_info_s g_focus_watch_cb_table = {NULL, NULL};
 _device_connected_info_s g_device_connected_cb_table = {NULL, NULL};
 _device_changed_info_s g_device_info_changed_cb_table = {NULL, NULL};
 
 sound_session_type_e g_cached_session = -1;
 _session_mode_e g_cached_session_mode = -1;
 
-int sound_manager_get_max_volume(sound_type_e type, int *max)
+int sound_manager_get_max_volume (sound_type_e type, int *max)
 {
        int volume;
        if(max == NULL)
@@ -49,7 +42,7 @@ int sound_manager_get_max_volume(sound_type_e type, int *max)
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_set_volume(sound_type_e type, int volume)
+int sound_manager_set_volume (sound_type_e type, int volume)
 {
        if(type >= SOUND_TYPE_NUM || type < 0)
                return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
@@ -57,12 +50,12 @@ int sound_manager_set_volume(sound_type_e type, int volume)
                return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
 
        int ret = mm_sound_volume_set_value(type, volume);
-       LOGI("returns : type=%d, volume=%d, ret=0x%x", type, volume, ret);
+       LOGI("returns : type=%d, volume=%d, ret=%p", type, volume, ret);
 
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_get_volume(sound_type_e type, int *volume)
+int sound_manager_get_volume (sound_type_e type, int *volume)
 {
        unsigned int uvolume;
        if(type >= SOUND_TYPE_NUM || type < 0)
@@ -74,12 +67,12 @@ int sound_manager_get_volume(sound_type_e type, int *volume)
        if(ret == 0)
                *volume = uvolume;
 
-       LOGI("returns : type=%d, volume=%d, ret=0x%x", type, *volume, ret);
+       LOGI("returns : type=%d, volume=%d, ret=%p", type, *volume, ret);
 
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_set_current_sound_type(sound_type_e type)
+int sound_manager_set_current_sound_type (sound_type_e type)
 {
        int ret = MM_ERROR_NONE;
        if(type >= SOUND_TYPE_NUM || type < 0)
@@ -90,19 +83,19 @@ int sound_manager_set_current_sound_type(sound_type_e type)
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_get_current_sound_type(sound_type_e *type)
+int sound_manager_get_current_sound_type (sound_type_e *type)
 {
        int ret = MM_ERROR_NONE;
        if(type == NULL)
                return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
        ret = mm_sound_volume_get_current_playing_type((volume_type_t *)type);
 
-       LOGI("returns : type=%d, ret=0x%x", *type, ret);
+       LOGI("returns : type=%d, ret=%p", *type, ret);
 
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_unset_current_sound_type(void)
+int sound_manager_unset_current_sound_type (void)
 {
        int ret = MM_ERROR_NONE;
        ret = mm_sound_volume_primary_type_clear();
@@ -110,7 +103,7 @@ int sound_manager_unset_current_sound_type(void)
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
+int sound_manager_set_volume_changed_cb (sound_manager_volume_changed_cb callback, void* user_data)
 {
        int ret = MM_ERROR_NONE;
 
@@ -123,7 +116,7 @@ int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_unset_volume_changed_cb(void)
+int sound_manager_unset_volume_changed_cb (void)
 {
        int ret = MM_ERROR_NONE;
 
@@ -140,7 +133,349 @@ int sound_manager_unset_volume_changed_cb(void)
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_set_session_type(sound_session_type_e type)
+int sound_manager_create_stream_information (sound_stream_type_e stream_type, sound_stream_focus_state_changed_cb callback, void *user_data, sound_stream_info_h *stream_info)
+{
+       int ret = MM_ERROR_NONE;
+
+       LOGI(">> enter");
+
+       SM_NULL_ARG_CHECK(stream_info);
+       SM_NULL_ARG_CHECK(callback);
+
+       sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
+       if (!stream_h) {
+               ret = MM_ERROR_OUT_OF_MEMORY;
+       } else {
+               memset(stream_h, 0, sizeof(sound_stream_info_s));
+               ret = __convert_stream_type(stream_type, stream_h->stream_type);
+               if (ret == MM_ERROR_NONE) {
+                       ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
+                       if (!ret) {
+                               *stream_info = (sound_stream_info_h)stream_h;
+                               LOGI("<< leave : stream_h(%p), index(%u), user_cb(%p), ret(%p)", stream_h, stream_h->index, stream_h->user_cb, ret);
+                       }
+               }
+       }
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_destroy_stream_information (sound_stream_info_h stream_info)
+{
+       int ret = MM_ERROR_NONE;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+
+       ret = _destroy_pa_connection_and_unregister_focus(stream_h);
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_add_device_for_stream_routing (sound_stream_info_h stream_info, sound_device_h device)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+       int j = 0;
+       bool added_successfully = false;
+       char device_type_str[SOUND_DEVICE_TYPE_LEN] = {0,};
+       mm_sound_device_type_e device_type;
+       mm_sound_device_io_direction_e device_direction;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+       SM_NULL_ARG_CHECK(device);
+
+       if (stream_h->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL) {
+               ret = mm_sound_get_device_type(device, &device_type);
+               if (ret) {
+                       return __convert_sound_manager_error_code(__func__, ret);
+               }
+               ret = __convert_device_type(device_type, device_type_str);
+               if (ret) {
+                       return __convert_sound_manager_error_code(__func__, ret);
+               }
+               ret = mm_sound_get_device_io_direction(device, &device_direction);
+               if (ret) {
+                       return __convert_sound_manager_error_code(__func__, ret);
+               }
+               if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
+                       for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
+                               if (stream_h->stream_conf_info.avail_in_devices[i]) {
+                                       if(!strncmp(stream_h->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
+                                               for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
+                                                       if (!stream_h->manual_route_info.route_in_devices[j]) {
+                                                               stream_h->manual_route_info.route_in_devices[j] = strdup(device_type_str);
+                                                               added_successfully = true;
+                                                               break;
+                                                       }
+                                                       if (!strncmp(stream_h->manual_route_info.route_in_devices[j], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
+                                                               /* it was already set */
+                                                               return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_DUPLICATED);
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       break;
+                               }
+                       }
+               }
+               if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
+                       for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
+                               if (stream_h->stream_conf_info.avail_out_devices[i]) {
+                                       if(!strncmp(stream_h->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
+                                               for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
+                                                       if (!stream_h->manual_route_info.route_out_devices[j]) {
+                                                               stream_h->manual_route_info.route_out_devices[j] = strdup(device_type_str);
+                                                               added_successfully = true;
+                                                               break;
+                                                       }
+                                                       if (!strncmp(stream_h->manual_route_info.route_out_devices[j], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
+                                                               /* it was already set */
+                                                               return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_DUPLICATED);
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (!added_successfully) {
+               ret = MM_ERROR_POLICY_INTERNAL;
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_remove_device_for_stream_routing (sound_stream_info_h stream_info, sound_device_h device)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+       int j = 0;
+       bool removed_successfully = false;
+       char device_type_str[SOUND_DEVICE_TYPE_LEN] = {0,};
+       mm_sound_device_type_e device_type;
+       mm_sound_device_io_direction_e device_direction;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+       SM_NULL_ARG_CHECK(device);
+
+       if (stream_h->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL) {
+               ret = mm_sound_get_device_type(device, &device_type);
+               if (ret) {
+                       return __convert_sound_manager_error_code(__func__, ret);
+               }
+               ret = __convert_device_type(device_type, device_type_str);
+               if (ret) {
+                       return __convert_sound_manager_error_code(__func__, ret);
+               }
+               ret = mm_sound_get_device_io_direction(device, &device_direction);
+               if (ret) {
+                       return __convert_sound_manager_error_code(__func__, ret);
+               }
+               if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
+                       for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
+                               if (stream_h->stream_conf_info.avail_in_devices[i]) {
+                                       if(!strncmp(stream_h->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
+                                               for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
+                                                       if (!strncmp(stream_h->manual_route_info.route_in_devices[j], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
+                                                               removed_successfully = true;
+                                                               free(stream_h->manual_route_info.route_in_devices[j]);
+                                                               stream_h->manual_route_info.route_in_devices[j] = NULL;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       break;
+                               }
+                       }
+               }
+               if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
+                       for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
+                               if (stream_h->stream_conf_info.avail_out_devices[i]) {
+                                       if(!strncmp(stream_h->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
+                                               for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
+                                                       if (!strncmp(stream_h->manual_route_info.route_out_devices[j], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
+                                                               removed_successfully = true;
+                                                               free(stream_h->manual_route_info.route_out_devices[j]);
+                                                               stream_h->manual_route_info.route_out_devices[j] = NULL;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (!removed_successfully) {
+               ret = MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_apply_stream_routing (sound_stream_info_h stream_info)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+       bool need_to_apply = false;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+
+       if (stream_h->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL) {
+               for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
+                       if (stream_h->manual_route_info.route_in_devices[i]) {
+                               need_to_apply = true;
+                               break;
+                       }
+                       if (stream_h->manual_route_info.route_out_devices[i]) {
+                               need_to_apply = true;
+                               break;
+                       }
+               }
+               if (need_to_apply) {
+                       ret = __set_manual_route_info(stream_h->index, &stream_h->manual_route_info);
+               } else {
+                       __convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_STATE);
+               }
+       } else {
+               ret = MM_ERROR_SOUND_INVALID_STATE;
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_acquire_focus (sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info)
+{
+       int ret = MM_ERROR_NONE;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+
+       ret = mm_sound_acquire_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, additional_info);
+       if (ret == MM_ERROR_NONE) {
+               stream_h->acquired_focus |= focus_mask;
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_release_focus (sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info)
+{
+       int ret = MM_ERROR_NONE;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+
+       ret = mm_sound_release_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, additional_info);
+       if (ret == MM_ERROR_NONE) {
+               stream_h->acquired_focus &= ~focus_mask;
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_get_focus_state (sound_stream_info_h stream_info, sound_stream_focus_state_e *state_for_playback, sound_stream_focus_state_e *state_for_recording)
+{
+       int ret = MM_ERROR_NONE;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+       if (!state_for_playback && !state_for_recording)
+               ret = MM_ERROR_INVALID_ARGUMENT;
+
+       if (state_for_playback)
+               *state_for_playback = (stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK)?SOUND_STREAM_FOCUS_STATE_ACQUIRED:SOUND_STREAM_FOCUS_STATE_RELEASED;
+       if (state_for_recording)
+               *state_for_recording = (stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING)?SOUND_STREAM_FOCUS_STATE_ACQUIRED:SOUND_STREAM_FOCUS_STATE_RELEASED;
+
+       LOGI("<< leave : acquired_focus(%p)", stream_h->acquired_focus);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_set_focus_state_watch_cb (sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data)
+{
+       int ret = MM_ERROR_NONE;
+
+       LOGI(">> enter");
+
+       SM_NULL_ARG_CHECK(callback);
+
+       if (!g_focus_watch_cb_table.user_cb) {
+               ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data);
+               if (ret == MM_ERROR_NONE) {
+                       g_focus_watch_cb_table.user_cb = callback;
+                       g_focus_watch_cb_table.user_data = user_data;
+               }
+       } else {
+               ret = MM_ERROR_SOUND_INTERNAL;
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_unset_focus_state_watch_cb (void)
+{
+       int ret = MM_ERROR_NONE;
+
+       LOGI(">> enter");
+
+       if (g_focus_watch_cb_table.user_cb) {
+               ret = mm_sound_unset_focus_watch_callback();
+               if (ret == MM_ERROR_NONE) {
+                       g_focus_watch_cb_table.user_cb = NULL;
+                       g_focus_watch_cb_table.user_data = NULL;
+               } else {
+                       ret = MM_ERROR_SOUND_INTERNAL;
+               }
+       } else {
+               ret = MM_ERROR_SOUND_INTERNAL;
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_set_session_type (sound_session_type_e type)
 {
        int ret = MM_ERROR_NONE;
        int cur_session = -1;
@@ -190,7 +525,7 @@ int sound_manager_set_session_type(sound_session_type_e type)
        if(g_session_interrupt_cb_table.is_registered) {
                if (new_session == cur_session ||
                        ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
-                       LOGI("<< leave : already set type=%d, ret=0x%x", type, ret);
+                       LOGI("<< leave : already set type=%d, ret=%p", type, ret);
                        return SOUND_MANAGER_ERROR_NONE;
                } else {
                        ret = mm_session_finish();
@@ -201,7 +536,7 @@ int sound_manager_set_session_type(sound_session_type_e type)
                        g_cached_session_mode = -1;
                }
        }
-       ret = mm_session_init_ex(new_session , __session_interrupt_cb, NULL);
+       ret = mm_session_init_ex(new_session , _session_interrupt_cb, NULL);
        if(ret == 0){
                g_session_interrupt_cb_table.is_registered = 1;
        }
@@ -213,12 +548,12 @@ int sound_manager_set_session_type(sound_session_type_e type)
                }
                g_cached_session_mode = _SESSION_MODE_RINGTONE;
        }
-       LOGI("<< leave : type=%d, ret=0x%x", type, ret);
+       LOGI("<< leave : type=%d, ret=%p", type, ret);
 
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_get_session_type(sound_session_type_e *type)
+int sound_manager_get_session_type (sound_session_type_e *type)
 {
        int ret = MM_ERROR_NONE;
        int cur_session;
@@ -262,12 +597,12 @@ int sound_manager_get_session_type(sound_session_type_e *type)
                break;
        }
 
-       LOGI("returns : type=%d, ret=0x%x", *type, ret);
+       LOGI("returns : type=%d, ret=%p", *type, ret);
 
        return 0;
 }
 
-int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
+int sound_manager_set_media_session_option (sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
 {
        int ret = MM_ERROR_NONE;
        int session = 0;
@@ -347,7 +682,7 @@ int sound_manager_set_media_session_option(sound_session_option_for_starting_e s
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
+int sound_manager_get_media_session_option (sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
 {
        int ret = MM_ERROR_NONE;
        int session = 0;
@@ -388,7 +723,7 @@ int sound_manager_get_media_session_option(sound_session_option_for_starting_e *
        return SOUND_MANAGER_ERROR_NONE;
 }
 
-int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
+int sound_manager_set_media_session_resumption_option (sound_session_option_for_resumption_e option)
 {
        int ret = MM_ERROR_NONE;
        int session = 0;
@@ -445,7 +780,7 @@ int sound_manager_set_media_session_resumption_option(sound_session_option_for_r
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
+int sound_manager_get_media_session_resumption_option (sound_session_option_for_resumption_e *option)
 {
        int ret = MM_ERROR_NONE;
        int session = 0;
@@ -480,7 +815,7 @@ int sound_manager_get_media_session_resumption_option(sound_session_option_for_r
        return SOUND_MANAGER_ERROR_NONE;
 }
 
-int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
+int sound_manager_set_voip_session_mode (sound_session_voip_mode_e mode)
 {
        int ret = MM_ERROR_NONE;
        int session = 0;
@@ -500,12 +835,12 @@ int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
        }
        ret = __set_session_mode ((_session_mode_e)mode);
 
-       LOGI("<< leave : session=%p, mode=%d, ret=0x%x", session, mode, ret);
+       LOGI("<< leave : session=%p, mode=%d, ret=%p", session, mode, ret);
 
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
+int sound_manager_get_voip_session_mode (sound_session_voip_mode_e *mode)
 {
        int ret = MM_ERROR_NONE;
        int session = 0;
@@ -526,12 +861,12 @@ int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
        if (ret == MM_ERROR_NONE)
                *mode = (sound_session_voip_mode_e)_mode;
 
-       LOGI("returns : session=%p, mode=%d, ret=0x%x", session, *mode, ret);
+       LOGI("returns : session=%p, mode=%d, ret=%p", session, *mode, ret);
 
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_set_call_session_mode(sound_session_call_mode_e mode)
+int sound_manager_set_call_session_mode (sound_session_call_mode_e mode)
 {
        int ret = MM_ERROR_NONE;
        int session = 0;
@@ -551,12 +886,12 @@ int sound_manager_set_call_session_mode(sound_session_call_mode_e mode)
        }
        ret = __set_session_mode ((_session_mode_e)mode);
 
-       LOGI("<< leave : session=%p, mode=%d, ret=0x%x", session, mode, ret);
+       LOGI("<< leave : session=%p, mode=%d, ret=%p", session, mode, ret);
 
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_get_call_session_mode(sound_session_call_mode_e *mode)
+int sound_manager_get_call_session_mode (sound_session_call_mode_e *mode)
 {
        int ret = MM_ERROR_NONE;
        int session = 0;
@@ -577,19 +912,19 @@ int sound_manager_get_call_session_mode(sound_session_call_mode_e *mode)
        if (ret == MM_ERROR_NONE)
                *mode = (sound_session_call_mode_e)_mode;
 
-       LOGI("returns : session=%p, mode=%d, ret=0x%x", session, *mode, ret);
+       LOGI("returns : session=%p, mode=%d, ret=%p", session, *mode, ret);
 
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
+int sound_manager_set_session_interrupted_cb (sound_session_interrupted_cb callback, void *user_data)
 {
        int ret = MM_ERROR_NONE;
        if(callback == NULL)
                return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
 
        if(g_session_interrupt_cb_table.is_registered ==0){
-               ret = mm_session_init_ex(SOUND_SESSION_TYPE_DEFAULT /*default*/ , __session_interrupt_cb, NULL);
+               ret = mm_session_init_ex(SOUND_SESSION_TYPE_DEFAULT /*default*/ , _session_interrupt_cb, NULL);
                if(ret != 0)
                        return __convert_sound_manager_error_code(__func__, ret);
                g_session_interrupt_cb_table.is_registered = 1;
@@ -600,7 +935,7 @@ int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callba
        return SOUND_MANAGER_ERROR_NONE;
 }
 
-int sound_manager_unset_session_interrupted_cb(void)
+int sound_manager_unset_session_interrupted_cb (void)
 {
        int ret = MM_ERROR_NONE;
        if (g_session_interrupt_cb_table.user_cb) {
@@ -612,7 +947,7 @@ int sound_manager_unset_session_interrupted_cb(void)
        return __convert_sound_manager_error_code(__func__, ret);
 }
 
-int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
+int sound_manager_get_current_device_list (sound_device_mask_e device_mask, sound_device_list_h *device_list)
 {
        int ret = MM_ERROR_NONE;
        ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
@@ -733,7 +1068,7 @@ int sound_manager_unset_device_information_changed_cb (void)
 }
 
 __attribute__ ((destructor))
-void __sound_manager_finalize(void)
+void __sound_manager_finalize (void)
 {
        int ret = MM_ERROR_NONE;
 
@@ -741,7 +1076,7 @@ void __sound_manager_finalize(void)
                LOGI("<ENTER>");
                ret = mm_session_finish();
                if (ret != MM_ERROR_NONE) {
-                       LOGE("[%s] failed to mm_session_finish(), ret(0x%x)", __func__, ret);
+                       LOGE("[%s] failed to mm_session_finish(), ret(%p)", __func__, ret);
                }
                g_session_interrupt_cb_table.is_registered = 0;
                LOGI("<LEAVE>");
@@ -749,7 +1084,7 @@ void __sound_manager_finalize(void)
 }
 
 __attribute__ ((constructor))
-void __sound_manager_initialize(void)
+void __sound_manager_initialize (void)
 {
 
 }
diff --git a/src/sound_manager_internal.c b/src/sound_manager_internal.c
new file mode 100644 (file)
index 0000000..bbddeff
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <sound_manager.h>
+#include <sound_manager_private.h>
+#include <sound_manager_internal.h>
+#include <mm_sound.h>
+
+int sound_manager_create_stream_information_internal (sound_stream_type_internal_e stream_type, sound_stream_focus_state_changed_cb callback, void *user_data, sound_stream_info_h *stream_info)
+{
+       int ret = MM_ERROR_NONE;
+
+       LOGI(">> enter");
+
+       SM_NULL_ARG_CHECK(stream_info);
+       SM_NULL_ARG_CHECK(callback);
+
+       sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
+       if (!stream_h) {
+               ret = MM_ERROR_OUT_OF_MEMORY;
+       } else {
+               memset(stream_h, 0, sizeof(sound_stream_info_s));
+               ret = __convert_stream_type_for_internal(stream_type, stream_h->stream_type);
+               if (ret == MM_ERROR_NONE) {
+                       ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
+                       if (!ret) {
+                               *stream_info = (sound_stream_info_h)stream_h;
+                               LOGI("<< leave : stream_h(%p), index(%u), user_cb(%p), ret(%p)", stream_h, stream_h->index, stream_h->user_cb, ret);
+                       }
+               }
+       }
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_add_option_for_stream_routing (sound_stream_info_h stream_info, const char *option)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+       bool added_successfully = false;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+       SM_NULL_ARG_CHECK(option);
+
+       for (i = 0; i < ROUTE_OPTIONS_MAX; i++) {
+               if (stream_h->route_options[i]) {
+                       if (!strncmp (stream_h->route_options[i], option, strlen(option))) {
+                               return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
+                       }
+                       continue;
+               } else {
+                       stream_h->route_options[i] = strdup(option);
+                       added_successfully = true;
+                       break;
+               }
+       }
+
+       if (!added_successfully) {
+               ret = MM_ERROR_SOUND_INTERNAL;
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_remove_option_for_stream_routing (sound_stream_info_h stream_info, const char *option)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+       bool removed_successfully = false;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+       SM_NULL_ARG_CHECK(option);
+
+       for (i = 0; i < ROUTE_OPTIONS_MAX; i++) {
+               if (stream_h->route_options[i] && !strncmp (stream_h->route_options[i], option, strlen(option))) {
+                       free(stream_h->route_options[i]);
+                       stream_h->route_options[i] = NULL;
+                       removed_successfully = true;
+                       break;
+               }
+       }
+
+       if (!removed_successfully) {
+               ret = MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_apply_stream_routing_options (sound_stream_info_h stream_info)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+       bool need_to_apply = false;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+
+       for (i = 0; i < ROUTE_OPTIONS_MAX; i++) {
+               if (stream_h->route_options[i]) {
+                       need_to_apply = true;
+                       break;
+               }
+       }
+       if (need_to_apply) {
+               ret = __set_route_options(stream_h->index, stream_h->route_options);
+       } else {
+               __convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_is_available_stream_information (sound_stream_info_h stream_info, native_api_e api_name, bool *is_available)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+       const char *name = NULL;
+       sound_stream_info_s* stream_h = (sound_stream_info_s*)stream_info;
+
+       SM_INSTANCE_CHECK(stream_h);
+       SM_NULL_ARG_CHECK(is_available);
+       *is_available = false;
+
+       name = __convert_api_name(api_name);
+       for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++) {
+               if (stream_h->stream_conf_info.avail_frameworks[i] && !strncmp(stream_h->stream_conf_info.avail_frameworks[i], name, strlen(name))) {
+                       *is_available = true;
+               } else {
+                       break;
+               }
+       }
+       LOGI("stream_type[%s], native api[%s], is_available[%d]", stream_h->stream_type, name, *is_available);
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_get_type_from_stream_information (sound_stream_info_h stream_info, char **type)
+{
+       int ret = MM_ERROR_NONE;
+       sound_stream_info_s* stream_h = (sound_stream_info_s*)stream_info;
+
+       SM_INSTANCE_CHECK(stream_h);
+       SM_NULL_ARG_CHECK(type);
+
+       *type = stream_h->stream_type;
+       LOGI("stream_type[%s]", *type);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+int sound_manager_get_index_from_stream_information (sound_stream_info_h stream_info, int *index)
+{
+       int ret = MM_ERROR_NONE;
+       sound_stream_info_s* stream_h = (sound_stream_info_s*)stream_info;
+       SM_INSTANCE_CHECK(stream_h);
+       SM_NULL_ARG_CHECK(index);
+
+       *index = stream_h->index;
+       LOGI("stream_index[%d]", stream_h->index);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_create_virtual_stream (sound_stream_info_h stream_info, virtual_sound_stream_h *virtual_stream)
+{
+       int ret = MM_ERROR_NONE;
+       bool result = false;
+       virtual_sound_stream_info_s *vstream_h = NULL;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(virtual_stream);
+       SM_INSTANCE_CHECK(stream_h);
+
+       /* check if this stream_info is available for virtual stream */
+       ret = sound_manager_is_available_stream_information(stream_info, NATIVE_API_SOUND_MANAGER, &result);
+       if (ret == MM_ERROR_NONE && result == true) {
+               vstream_h = malloc(sizeof(virtual_sound_stream_info_s));
+               if(!vstream_h) {
+                       ret = MM_ERROR_OUT_OF_MEMORY;
+               } else {
+                       memset(vstream_h, 0, sizeof(virtual_sound_stream_info_s));
+                       memcpy(vstream_h->stream_type, stream_h->stream_type, SOUND_STREAM_TYPE_LEN);
+                       vstream_h->pa_mainloop = stream_h->pa_mainloop;
+                       vstream_h->pa_context = stream_h->pa_context;
+                       vstream_h->pa_proplist = pa_proplist_new();
+                       pa_proplist_sets(vstream_h->pa_proplist, PA_PROP_MEDIA_ROLE, vstream_h->stream_type);
+                       pa_proplist_setf(vstream_h->pa_proplist, PA_PROP_MEDIA_PARENT_ID, "%u", stream_h->index);
+                       vstream_h->state = _VSTREAM_STATE_READY;
+                       vstream_h->stream_conf_info = &(stream_h->stream_conf_info);
+                       *virtual_stream = (virtual_sound_stream_h)vstream_h;
+               }
+       } else {
+               ret = MM_ERROR_SOUND_NOT_SUPPORTED_OPERATION;
+       }
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_destroy_virtual_stream (virtual_sound_stream_h virtual_stream)
+{
+       int ret = MM_ERROR_NONE;
+       virtual_sound_stream_info_s *vstream_h = (virtual_sound_stream_info_s*)virtual_stream;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(vstream_h);
+       SM_STATE_CHECK(vstream_h, _VSTREAM_STATE_READY);
+
+       vstream_h->pa_mainloop = NULL;
+       vstream_h->pa_context = NULL;
+       if (vstream_h->pa_proplist)
+               pa_proplist_free(vstream_h->pa_proplist);
+
+       free(vstream_h);
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_start_virtual_stream (virtual_sound_stream_h virtual_stream)
+{
+       int ret = MM_ERROR_NONE;
+       int pa_ret = PA_OK;
+       int i = 0;
+       int io_direction = 0;
+       pa_sample_spec ss;
+       pa_channel_map maps;
+
+       virtual_sound_stream_info_s *vstream_h = (virtual_sound_stream_info_s*)virtual_stream;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(vstream_h);
+       SM_STATE_CHECK(vstream_h, _VSTREAM_STATE_READY);
+
+       /* check route-type(auto/manual) and error handling as per the type */
+       if (vstream_h->stream_conf_info->route_type == STREAM_ROUTE_TYPE_MANUAL) {
+               /* TODO : check if the device info. is set when it comes to the manual route type */
+               /* if no, return error */
+       }
+
+       /* fill up with default value */
+       ss.channels = 2;
+       ss.rate = 44100;
+       ss.format = PA_SAMPLE_S16LE;
+       pa_channel_map_init_auto(&maps, ss.channels, PA_CHANNEL_MAP_ALSA);
+
+       /* check direction of this stream */
+       if (vstream_h->stream_conf_info->avail_in_devices[0] != NULL)
+               io_direction |= SOUND_STREAM_DIRECTION_INPUT;
+       if (vstream_h->stream_conf_info->avail_out_devices[0] != NULL)
+               io_direction |= SOUND_STREAM_DIRECTION_OUTPUT;
+
+       /* LOCK the pa_threaded_mainloop */
+       pa_threaded_mainloop_lock(vstream_h->pa_mainloop);
+
+       for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
+               if (io_direction & (i + 1)) {
+                       vstream_h->pa_stream[i] = pa_stream_new_with_proplist(vstream_h->pa_context, "VIRTUAL_STREAM", &ss, &maps, vstream_h->pa_proplist);
+                       if(vstream_h->pa_stream[i] == NULL) {
+                               LOGE("failed to pa_stream_new_with_proplist()");
+                               pa_ret = pa_context_errno(vstream_h->pa_context);
+                               goto ERROR_WITH_UNLOCK;
+                       }
+                       pa_stream_set_state_callback(vstream_h->pa_stream[i], _pa_stream_state_cb, vstream_h);
+
+                       if ((i + 1) == SOUND_STREAM_DIRECTION_OUTPUT) {
+                               pa_ret = pa_stream_connect_playback(vstream_h->pa_stream[i], NULL, NULL, 0, NULL, NULL);
+                               if (pa_ret < 0) {
+                                       LOGE("failed to pa_stream_connect_playback()");
+                                       pa_ret = pa_context_errno(vstream_h->pa_context);
+                                       goto ERROR_WITH_UNLOCK;
+                               }
+                       } else if ((i + 1) == SOUND_STREAM_DIRECTION_INPUT) {
+                               pa_ret = pa_stream_connect_record(vstream_h->pa_stream[i], NULL, NULL, 0);
+                               if (pa_ret < 0) {
+                                       LOGE("failed to pa_stream_connect_record()");
+                                       pa_ret = pa_context_errno(vstream_h->pa_context);
+                                       goto ERROR_WITH_UNLOCK;
+                               }
+                       }
+
+                       /* wait for ready state of the stream */
+                       for (;;) {
+                               pa_stream_state_t state;
+                               state = pa_stream_get_state(vstream_h->pa_stream[i]);
+                               if (state == PA_STREAM_READY) {
+                                       break;
+                               }
+                               if (!PA_STREAM_IS_GOOD(state)) {
+                                       pa_ret = pa_context_errno(vstream_h->pa_context);
+                               }
+                               pa_threaded_mainloop_wait(vstream_h->pa_mainloop);
+                       }
+               }
+       }
+       vstream_h->state = _VSTREAM_STATE_RUNNING;
+
+       /* UNLOCK the pa_threaded_mainloop */
+       pa_threaded_mainloop_unlock(vstream_h->pa_mainloop);
+       goto SUCCESS;
+ERROR_WITH_UNLOCK:
+       /* UNLOCK the pa_threaded_mainloop */
+       pa_threaded_mainloop_unlock(vstream_h->pa_mainloop);
+
+       for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
+               if (vstream_h->pa_stream[i]) {
+                       pa_stream_unref(vstream_h->pa_stream[i]);
+                       vstream_h->pa_stream[i] = NULL;
+               }
+       }
+       LOGE("pa_ret(%d)", pa_ret);
+       ret = MM_ERROR_SOUND_INTERNAL;
+SUCCESS:
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
+
+int sound_manager_stop_virtual_stream (virtual_sound_stream_h virtual_stream)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+       virtual_sound_stream_info_s *vstream_h = (virtual_sound_stream_info_s*)virtual_stream;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(vstream_h);
+       SM_STATE_CHECK(vstream_h, _VSTREAM_STATE_RUNNING);
+
+       /* LOCK the pa_threaded_mainloop */
+       pa_threaded_mainloop_lock(vstream_h->pa_mainloop);
+
+       for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
+               if (vstream_h->pa_stream[i]) {
+                       pa_stream_disconnect(vstream_h->pa_stream[i]);
+                       pa_stream_unref(vstream_h->pa_stream[i]);
+                       vstream_h->pa_stream[i] = NULL;
+               }
+       }
+
+       /* UNLOCK the pa_threaded_mainloop */
+       pa_threaded_mainloop_unlock(vstream_h->pa_mainloop);
+
+       vstream_h->state = _VSTREAM_STATE_READY;
+
+       LOGI("<< leave : ret(%p)", ret);
+
+       return __convert_sound_manager_error_code(__func__, ret);
+}
index 3b7be7628ef391babab5eb5fb94e1ae1120b27be..1d7b7da5347ba29240acc9a8772c2cd4ca6d83c2 100644 (file)
 
 #include <sound_manager.h>
 #include <sound_manager_private.h>
-
 #include <mm_sound.h>
-#include <dlog.h>
+
+#define PA_BUS_NAME                                             "org.pulseaudio.Server"
+#define PA_STREAM_MANAGER_OBJECT_PATH                           "/org/pulseaudio/Ext/StreamManager"
+#define PA_STREAM_MANAGER_INTERFACE                             "org.pulseaudio.Ext.StreamManager"
+#define PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO           "GetStreamInfo"
+#define PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES  "SetStreamRouteDevices"
+#define PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTIONS  "SetStreamRouteOptions"
 
 extern _session_interrupt_info_s g_session_interrupt_cb_table;
 extern _session_mode_e g_cached_session_mode;
+extern _focus_watch_info_s g_focus_watch_cb_table;
+extern sound_stream_info_s* sound_stream_info_arr[SOUND_STREAM_INFO_ARR_MAX];
 
-int __convert_sound_manager_error_code(const char *func, int code) {
+int __convert_sound_manager_error_code (const char *func, int code) {
        int ret = SOUND_MANAGER_ERROR_NONE;
        char *errorstr = NULL;
 
-       switch(code)
-       {
-               case MM_ERROR_FILE_WRITE:
-               case MM_ERROR_INVALID_HANDLE:
-                       ret = SOUND_MANAGER_ERROR_INVALID_OPERATION;
-                       errorstr = "INVALID_OPERATION";
-                       break;
-               case MM_ERROR_NONE:
-                       ret = SOUND_MANAGER_ERROR_NONE;
-                       errorstr = "ERROR_NONE";
-                       break;
-               case MM_ERROR_INVALID_ARGUMENT:
-               case MM_ERROR_SOUND_INVALID_POINTER:
-                       ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
-                       errorstr = "INVALID_PARAMETER";
-                       break;
-               case MM_ERROR_SOUND_PERMISSION_DENIED:
-                       ret = SOUND_MANAGER_ERROR_PERMISSION_DENIED;
-                       errorstr = "PERMISSION_DENIED";
-                       break;
-               case MM_ERROR_SOUND_NO_DATA:
-                       ret = SOUND_MANAGER_ERROR_NO_DATA;
-                       errorstr = "NO_DATA";
-                       break;
-               case MM_ERROR_SOUND_INTERNAL:
-               case MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY:
-                       ret = SOUND_MANAGER_ERROR_INTERNAL;
-                       errorstr = "INTERNAL";
+       switch(code) {
+       case MM_ERROR_FILE_WRITE:
+       case MM_ERROR_INVALID_HANDLE:
+               ret = SOUND_MANAGER_ERROR_INVALID_OPERATION;
+               errorstr = "INVALID_OPERATION";
+               break;
+       case MM_ERROR_NONE:
+               ret = SOUND_MANAGER_ERROR_NONE;
+               errorstr = "ERROR_NONE";
+               break;
+       case MM_ERROR_INVALID_ARGUMENT:
+       case MM_ERROR_SOUND_INVALID_POINTER:
+               ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
+               errorstr = "INVALID_PARAMETER";
+               break;
+       case MM_ERROR_SOUND_PERMISSION_DENIED:
+               ret = SOUND_MANAGER_ERROR_PERMISSION_DENIED;
+               errorstr = "PERMISSION_DENIED";
+               break;
+       case MM_ERROR_SOUND_NO_DATA:
+               ret = SOUND_MANAGER_ERROR_NO_DATA;
+               errorstr = "NO_DATA";
+               break;
+       case MM_ERROR_SOUND_INTERNAL:
+       case MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY:
+       case MM_ERROR_OUT_OF_MEMORY:
+               ret = SOUND_MANAGER_ERROR_INTERNAL;
+               errorstr = "INTERNAL";
+               break;
+       case MM_ERROR_POLICY_DUPLICATED:
+       case MM_ERROR_POLICY_INTERNAL:
+       case MM_ERROR_POLICY_BLOCKED:
+               ret = SOUND_MANAGER_ERROR_POLICY;
+               errorstr = "POLICY";
+               break;
+       case MM_ERROR_SOUND_VOLUME_NO_INSTANCE:
+               ret = SOUND_MANAGER_ERROR_NO_PLAYING_SOUND;
+               errorstr = "NO_PLAYING_SOUND";
+               break;
+       case MM_ERROR_NOT_SUPPORT_API:
+       case MM_ERROR_SOUND_NOT_SUPPORTED_OPERATION:
+               ret = SOUND_MANAGER_ERROR_NOT_SUPPORTED;
+               errorstr = "NOT_SUPPORTED";
+               break;
+       case MM_ERROR_SOUND_INVALID_STATE:
+               ret = SOUND_MANAGER_ERROR_INVALID_STATE;
+               errorstr = "INVALID_STATE";
+               break;
+       }
+       if (ret) {
+               LOGE("[%s] %s(0x%08x) : core frameworks error code(0x%08x)",func, errorstr, ret, code);
+       } else {
+               LOGD("[%s] %s(0x%08x) : core frameworks error code(0x%08x)",func, errorstr, ret, code);
+       }
+       return ret;
+}
+
+int __convert_stream_type (sound_stream_type_e stream_type_enum, char *stream_type)
+{
+       int ret = MM_ERROR_NONE;
+       switch (stream_type_enum) {
+       case SOUND_STREAM_TYPE_MEDIA:
+               SOUND_STRNCPY(stream_type,"media",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_SYSTEM:
+               SOUND_STRNCPY(stream_type,"system",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_ALARM:
+               SOUND_STRNCPY(stream_type,"alarm",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_NOTIFICATION:
+               SOUND_STRNCPY(stream_type,"notification",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_EMERGENCY:
+               SOUND_STRNCPY(stream_type,"emergency",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_VOICE_INFORMATION:
+               SOUND_STRNCPY(stream_type,"voice-information",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_VOICE_RECOGNITION:
+               SOUND_STRNCPY(stream_type,"voice-recognition",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_RINGTONE_VOIP:
+               SOUND_STRNCPY(stream_type,"ringtone-voip",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_VOIP:
+               SOUND_STRNCPY(stream_type,"voip",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       }
+       if (!strncmp(stream_type,"",SOUND_STREAM_TYPE_LEN)) {
+               LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum);
+               ret = MM_ERROR_SOUND_INTERNAL;
+       } else {
+               LOGI("stream_type[%s]", stream_type);
+       }
+       return ret;
+}
+
+int __convert_stream_type_for_internal (sound_stream_type_internal_e stream_type_enum, char *stream_type)
+{
+       int ret = MM_ERROR_NONE;
+
+       SM_NULL_ARG_CHECK(stream_type);
+
+       switch (stream_type_enum) {
+       case SOUND_STREAM_TYPE_RINGTONE_CALL:
+               SOUND_STRNCPY(stream_type,"ringtone-call",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_VOICE_CALL:
+               SOUND_STRNCPY(stream_type,"call-voice",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_VIDEO_CALL:
+               SOUND_STRNCPY(stream_type,"call-video",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_RADIO:
+               SOUND_STRNCPY(stream_type,"radio",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       case SOUND_STREAM_TYPE_LOOPBACK:
+               SOUND_STRNCPY(stream_type,"loopback",SOUND_STREAM_TYPE_LEN,ret);
+               break;
+       }
+       if (!strncmp(stream_type,"",SOUND_STREAM_TYPE_LEN)) {
+               LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum);
+               ret = MM_ERROR_SOUND_INTERNAL;
+       } else {
+               LOGI("stream_type_for_internal[%s]", stream_type);
+       }
+       return ret;
+}
+
+int __convert_stream_type_to_change_reason (const char *stream_type, sound_stream_focus_change_reason_e *change_reason)
+{
+       int ret = MM_ERROR_NONE;
+
+       SM_NULL_ARG_CHECK(stream_type);
+       SM_NULL_ARG_CHECK(change_reason);
+
+       if (!strncmp(stream_type, "media", SOUND_STREAM_TYPE_LEN) ||
+               !strncmp(stream_type, "radio", SOUND_STREAM_TYPE_LEN) ||
+               !strncmp(stream_type, "loopback", SOUND_STREAM_TYPE_LEN)) {
+               *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
+
+       } else if (!strncmp(stream_type, "system", SOUND_STREAM_TYPE_LEN)) {
+               *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM;
+
+       } else if (!strncmp(stream_type, "alarm", SOUND_STREAM_TYPE_LEN)) {
+               *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_ALARM;
+
+       } else if (!strncmp(stream_type, "notification", SOUND_STREAM_TYPE_LEN)) {
+               *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION;
+
+       } else if (!strncmp(stream_type, "emergency", SOUND_STREAM_TYPE_LEN)) {
+               *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY;
+
+       } else if (!strncmp(stream_type, "voice-information", SOUND_STREAM_TYPE_LEN)) {
+               *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION;
+
+       } else if (!strncmp(stream_type, "voice-recognition", SOUND_STREAM_TYPE_LEN)) {
+               *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION;
+
+       } else if (!strncmp(stream_type, "ringtone-voip", SOUND_STREAM_TYPE_LEN) ||
+                       !strncmp(stream_type, "ringtone-call", SOUND_STREAM_TYPE_LEN)) {
+               *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE;
+
+       } else if (!strncmp(stream_type, "voip", SOUND_STREAM_TYPE_LEN)) {
+               *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOIP;
+
+       } else if (!strncmp(stream_type, "call-voice", SOUND_STREAM_TYPE_LEN) ||
+                       !strncmp(stream_type, "call-video", SOUND_STREAM_TYPE_LEN)) {
+               *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_CALL;
+       } else {
+               ret = MM_ERROR_INVALID_ARGUMENT;
+               LOGE("not supported stream_type(%s), err(0x%08x)", stream_type, ret);
+       }
+       return ret;
+}
+
+int __convert_device_type (sound_device_type_e device_type_enum, char *device_type)
+{
+       int ret = MM_ERROR_NONE;
+
+       SM_NULL_ARG_CHECK(device_type);
+
+       switch (device_type_enum) {
+       case SOUND_DEVICE_BUILTIN_SPEAKER:
+               SOUND_STRNCPY(device_type,"builtin-speaker",SOUND_DEVICE_TYPE_LEN,ret);
+               break;
+       case SOUND_DEVICE_BUILTIN_RECEIVER:
+               SOUND_STRNCPY(device_type,"builtin-receiver",SOUND_DEVICE_TYPE_LEN,ret);
+               break;
+       case SOUND_DEVICE_BUILTIN_MIC:
+               SOUND_STRNCPY(device_type,"builtin-mic",SOUND_DEVICE_TYPE_LEN,ret);
+               break;
+       case SOUND_DEVICE_AUDIO_JACK:
+               SOUND_STRNCPY(device_type,"audio-jack",SOUND_DEVICE_TYPE_LEN,ret);
+               break;
+       case SOUND_DEVICE_BLUETOOTH:
+               SOUND_STRNCPY(device_type,"bt",SOUND_DEVICE_TYPE_LEN,ret);
+               break;
+       case SOUND_DEVICE_HDMI:
+               SOUND_STRNCPY(device_type,"hdmi",SOUND_DEVICE_TYPE_LEN,ret);
+               break;
+       case SOUND_DEVICE_USB_AUDIO:
+               SOUND_STRNCPY(device_type,"usb-audio",SOUND_DEVICE_TYPE_LEN,ret);
+               break;
+       case SOUND_DEVICE_FORWARDING:
+               SOUND_STRNCPY(device_type,"forwarding",SOUND_DEVICE_TYPE_LEN,ret);
+               break;
+       }
+       if (!strncmp(device_type,"",SOUND_DEVICE_TYPE_LEN)) {
+               LOGE("could not find the device_type[%d] in this switch case statement", device_type_enum);
+               ret = MM_ERROR_SOUND_INTERNAL;
+       } else {
+               LOGI("device_type[%s]", device_type);
+       }
+       return ret;
+}
+
+/* it will be deprecated after ready for changing device type that is from server to string */
+int __convert_device_type_to_enum (char *device_type, sound_device_type_e *device_type_enum)
+{
+       int ret = MM_ERROR_NONE;
+
+       SM_NULL_ARG_CHECK(device_type);
+       SM_NULL_ARG_CHECK(device_type_enum);
+
+       if (!strncmp(device_type, "builtin-speaker", SOUND_DEVICE_TYPE_LEN)) {
+               *device_type_enum = SOUND_DEVICE_BUILTIN_SPEAKER;
+       } else if (!strncmp(device_type, "builtin-receiver", SOUND_DEVICE_TYPE_LEN)) {
+               *device_type_enum = SOUND_DEVICE_BUILTIN_RECEIVER;
+       } else if (!strncmp(device_type, "builtin-mic", SOUND_DEVICE_TYPE_LEN)) {
+               *device_type_enum = SOUND_DEVICE_BUILTIN_MIC;
+       } else if (!strncmp(device_type, "audio-jack", SOUND_DEVICE_TYPE_LEN)) {
+               *device_type_enum = SOUND_DEVICE_AUDIO_JACK;
+       } else if (!strncmp(device_type, "bt", SOUND_DEVICE_TYPE_LEN)) {
+               *device_type_enum = SOUND_DEVICE_BLUETOOTH;
+       } else if (!strncmp(device_type, "hdmi", SOUND_DEVICE_TYPE_LEN)) {
+               *device_type_enum = SOUND_DEVICE_HDMI;
+       } else if (!strncmp(device_type, "usb-audio", SOUND_DEVICE_TYPE_LEN)) {
+               *device_type_enum = SOUND_DEVICE_USB_AUDIO;
+       } else {
+               ret = MM_ERROR_INVALID_ARGUMENT;
+               LOGE("not supported device_type(%s), err(0x%08x)", device_type, ret);
+       }
+
+       return ret;
+}
+
+const char* __convert_api_name (native_api_e api_name)
+{
+       const char* name = NULL;
+       switch (api_name) {
+       case NATIVE_API_SOUND_MANAGER:
+               name = "sound-manager";
+               break;
+       case NATIVE_API_PLAYER:
+               name = "player";
+               break;
+       case NATIVE_API_WAV_PLAYER:
+               name = "wav-player";
+               break;
+       case NATIVE_API_TONE_PLAYER:
+               name = "tone-player";
+               break;
+       case NATIVE_API_AUDIO_IO:
+               name = "audio-io";
+               break;
+       case NATIVE_API_RECORDER:
+               name = "recorder";
+               break;
+       }
+       return name;
+}
+
+void _focus_state_change_callback (int index, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+
+       LOGI(">> enter");
+
+       sound_stream_focus_change_reason_e change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
+       ret = __convert_stream_type_to_change_reason(reason_for_change, &change_reason);
+       if (ret) {
+               LOGE("failed to __convert_stream_type_to_enum(), reason_for_change(%s), err(0x%08x)", reason_for_change, ret);
+       } else {
+               for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++) {
+                       if (sound_stream_info_arr[i] && sound_stream_info_arr[i]->index == index) {
+                               if (state ==  FOCUS_IS_RELEASED) {
+                                       sound_stream_info_arr[i]->acquired_focus &= ~focus_type;
+                               } else if (state == FOCUS_IS_ACQUIRED) {
+                                       sound_stream_info_arr[i]->acquired_focus |= focus_type;
+                               }
+                               LOGI("[FOCUS USER CALLBACK(%p) START]", sound_stream_info_arr[i]->user_cb);
+                               sound_stream_info_arr[i]->user_cb((sound_stream_info_h)sound_stream_info_arr[i], change_reason, additional_info, sound_stream_info_arr[i]->user_data);
+                               LOGI("[FOCUS USER CALLBACK(%p) END]", sound_stream_info_arr[i]->user_cb);
+                               break;
+                       }
+               }
+               if (i == SOUND_STREAM_INFO_ARR_MAX) {
+                       LOGE("could not find index(%d), failed to call user callback", index);
+               }
+       }
+
+       LOGI("<< leave");
+
+       return;
+}
+
+void _focus_watch_callback (mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data)
+{
+       int ret = MM_ERROR_NONE;
+       sound_stream_focus_change_reason_e change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
+       ret = __convert_stream_type_to_change_reason(reason_for_change, &change_reason);
+       if (ret)
+               LOGE("failed to __convert_stream_type_to_enum(), reason_for_change(%s), err(0x%08x)", reason_for_change, ret);
+       if (g_focus_watch_cb_table.user_cb)
+               g_focus_watch_cb_table.user_cb(focus_type, state, change_reason, additional_info, g_focus_watch_cb_table.user_data);
+       return;
+}
+
+void _pa_context_state_cb (pa_context *c, void *userdata)
+{
+       pa_context_state_t state;
+       sound_stream_info_s *stream_info_h = (sound_stream_info_s*)userdata;
+       assert(c);
+
+       state = pa_context_get_state(c);
+       LOGI ("[%p] context state = [%d]", stream_info_h, state);
+       switch (state) {
+       case PA_CONTEXT_READY:
+       case PA_CONTEXT_TERMINATED:
+       case PA_CONTEXT_FAILED:
+               pa_threaded_mainloop_signal(stream_info_h->pa_mainloop, 0);
+               break;
+       case PA_CONTEXT_UNCONNECTED:
+       case PA_CONTEXT_CONNECTING:
+       case PA_CONTEXT_AUTHORIZING:
+       case PA_CONTEXT_SETTING_NAME:
+               break;
+       }
+}
+
+void _pa_stream_state_cb (pa_stream *s, void * userdata)
+{
+       pa_stream_state_t state;
+       virtual_sound_stream_info_s *vstream_h = (virtual_sound_stream_info_s*)userdata;
+       assert(s);
+
+       state = pa_stream_get_state(s);
+       LOGI ("[%p] stream [%d] state = [%d]", vstream_h, pa_stream_get_index(s), state);
+
+       switch (state) {
+       case PA_STREAM_READY:
+       case PA_STREAM_FAILED:
+       case PA_STREAM_TERMINATED:
+               pa_threaded_mainloop_signal(vstream_h->pa_mainloop, 0);
+               break;
+       case PA_STREAM_UNCONNECTED:
+       case PA_STREAM_CREATING:
+               break;
+       }
+}
+
+int __get_stream_conf_info (const char *stream_type, stream_conf_info_s *info)
+{
+       int ret = MM_ERROR_NONE;
+       GVariant *result = NULL;
+       GVariant *child = NULL;
+       GDBusConnection *conn = NULL;
+       GError *err = NULL;
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+       if (!conn && err) {
+               LOGE("g_bus_get_sync() error (%s)", err->message);
+               g_error_free (err);
+               ret = MM_ERROR_SOUND_INTERNAL;
+               return ret;
+       }
+       result = g_dbus_connection_call_sync (conn,
+                                                       PA_BUS_NAME,
+                                                       PA_STREAM_MANAGER_OBJECT_PATH,
+                                                       PA_STREAM_MANAGER_INTERFACE,
+                                                       PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO,
+                                                       g_variant_new ("(s)", stream_type),
+                                                       G_VARIANT_TYPE("(vvvvv)"),
+                                                       G_DBUS_CALL_FLAGS_NONE,
+                                                       2000,
+                                                       NULL,
+                                                       &err);
+       if (!result && err) {
+               LOGE("g_dbus_connection_call_sync() error (%s)", err->message);
+               ret = MM_ERROR_SOUND_INTERNAL;
+       } else {
+               GVariantIter iter;
+               GVariant *item = NULL;
+               gchar *name = NULL;
+               gsize size = 0;
+               int i = 0;
+
+               /* get priority */
+               child = g_variant_get_child_value(result, 0);
+               item = g_variant_get_variant(child);
+               info->priority = g_variant_get_int32(item);
+               g_variant_unref (item);
+               g_variant_unref (child);
+               LOGI ("priority(%d)", info->priority);
+
+               /* get route type */
+               child = g_variant_get_child_value(result, 1);
+               item = g_variant_get_variant(child);
+               info->route_type = g_variant_get_int32(item);
+               g_variant_unref (item);
+               g_variant_unref (child);
+               LOGI ("route_type(%d)", info->route_type);
+
+               /* get availabe in-devices */
+               child = g_variant_get_child_value(result, 2);
+               item = g_variant_get_variant(child);
+               size = g_variant_n_children(item);
+               LOGI ("num of avail-in-devices are %d", size);
+               g_variant_iter_init(&iter, item);
+               i = 0;
+               while (g_variant_iter_loop(&iter, "&s", &name)) {
+                       if (size == 1 && !strncmp (name, "none", strlen("none"))) {
+                               LOGI (" in-device is [%s], skip it", name);
+                               break;
+                       } else {
+                               LOGI (" in-device name : %s", name);
+                               info->avail_in_devices[i++] = strdup(name);
+                       }
+               }
+               g_variant_iter_free (&iter);
+               g_variant_unref (item);
+               g_variant_unref (child);
+
+               /* get available out-devices */
+               child = g_variant_get_child_value(result, 3);
+               item = g_variant_get_variant(child);
+               size = g_variant_n_children(item);
+               LOGI ("num of avail-out-devices are %d", size);
+               g_variant_iter_init(&iter, item);
+               i = 0;
+               while (g_variant_iter_loop(&iter, "&s", &name)) {
+                       if (size == 1 && !strncmp (name, "none", strlen("none"))) {
+                               LOGI (" out-device is [%s], skip it", name);
+                               break;
+                       } else {
+                               LOGI (" out-device name : %s", name);
+                               info->avail_out_devices[i++] = strdup(name);
+                       }
+               }
+               g_variant_iter_free (&iter);
+               g_variant_unref (item);
+               g_variant_unref (child);
+
+               /* get available frameworks */
+               child = g_variant_get_child_value(result, 4);
+               item = g_variant_get_variant(child);
+               size = g_variant_n_children(item);
+               LOGI ("num of avail-frameworks are %d", size);
+               g_variant_iter_init(&iter, item);
+               i = 0;
+               while (g_variant_iter_loop(&iter, "&s", &name)) {
+                       if (size == 1 && !strncmp (name, "none", strlen("none"))) {
+                               LOGI (" framework is [%s], skip it", name);
+                               break;
+                       } else {
+                               LOGI (" framework name : %s", name);
+                               info->avail_frameworks[i++] = strdup(name);
+                       }
+               }
+               g_variant_iter_free (&iter);
+               g_variant_unref (item);
+               g_variant_unref (child);
+               g_variant_unref(result);
+       }
+       g_object_unref(conn);
+       return ret;
+}
+
+int __set_manual_route_info (unsigned int index, manual_route_info_s *info)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+       GVariantBuilder *builder_for_in_devices;
+       GVariantBuilder *builder_for_out_devices;
+       GVariant *result = NULL;
+       GDBusConnection *conn = NULL;
+       GError *err = NULL;
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+       if (!conn && err) {
+               LOGE("g_bus_get_sync() error (%s)", err->message);
+               g_error_free (err);
+               ret = MM_ERROR_SOUND_INTERNAL;
+               return ret;
+       }
+
+       builder_for_in_devices = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       builder_for_out_devices = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
+               if (info->route_in_devices[i]) {
+                       g_variant_builder_add(builder_for_in_devices, "s", info->route_in_devices[i]);
+                       LOGI("[IN] %s", info->route_in_devices[i]);
+               } else {
                        break;
-               case MM_ERROR_POLICY_DUPLICATED:
-               case MM_ERROR_POLICY_INTERNAL:
-               case MM_ERROR_POLICY_BLOCKED:
-                       ret = SOUND_MANAGER_ERROR_POLICY;
-                       errorstr = "POLICY";
+               }
+       }
+       for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
+               if (info->route_out_devices[i]) {
+                       g_variant_builder_add(builder_for_out_devices, "s", info->route_out_devices[i]);
+                       LOGI("[OUT] %s", info->route_out_devices[i]);
+               } else {
                        break;
-               case MM_ERROR_SOUND_VOLUME_NO_INSTANCE:
-                       ret = SOUND_MANAGER_ERROR_NO_PLAYING_SOUND;
-                       errorstr = "NO_PLAYING_SOUND";
+               }
+       }
+
+       result = g_dbus_connection_call_sync (conn,
+                                                       PA_BUS_NAME,
+                                                       PA_STREAM_MANAGER_OBJECT_PATH,
+                                                       PA_STREAM_MANAGER_INTERFACE,
+                                                       PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES,
+                                                       g_variant_new ("(uasas)", index, builder_for_in_devices, builder_for_out_devices),
+                                                       G_VARIANT_TYPE("(s)"),
+                                                       G_DBUS_CALL_FLAGS_NONE,
+                                                       2000,
+                                                       NULL,
+                                                       &err);
+       if (!result && err) {
+               LOGE("g_dbus_connection_call_sync() error (%s)", err->message);
+               ret = MM_ERROR_SOUND_INTERNAL;
+       } else {
+               const gchar *dbus_ret = NULL;
+               g_variant_get(result, "(s)", &dbus_ret);
+               LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
+               if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
+                       ret = MM_ERROR_SOUND_INVALID_STATE;
+               }
+               g_variant_unref(result);
+       }
+       g_variant_builder_unref(builder_for_in_devices);
+       g_variant_builder_unref(builder_for_out_devices);
+       g_object_unref(conn);
+       return ret;
+}
+
+int __set_route_options (unsigned int index, char **route_options)
+{
+       int ret = MM_ERROR_NONE;
+       int i = 0;
+       GVariantBuilder *builder;
+
+       GVariant *result = NULL;
+       GDBusConnection *conn = NULL;
+       GError *err = NULL;
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+       if (!conn && err) {
+               LOGE("g_bus_get_sync() error (%s)", err->message);
+               g_error_free (err);
+               ret = MM_ERROR_SOUND_INTERNAL;
+               return ret;
+       }
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       for (i = 0; i < ROUTE_OPTIONS_MAX; i++) {
+               if (route_options[i]) {
+                       g_variant_builder_add(builder, "s", route_options[i]);
+                       LOGI("[OPTIONS] %s", route_options[i]);
+               } else {
                        break;
+               }
+       }
+
+       result = g_dbus_connection_call_sync (conn,
+                                                       PA_BUS_NAME,
+                                                       PA_STREAM_MANAGER_OBJECT_PATH,
+                                                       PA_STREAM_MANAGER_INTERFACE,
+                                                       PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTIONS,
+                                                       g_variant_new ("(uas)", index, builder),
+                                                       G_VARIANT_TYPE("(s)"),
+                                                       G_DBUS_CALL_FLAGS_NONE,
+                                                       2000,
+                                                       NULL,
+                                                       &err);
+       if (!result && err) {
+               LOGE("g_dbus_connection_call_sync() error (%s)", err->message);
+               ret = MM_ERROR_SOUND_INTERNAL;
+       } else {
+               const gchar *dbus_ret = NULL;
+               g_variant_get(result, "(s)", &dbus_ret);
+               LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
+               if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
+                       ret = MM_ERROR_SOUND_INTERNAL;
+               }
+               g_variant_unref(result);
        }
-       LOGE("[%s] %s(0x%08x) : core frameworks error code(0x%08x)",func, errorstr, ret, code);
+       g_variant_builder_unref(builder);
+       g_object_unref(conn);
        return ret;
 }
 
-void __session_interrupt_cb(session_msg_t msg, session_event_t event, void *user_data){
+void _session_interrupt_cb (session_msg_t msg, session_event_t event, void *user_data){
        if( g_session_interrupt_cb_table.user_cb ){
                sound_session_interrupted_code_e e = SOUND_SESSION_INTERRUPTED_COMPLETED;
                if( msg == MM_SESSION_MSG_RESUME )
@@ -108,7 +674,7 @@ void __session_interrupt_cb(session_msg_t msg, session_event_t event, void *user
        }
 }
 
-int __set_session_mode(_session_mode_e mode)
+int __set_session_mode (_session_mode_e mode)
 {
        int ret = MM_ERROR_NONE;
        mm_sound_route route = MM_SOUND_ROUTE_IN_MIC_OUT_SPEAKER;
@@ -208,7 +774,7 @@ ERROR_CASE:
        return ret;
 }
 
-int __get_session_mode(_session_mode_e *mode)
+int __get_session_mode (_session_mode_e *mode)
 {
        int ret = MM_ERROR_NONE;
        int subsession = 0;
@@ -267,3 +833,168 @@ int __get_session_mode(_session_mode_e *mode)
 ERROR_CASE:
        return ret;
 }
+
+int _make_pa_connection_and_register_focus(sound_stream_info_s *stream_h, sound_stream_focus_state_changed_cb callback, void *user_data)
+{
+       int ret = MM_ERROR_NONE;
+       int pa_ret = PA_OK;
+       int i = 0;
+       if (!(stream_h->pa_mainloop = pa_threaded_mainloop_new()))
+               goto PA_ERROR;
+
+       if (!(stream_h->pa_context = pa_context_new(pa_threaded_mainloop_get_api(stream_h->pa_mainloop), "SOUND_MANAGER_STREAM_INFO")))
+               goto PA_ERROR;
+
+       pa_context_set_state_callback(stream_h->pa_context, _pa_context_state_cb, stream_h);
+
+       if (pa_context_connect(stream_h->pa_context, NULL, 0, NULL) < 0) {
+               pa_ret = pa_context_errno(stream_h->pa_context);
+               goto PA_ERROR;
+       }
+
+       pa_threaded_mainloop_lock(stream_h->pa_mainloop);
+
+       if (pa_threaded_mainloop_start(stream_h->pa_mainloop) < 0)
+               goto PA_ERROR_WITH_UNLOCK;
+
+       /* wait for ready state of the context */
+       for (;;) {
+               pa_context_state_t state;
+               state = pa_context_get_state(stream_h->pa_context);
+               if (state == PA_CONTEXT_READY)
+                       break;
+               if (!PA_CONTEXT_IS_GOOD(state)) {
+                       pa_ret = pa_context_errno(stream_h->pa_context);
+                       goto PA_ERROR_WITH_UNLOCK;
+               }
+               pa_threaded_mainloop_wait(stream_h->pa_mainloop);
+       }
+
+       /* get uniq id of this context */
+       stream_h->index = pa_context_get_index(stream_h->pa_context);
+
+       /* get configuration information of this stream type */
+       ret = __get_stream_conf_info(stream_h->stream_type, &stream_h->stream_conf_info);
+       if (ret) {
+               goto PA_ERROR_WITH_UNLOCK;
+       } else {
+               LOGI("stream_conf_info : priority[%d], route type[%d]", stream_h->stream_conf_info.priority, stream_h->stream_conf_info.route_type);
+       }
+
+       pa_threaded_mainloop_unlock(stream_h->pa_mainloop);
+
+       /* register focus */
+       ret = mm_sound_register_focus(stream_h->index, stream_h->stream_type, _focus_state_change_callback, user_data);
+       if (ret == MM_ERROR_NONE) {
+               int i = 0;
+               stream_h->user_cb = callback;
+               stream_h->user_data = user_data;
+               for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++) {
+                       if (sound_stream_info_arr[i] == NULL) {
+                               sound_stream_info_arr[i] = stream_h;
+                               break;
+                       }
+               }
+               if (i == SOUND_STREAM_INFO_ARR_MAX) {
+                       LOGE("client sound stream info array is full");
+                       ret = mm_sound_unregister_focus(stream_h->index);
+                       goto PA_ERROR;
+               }
+       } else {
+               /* disconnect */
+               goto PA_ERROR;
+       }
+       goto SUCCESS;
+PA_ERROR_WITH_UNLOCK:
+       pa_threaded_mainloop_unlock(stream_h->pa_mainloop);
+PA_ERROR:
+       for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
+               if (stream_h->stream_conf_info.avail_in_devices[i]) {
+                       free(stream_h->stream_conf_info.avail_in_devices[i]);
+               } else {
+                       break;
+               }
+       }
+       for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
+               if (stream_h->stream_conf_info.avail_out_devices[i]) {
+                       free(stream_h->stream_conf_info.avail_out_devices[i]);
+               } else {
+                       break;
+               }
+       }
+       for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++) {
+               if (stream_h->stream_conf_info.avail_frameworks[i]) {
+                       free(stream_h->stream_conf_info.avail_frameworks[i]);
+               } else {
+                       break;
+               }
+       }
+       if (stream_h->pa_context) {
+               pa_context_disconnect(stream_h->pa_context);
+               pa_context_unref(stream_h->pa_context);
+               stream_h->pa_context = NULL;
+       }
+       if (stream_h->pa_mainloop) {
+               pa_threaded_mainloop_free(stream_h->pa_mainloop);
+               stream_h->pa_mainloop = NULL;
+       }
+       free(stream_h);
+       ret = MM_ERROR_SOUND_INTERNAL;
+       LOGE("pa_ret(%d), ret(%p)", pa_ret, ret);
+SUCCESS:
+       return ret;
+}
+
+int _destroy_pa_connection_and_unregister_focus(sound_stream_info_s *stream_h)
+{
+       int i = 0;
+       int ret = MM_ERROR_NONE;
+
+       if (stream_h->pa_context) {
+               pa_context_disconnect(stream_h->pa_context);
+               pa_context_unref(stream_h->pa_context);
+               stream_h->pa_context = NULL;
+       }
+
+       if (stream_h->pa_mainloop) {
+               pa_threaded_mainloop_free(stream_h->pa_mainloop);
+               stream_h->pa_mainloop = NULL;
+       }
+
+       /* unregister focus */
+       ret = mm_sound_unregister_focus(stream_h->index);
+
+       for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
+               if (stream_h->stream_conf_info.avail_in_devices[i]) {
+                       free(stream_h->stream_conf_info.avail_in_devices[i]);
+               }
+               if (stream_h->stream_conf_info.avail_out_devices[i]) {
+                       free(stream_h->stream_conf_info.avail_out_devices[i]);
+               }
+               if (stream_h->manual_route_info.route_in_devices[i]) {
+                       free (stream_h->manual_route_info.route_in_devices[i]);
+               }
+               if (stream_h->manual_route_info.route_out_devices[i]) {
+                       free (stream_h->manual_route_info.route_out_devices[i]);
+               }
+       }
+       for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++) {
+               if (stream_h->stream_conf_info.avail_frameworks[i]) {
+                       free(stream_h->stream_conf_info.avail_frameworks[i]);
+               }
+       }
+       for (i = 0; i < ROUTE_OPTIONS_MAX; i++) {
+               if (stream_h->route_options[i]) {
+                       free(stream_h->route_options[i]);
+               }
+       }
+       for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++) {
+               if (sound_stream_info_arr[i] && sound_stream_info_arr[i]->index == stream_h->index) {
+                       sound_stream_info_arr[i] = NULL;
+                       break;
+               }
+       }
+       free(stream_h);
+
+       return ret;
+}
index 8a704e553d2c7a1b7dd36d9b8dca12cb3d2f6dd1..ebdfed01f23b67841711074bb0409be77408c2ee 100644 (file)
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 
 #include <sound_manager.h>
+#include <sound_manager_internal.h>
 #include <pthread.h>
 #include <glib.h>
 //#include <dlfcn.h>
@@ -58,6 +59,23 @@ enum
        CURRENT_STATUS_UNSET_DEVICE_CONNECTED_CB,
        CURRENT_STATUS_SET_DEVICE_INFO_CHANGED_CB,
        CURRENT_STATUS_UNSET_DEVICE_INFO_CHANGED_CB,
+       CURRENT_STATUS_CREATE_STREAM_INFO,
+       CURRENT_STATUS_ADD_DEVICE_FOR_STREAM_ROUTING,
+       CURRENT_STATUS_REMOVE_DEVICE_FOR_STREAM_ROUTING,
+       CURRENT_STATUS_APPLY_STREAM_ROUTING,
+       CURRENT_STATUS_ADD_OPTION_FOR_STREAM_ROUTING,
+       CURRENT_STATUS_REMOVE_OPTION_FOR_STREAM_ROUTING,
+       CURRENT_STATUS_APPLY_STREAM_ROUTING_OPTIONS,
+       CURRENT_STATUS_ACQUIRE_FOCUS,
+       CURRENT_STATUS_RELEASE_FOCUS,
+       CURRENT_STATUS_GET_ACQUIRED_FOCUS,
+       CURRENT_STATUS_DESTROY_STREAM_INFO,
+       CURRENT_STATUS_SET_FOCUS_WATCH_CB,
+       CURRENT_STATUS_UNSET_FOCUS_WATCH_CB,
+       CURRENT_STATUS_CREATE_VIRTUAL_STREAM,
+       CURRENT_STATUS_START_VIRTUAL_STREAM,
+       CURRENT_STATUS_STOP_VIRTUAL_STREAM,
+       CURRENT_STATUS_DESTROY_VIRTUAL_STREAM
 };
 
 
@@ -66,6 +84,34 @@ static int g_menu_state = CURRENT_STATUS_MAINMENU;
 GMainLoop* g_loop;
 sound_device_list_h g_device_list = NULL;
 sound_device_mask_e g_device_mask = SOUND_DEVICE_ALL_MASK;
+sound_stream_info_h g_stream_info_h = NULL;
+virtual_sound_stream_h g_vstream_h = NULL;
+
+void focus_callback (sound_stream_info_h stream_info, sound_stream_focus_change_reason_e reason_for_change, const char *additional_info, void *user_data) {
+       int ret = 0;
+       sound_stream_focus_state_e playback_focus_state;
+       sound_stream_focus_state_e recording_focus_state;
+       g_print("*** FOCUS callback is called, stream_info(%p) ***\n", stream_info);
+       g_print(" - reason_for_change(%d), additional_info(%s), user_data(%p)\n", reason_for_change, additional_info, user_data);
+       ret = sound_manager_get_focus_state (stream_info, &playback_focus_state, &recording_focus_state);
+       if (!ret)
+               g_print(" - focus_state(playback_focus:%d, recording_focus:%d)\n", playback_focus_state, recording_focus_state);
+       if (playback_focus_state == SOUND_STREAM_FOCUS_STATE_ACQUIRED) {
+               g_print(" -- PLAYBACK_FOCUS acquired\n");
+       }
+       if (recording_focus_state == SOUND_STREAM_FOCUS_STATE_ACQUIRED) {
+               g_print(" -- FOCUS_RECORDING acquired\n");
+       }
+       g_print("*** FOCUS callback is ended, stream_info(%p) ****\n", stream_info);
+       return;
+}
+
+void focus_watch_callback (sound_stream_focus_mask_e  changed_focus_type, sound_stream_focus_state_e changed_focus_state, sound_stream_focus_change_reason_e reason_for_change, const char *additional_info, void *user_data) {
+       g_print("*** FOCUS WATCH callback is called ***\n");
+       g_print(" - changed_focus_type(%d), changed_focus_state(%d), reason_for_change(%d), additional_info(%s), user_data(%p)\n",
+                               changed_focus_type, changed_focus_state, reason_for_change, additional_info, user_data);
+       return;
+}
 
 void quit_program()
 {
@@ -74,123 +120,191 @@ void quit_program()
 
 void _interpret_main_menu(char *cmd)
 {
-               if (strncmp(cmd, "gx", 2) == 0)
+               if (strncmp(cmd, "gx", 3) == 0)
                {
                        g_menu_state = CURRENT_STATUS_GET_MAX_VOLUME;
                }
-               else if (strncmp(cmd, "sv", 2) == 0)
+           else if (strncmp(cmd, "sv", 3) == 0)
                {
                        g_menu_state = CURRENT_STATUS_SET_VOLUME;
-               }
-               else if (strncmp(cmd, "gv", 2) == 0)
+               }               
+               else if (strncmp(cmd, "gv", 3) == 0)
                {
                        g_menu_state = CURRENT_STATUS_GET_VOLUME;
                }
-               else if (strncmp(cmd, "st", 2) == 0)
+               else if (strncmp(cmd, "st", 3) == 0)
                {
                        g_menu_state = CURRENT_STATUS_SET_CURRENT_SOUND_TYPE;
                }
-               else if (strncmp(cmd, "gt", 2) == 0)
+               else if (strncmp(cmd, "gt", 3) == 0)
                {
                        g_menu_state = CURRENT_STATUS_GET_CURRENT_SOUND_TYPE;
                }
-               else if (strncmp(cmd, "ut", 2) == 0)
+               else if (strncmp(cmd, "ut", 3) == 0)
                {
                        g_menu_state = CURRENT_STATUS_UNSET_CURRENT_SOUND_TYPE;
-               }
-               else if (strncmp(cmd, "vc", 2) == 0)
+               }               
+               else if (strncmp(cmd, "vc", 3) == 0)
                {
                        g_menu_state = CURRENT_STATUS_SET_VOLUME_CHANGED_CB;
                }
-               else if (strncmp(cmd, "uv", 2) == 0)
+               else if (strncmp(cmd, "uv", 3) == 0)
                {
                        g_menu_state = CURRENT_STATUS_UNSET_VOLUME_CHANGED_CB;
                }
-               else if (strncmp(cmd, "ss", 2) == 0 )
+               else if (strncmp(cmd, "ss", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_SET_SESSION_TYPE;
-               }
-               else if (strncmp(cmd, "gs", 2) == 0 )
+               }               
+               else if (strncmp(cmd, "gs", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_GET_SESSION_TYPE;
                }
-               else if (strncmp(cmd, "sm", 2) == 0 )
+               else if (strncmp(cmd, "sm", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_SET_MEDIA_SESSION_OPTION;
                }
-               else if (strncmp(cmd, "gm", 2) == 0 )
+               else if (strncmp(cmd, "gm", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_GET_MEDIA_SESSION_OPTION;
                }
-               else if (strncmp(cmd, "sr", 2) == 0 )
+               else if (strncmp(cmd, "sr", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_SET_MEDIA_SESSION_RESUMPTION_OPTION;
                }
-               else if (strncmp(cmd, "gr", 2) == 0 )
+               else if (strncmp(cmd, "gr", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_GET_MEDIA_SESSION_RESUMPTION_OPTION;
                }
-               else if (strncmp(cmd, "so", 2) == 0 )
+               else if (strncmp(cmd, "so", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_SET_VOIP_SESSION_MODE;
                }
-               else if (strncmp(cmd, "go", 2) == 0 )
+               else if (strncmp(cmd, "go", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_GET_VOIP_SESSION_MODE;
                }
-               else if (strncmp(cmd, "sl", 2) == 0 )
+               else if (strncmp(cmd, "sl", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_SET_CALL_SESSION_MODE;
                }
-               else if (strncmp(cmd, "gc", 2) == 0 )
+               else if (strncmp(cmd, "gc", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_GET_CALL_SESSION_MODE;
                }
-               else if (strncmp(cmd, "sc", 2) == 0 )
+               else if (strncmp(cmd, "sc", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_SET_SESSION_INTERRUPTED_CB;
                }
-               else if (strncmp(cmd, "us", 2) == 0 )
+               else if (strncmp(cmd, "us", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_UNSET_SESSION_INTERRUPTED_CB;
                }
-               else if (strncmp(cmd, "sk", 2) == 0 )
+               else if (strncmp(cmd, "sk", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_SET_DEVICE_MASK;
                }
-               else if (strncmp(cmd, "gk", 2) == 0 )
+               else if (strncmp(cmd, "gk", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_GET_DEVICE_MASK;
                }
-               else if (strncmp(cmd, "gl", 2) == 0 )
+               else if (strncmp(cmd, "gl", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_GET_DEVICE_LIST;
                }
-               else if (strncmp(cmd, "gn", 2) == 0 )
+               else if (strncmp(cmd, "gn", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_GET_DEVICE_NEXT;
                }
-               else if (strncmp(cmd, "gp", 2) == 0 )
+               else if (strncmp(cmd, "gp", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_GET_DEVICE_PREV;
                }
-               else if (strncmp(cmd, "sd", 2) == 0 )
+               else if (strncmp(cmd, "sd", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_SET_DEVICE_CONNECTED_CB;
                }
-               else if (strncmp(cmd, "ud", 2) == 0 )
+               else if (strncmp(cmd, "ud", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_UNSET_DEVICE_CONNECTED_CB;
                }
-               else if (strncmp(cmd, "si", 2) == 0 )
+               else if (strncmp(cmd, "si", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_SET_DEVICE_INFO_CHANGED_CB;
                }
-               else if (strncmp(cmd, "ui", 2) == 0 )
+               else if (strncmp(cmd, "ui", 3) == 0 )
                {
                        g_menu_state = CURRENT_STATUS_UNSET_DEVICE_INFO_CHANGED_CB;
                }
-               else if (strncmp(cmd, "q", 1) == 0 )
+               else if (strncmp(cmd, "csi", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_CREATE_STREAM_INFO;
+               }
+               else if (strncmp(cmd, "ads", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_ADD_DEVICE_FOR_STREAM_ROUTING;
+               }
+               else if (strncmp(cmd, "rds", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_REMOVE_DEVICE_FOR_STREAM_ROUTING;
+               }
+               else if (strncmp(cmd, "aps", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_APPLY_STREAM_ROUTING;
+               }
+               else if (strncmp(cmd, "aos", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_ADD_OPTION_FOR_STREAM_ROUTING;
+               }
+               else if (strncmp(cmd, "ros", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_REMOVE_OPTION_FOR_STREAM_ROUTING;
+               }
+               else if (strncmp(cmd, "aso", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_APPLY_STREAM_ROUTING_OPTIONS;
+               }
+               else if (strncmp(cmd, "afc", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_ACQUIRE_FOCUS;
+               }
+               else if (strncmp(cmd, "rfc", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_RELEASE_FOCUS;
+               }
+               else if (strncmp(cmd, "gfs", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_GET_ACQUIRED_FOCUS;
+               }
+               else if (strncmp(cmd, "sfw", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_SET_FOCUS_WATCH_CB;
+               }
+               else if (strncmp(cmd, "ufw", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_UNSET_FOCUS_WATCH_CB;
+               }
+               else if (strncmp(cmd, "dsi", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_DESTROY_STREAM_INFO;
+               }
+               else if (strncmp(cmd, "vcr", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_CREATE_VIRTUAL_STREAM;
+               }
+               else if (strncmp(cmd, "vsr", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_START_VIRTUAL_STREAM;
+               }
+               else if (strncmp(cmd, "vst", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_STOP_VIRTUAL_STREAM;
+               }
+               else if (strncmp(cmd, "vdt", 3) == 0 )
+               {
+                       g_menu_state = CURRENT_STATUS_DESTROY_VIRTUAL_STREAM;
+               }
+               else if (strncmp(cmd, "q", 3) == 0 )
                {
                        g_print("closing the test suite\n");
                        quit_program();
@@ -219,8 +333,8 @@ void display_sub_basic()
        g_print("vc. Set Volume Changed CB \t");
        g_print("uv. Unset Volume Changed CB \n");
        g_print("-----------------------------------------------------------------------------------------\n");
-       g_print("                                       SESSION MODULE \n");
-       g_print("-----------------------------------------------------------------------------------------\n");
+       g_print("                                    SESSION MODULE \n");
+       g_print("-----------------------------------------------------------------------------------------\n"); 
        g_print("ss. Set Session Type\t\t");
        g_print("gs. Get Session Type\n");
        g_print("sm. Set Media Session Option \t");
@@ -234,7 +348,7 @@ void display_sub_basic()
        g_print("sc. Set Session Interruped CB \t");
        g_print("us. Unset Session Interrupted CB \n");
        g_print("-----------------------------------------------------------------------------------------\n");
-       g_print("                                       DEVICE MODULE \n");
+       g_print("                                    DEVICE MODULE \n");
        g_print("-----------------------------------------------------------------------------------------\n");
        g_print("sk. Set Devices Mask(default ALL)\t");
        g_print("gk. Get Devices Mask\n");
@@ -245,7 +359,27 @@ void display_sub_basic()
        g_print("ud. Unset Device Connenected CB\n");
        g_print("si. Set Device Information Changed CB\t");
        g_print("ui. Unset Device Information Changed CB\n");
-       g_print("\n");
+       g_print("-----------------------------------------------------------------------------------------\n");
+       g_print("                                    STREAM POLICY MODULE \n");
+       g_print("-----------------------------------------------------------------------------------------\n");
+       g_print("csi. Create Stream Info\t");
+       g_print("dsi. Destroy Stream Info\n");
+       g_print("ads. Add device for stream routing\t");
+       g_print("rds. Remove device for stream routing\t");
+       g_print("aps. Apply devices for stream routing\n");
+       g_print("afc. Acquire Focus\t");
+       g_print("rfc. Release Focus\t");
+       g_print("gfs. Get Focus State\n");
+       g_print("sfw. Set Focus State Watch CB\t");
+       g_print("ufw. Unset Focus State Watch CB\n");
+       g_print("aos. *Add option for stream routing\t");
+       g_print("ros. *Remove option for stream routing\t");
+       g_print("aso. *Apply options for stream routing\n");
+       g_print("vcr. *Create VStream\t");
+       g_print("vsr. *Start VStream\t");
+       g_print("vst. *Stop VStream\t");
+       g_print("vdt. *Destroy VStream\n");
+       g_print("                                                                 * is for internal usage.\n");
        g_print("=========================================================================================\n");
 }
 
@@ -377,6 +511,74 @@ static void displaymenu()
        {
                g_print("*** press enter to unset device information changed cb\n");
        }
+       else if (g_menu_state == CURRENT_STATUS_CREATE_STREAM_INFO)
+       {
+               g_print("*** input stream type to create stream information (0:media, 1:alarm, 2:notification, 3:ringtone-call, 4:voice-call)\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_ADD_DEVICE_FOR_STREAM_ROUTING)
+       {
+               g_print("*** input device type to add (0:built-in spk, 1:built-in rcv, 2:audio-jack, 3:bt)\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_REMOVE_DEVICE_FOR_STREAM_ROUTING)
+       {
+               g_print("*** input device type to remove (0:built-in spk, 1:built-in rcv, 2:audio-jack, 3:bt)\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_APPLY_STREAM_ROUTING)
+       {
+               g_print("*** press enter to apply devices for stream routing\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_ADD_OPTION_FOR_STREAM_ROUTING)
+       {
+               g_print("*** input option to add\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_REMOVE_OPTION_FOR_STREAM_ROUTING)
+       {
+               g_print("*** input option to remove\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_APPLY_STREAM_ROUTING_OPTIONS)
+       {
+               g_print("*** press enter to apply options for stream routing \n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_ACQUIRE_FOCUS)
+       {
+               g_print("*** input focus type to acquire (0:playback, 1:recording, 2:both)\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_RELEASE_FOCUS)
+       {
+               g_print("*** input focus type to release (0:playback, 1:recording, 2:both)\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_GET_ACQUIRED_FOCUS)
+       {
+               g_print("*** press enter to get focus state\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_DESTROY_STREAM_INFO)
+       {
+               g_print("*** press enter to destroy stream information\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_SET_FOCUS_WATCH_CB)
+       {
+               g_print("*** input focus type to watch for (0:playback, 1:recording, 2:both)\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_UNSET_FOCUS_WATCH_CB)
+       {
+               g_print("*** press enter to unset focus state watch cb\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_CREATE_VIRTUAL_STREAM)
+       {
+               g_print("*** press enter to create virtual stream\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_START_VIRTUAL_STREAM)
+       {
+               g_print("*** press enter to start virtual stream\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_STOP_VIRTUAL_STREAM)
+       {
+               g_print("*** press enter to stop virtual stream\n");
+       }
+       else if (g_menu_state == CURRENT_STATUS_DESTROY_VIRTUAL_STREAM)
+       {
+               g_print("*** press enter to destroy virtual stream\n");
+       }
        else
        {
                g_print("*** unknown status.\n");
@@ -1009,6 +1211,381 @@ static void interpret (char *cmd)
                        reset_menu_state();
                }
                break;
+               case CURRENT_STATUS_CREATE_STREAM_INFO:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       int stream_type = 0;
+                       sound_stream_type_e type = SOUND_STREAM_TYPE_MEDIA;
+                       if (g_stream_info_h) {
+                               g_print("fail to create stream information, g_stream_info_h(%p) is already set\n", g_stream_info_h);
+                               reset_menu_state();
+                               break;
+                       }
+                       stream_type = atoi(cmd);
+                       switch(stream_type) {
+                       case 0: /* media */
+                               type = SOUND_STREAM_TYPE_MEDIA;
+                               break;
+                       case 1: /* alarm */
+                               type = SOUND_STREAM_TYPE_ALARM;
+                               break;
+                       case 2: /* notification */
+                               type = SOUND_STREAM_TYPE_NOTIFICATION;
+                               break;
+                       case 3: /* ringtone for call*/
+                               type = SOUND_STREAM_TYPE_RINGTONE_CALL;
+                               break;
+                       case 4: /* voice call */
+                               type = SOUND_STREAM_TYPE_VOICE_CALL;
+                               break;
+                       default:
+                               type = SOUND_STREAM_TYPE_MEDIA;
+                               break;
+                       }
+                       if (type == (int)SOUND_STREAM_TYPE_RINGTONE_CALL || type == (int)SOUND_STREAM_TYPE_VOICE_CALL) {
+                               ret = sound_manager_create_stream_information_internal(type, focus_callback, NULL, &g_stream_info_h);
+                       } else {
+                               ret = sound_manager_create_stream_information(type, focus_callback, NULL, &g_stream_info_h);
+                       }
+                       if (ret) {
+                               g_print("fail to sound_manager_create_stream_information(), ret(0x%x)\n", ret);
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_ADD_DEVICE_FOR_STREAM_ROUTING:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       int device_type = 0;
+                       sound_device_h device = NULL;
+                       sound_device_type_e selected_type = SOUND_DEVICE_BUILTIN_SPEAKER;
+                       sound_device_type_e type = SOUND_DEVICE_BUILTIN_SPEAKER;
+                       bool need_to_go = false;
+                       device_type = atoi(cmd);
+                       switch(device_type) {
+                       case 0: /* built-in spk */
+                               selected_type = SOUND_DEVICE_BUILTIN_SPEAKER;
+                               break;
+                       case 1: /* built-in rcv */
+                               selected_type = SOUND_DEVICE_BUILTIN_RECEIVER;
+                               break;
+                       case 2: /* audio-jack */
+                               selected_type = SOUND_DEVICE_AUDIO_JACK;
+                               break;
+                       case 3: /* bt */
+                               selected_type = SOUND_DEVICE_BLUETOOTH;
+                               break;
+                       default:
+                               g_print("invalid argument, device_type(%d) is not valid for this feature\n", device_type);
+                               reset_menu_state();
+                               break;
+                       }
+                       if (!(ret = sound_manager_get_current_device_list(SOUND_DEVICE_ALL_MASK, &g_device_list))) {
+                               g_print("success to get current device list\n");
+                               while (!sound_manager_get_next_device(g_device_list, &device)) {
+                                       if (!(ret = sound_manager_get_device_type (device, &type))) {
+                                               if (selected_type == type) {
+                                                       need_to_go = true;
+                                                       break;
+                                               }
+                                       } else {
+                                               g_print("fail to get type of device, ret(0x%x)\n", ret);
+                                               reset_menu_state();
+                                               break;
+                                       }
+                               }
+                               if (need_to_go) {
+                                       ret = sound_manager_add_device_for_stream_routing (g_stream_info_h, device);
+                                       if (ret) {
+                                               g_print("failed to sound_manager_add_device_for_stream_routing(), ret(0x%x)\n", ret);
+                                       }
+                               } else {
+                                       g_print("the device is not available now\n");
+                               }
+                               reset_menu_state();
+                       } else {
+                               g_print("fail to get current device list, ret(0x%x)\n", ret);
+                               reset_menu_state();
+                       }
+               }
+               break;
+               case CURRENT_STATUS_REMOVE_DEVICE_FOR_STREAM_ROUTING:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       int device_type = 0;
+                       sound_device_h device = NULL;
+                       sound_device_type_e selected_type = SOUND_DEVICE_BUILTIN_SPEAKER;
+                       sound_device_type_e type = SOUND_DEVICE_BUILTIN_SPEAKER;
+                       bool need_to_go = false;
+                       device_type = atoi(cmd);
+                       switch(device_type) {
+                       case 0: /* built-in spk */
+                               selected_type = SOUND_DEVICE_BUILTIN_SPEAKER;
+                               break;
+                       case 1: /* built-in rcv */
+                               selected_type = SOUND_DEVICE_BUILTIN_RECEIVER;
+                               break;
+                       case 2: /* audio-jack */
+                               selected_type = SOUND_DEVICE_AUDIO_JACK;
+                               break;
+                       case 3: /* bt */
+                               selected_type = SOUND_DEVICE_BLUETOOTH;
+                               break;
+                       default:
+                               g_print("invalid argument, device_type(%d) is not valid for this feature\n", device_type);
+                               reset_menu_state();
+                               break;
+                       }
+                       if (!(ret = sound_manager_get_current_device_list(SOUND_DEVICE_ALL_MASK, &g_device_list))) {
+                               g_print("success to get current device list\n");
+                               while (!sound_manager_get_next_device(g_device_list, &device)) {
+                                       if (!(ret = sound_manager_get_device_type (device, &type))) {
+                                               if (selected_type == type) {
+                                                       need_to_go = true;
+                                                       break;
+                                               }
+                                       } else {
+                                               g_print("fail to get type of device, ret(0x%x)\n", ret);
+                                               reset_menu_state();
+                                               break;
+                                       }
+                               }
+                               if (need_to_go) {
+                                       ret = sound_manager_remove_device_for_stream_routing (g_stream_info_h, device);
+                                       if (ret) {
+                                               g_print("failed to sound_manager_remove_device_for_stream_routing(), ret(0x%x)\n", ret);
+                                       }
+                               } else {
+                                       g_print("the device is not available now\n");
+                               }
+                               reset_menu_state();
+                       } else {
+                               g_print("fail to get current device list, ret(0x%x)\n", ret);
+                               reset_menu_state();
+                       }
+               }
+               break;
+               case CURRENT_STATUS_APPLY_STREAM_ROUTING:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       ret = sound_manager_apply_stream_routing (g_stream_info_h);
+                       if (ret) {
+                               g_print("failed to sound_manager_apply_stream_routing(), ret(0x%x)\n", ret);
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_ADD_OPTION_FOR_STREAM_ROUTING:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       ret = sound_manager_add_option_for_stream_routing (g_stream_info_h, cmd);
+                       if (ret) {
+                               g_print("failed to sound_manager_add_option_for_stream_routing(), ret(0x%x)\n", ret);
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_REMOVE_OPTION_FOR_STREAM_ROUTING:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       ret = sound_manager_remove_option_for_stream_routing (g_stream_info_h, cmd);
+                       if (ret) {
+                               g_print("failed to sound_manager_remove_option_for_stream_routing(), ret(0x%x)\n", ret);
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_APPLY_STREAM_ROUTING_OPTIONS:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       ret = sound_manager_apply_stream_routing_options (g_stream_info_h);
+                       if (ret) {
+                               g_print("failed to sound_manager_apply_stream_routing_options(), ret(0x%x)\n", ret);
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_ACQUIRE_FOCUS:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       int focus_type = 0;
+                       sound_stream_focus_mask_e focus_mask;
+                       focus_type = atoi(cmd);
+                       switch(focus_type) {
+                       case 0: /* playback */
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_PLAYBACK;
+                               break;
+                       case 1: /* recording */
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_RECORDING;
+                               break;
+                       case 2: /* all */
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_PLAYBACK | SOUND_STREAM_FOCUS_FOR_RECORDING;
+                               break;
+                       default:
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_PLAYBACK;
+                               break;
+                       }
+                       ret = sound_manager_acquire_focus(g_stream_info_h, focus_mask, NULL);
+                       if (ret) {
+                               g_print("fail to sound_manager_acquire_focus(), ret(0x%x)\n", ret);
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_RELEASE_FOCUS:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       int focus_type = 0;
+                       sound_stream_focus_mask_e focus_mask;
+                       focus_type = atoi(cmd);
+                       switch(focus_type) {
+                       case 0: /* playback */
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_PLAYBACK;
+                               break;
+                       case 1: /* recording */
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_RECORDING;
+                               break;
+                       case 2: /* both */
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_PLAYBACK | SOUND_STREAM_FOCUS_FOR_RECORDING;
+                               break;
+                       default:
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_PLAYBACK;
+                               break;
+                       }
+                       ret = sound_manager_release_focus(g_stream_info_h, focus_mask, NULL);
+                       if (ret) {
+                               g_print("fail to sound_manager_acquire_focus(), ret(0x%x)\n", ret);
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_GET_ACQUIRED_FOCUS:
+               {
+                       sound_stream_focus_state_e for_playback;
+                       sound_stream_focus_state_e for_recording;
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       if(g_stream_info_h) {
+                               ret = sound_manager_get_focus_state(g_stream_info_h, &for_playback, &for_recording);
+                               if (ret) {
+                                       g_print("fail to sound_manager_get_focus_state(), ret(0x%x)\n", ret);
+                               } else {
+                                       g_print("focus_state(playback:%d, capture:%d)\n", for_playback, for_recording);
+                               }
+                       } else {
+                               g_print("please create stream info. first\n");
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_DESTROY_STREAM_INFO:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       ret = sound_manager_destroy_stream_information(g_stream_info_h);
+                       if (ret) {
+                               g_print("fail to sound_manager_destroy_stream_information(), ret(0x%x)\n", ret);
+                       } else {
+                               g_stream_info_h = NULL;
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_SET_FOCUS_WATCH_CB:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       int focus_type = 0;
+                       sound_stream_focus_mask_e focus_mask;
+                       focus_type = atoi(cmd);
+                       switch(focus_type) {
+                       case 0: /* playback */
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_PLAYBACK;
+                               break;
+                       case 1: /* recording */
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_RECORDING;
+                               break;
+                       case 2: /* both */
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_PLAYBACK | SOUND_STREAM_FOCUS_FOR_RECORDING;
+                               break;
+                       default:
+                               focus_mask = SOUND_STREAM_FOCUS_FOR_PLAYBACK;
+                               break;
+                       }
+                       ret = sound_manager_set_focus_state_watch_cb(focus_mask, focus_watch_callback, NULL);
+                       if (ret) {
+                               g_print("fail to sound_manager_set_focus_state_watch_cb(), ret(0x%x)\n", ret);
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_UNSET_FOCUS_WATCH_CB:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       ret = sound_manager_unset_focus_state_watch_cb();
+                       if (ret) {
+                               g_print("fail to sound_manager_unset_focus_state_watch_cb(), ret(0x%x)\n", ret);
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_CREATE_VIRTUAL_STREAM:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       if (!g_stream_info_h || g_vstream_h) {
+                               g_print("fail to create virtual stream, g_stream_info_h(%p)/g_vstream_h(%p)\n", g_stream_info_h, g_vstream_h);
+                               reset_menu_state();
+                               break;
+                       }
+                       ret = sound_manager_create_virtual_stream(g_stream_info_h, &g_vstream_h);
+                       if (ret) {
+                               g_print("fail to sound_manager_create_virtual_stream(), ret(0x%x)\n", ret);
+                       } else {
+                               g_print("success to sound_manager_create_virtual_stream(), ret(0x%x)\n", ret);
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_START_VIRTUAL_STREAM:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       if (g_vstream_h) {
+                               ret = sound_manager_start_virtual_stream(g_vstream_h);
+                               if (ret) {
+                                       g_print("fail to sound_manager_start_virtual_stream(), ret(0x%x)\n", ret);
+                               } else {
+                                       g_print("success to sound_manager_start_virtual_stream(), ret(0x%x)\n", ret);
+                               }
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_STOP_VIRTUAL_STREAM:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       if (g_vstream_h) {
+                               ret = sound_manager_stop_virtual_stream(g_vstream_h);
+                               if (ret) {
+                                       g_print("fail to sound_manager_stop_virtual_stream(), ret(0x%x)\n", ret);
+                               } else {
+                                       g_print("success to sound_manager_stop_virtual_stream(), ret(0x%x)\n", ret);
+                               }
+                       }
+                       reset_menu_state();
+               }
+               break;
+               case CURRENT_STATUS_DESTROY_VIRTUAL_STREAM:
+               {
+                       int ret = SOUND_MANAGER_ERROR_NONE;
+                       if (g_vstream_h) {
+                               ret = sound_manager_destroy_virtual_stream(g_vstream_h);
+                               if (ret) {
+                                       g_print("fail to sound_manager_destroy_virtual_stream(), ret(0x%x)\n", ret);
+                               } else {
+                                       g_print("success to sound_manager_destroy_virtual_stream(), ret(0x%x)\n", ret);
+                               }
+                               g_vstream_h = NULL;
+                       }
+                       reset_menu_state();
+               }
+               break;
        }
        g_timeout_add(100, timeout_menu_display, 0);
 }