Add 'R2 Secondary Sink' 20/192520/2
authorHyunsoo Park <hance.park@samsung.com>
Tue, 6 Nov 2018 06:36:19 +0000 (15:36 +0900)
committerHyunsoo Park <hance.park@samsung.com>
Tue, 6 Nov 2018 06:38:13 +0000 (15:38 +0900)
I added files for 'R2 Secondary Sink' function and testing.

- scmirroring_secondary_sink.h
- scmirroring_secondary_sink.c
- scmirroring_secondary_sink_test.c

Change-Id: I56d7b7b2ce9db393f3b4b3dbe852aa95cf57eeab
Signed-off-by: Hyunsoo Park <hance.park@samsung.com>
include/scmirroring_private.h
include/scmirroring_secondary_sink.h [new file with mode: 0644]
packaging/capi-media-screen-mirroring.spec
src/scmirroring_secondary_sink.c [new file with mode: 0644]
test_sink/scmirroring_secondary_sink_test.c [new file with mode: 0644]

index bac3bbd2e447ebc85a11f4f1265e3c82a4fcd55d..91a598ecde1287f47be993abc2bc3442792bfb97 100644 (file)
@@ -156,6 +156,17 @@ typedef struct {
        char *coupled_sink_ip;
 } scmirroring_primary_sink_s;
 
+
+typedef struct {
+       MMHandleType mm_handle;
+       char *ip;
+       char *port;
+       bool use_hdcp;
+       scmirroring_sink_state_cb_s *scmirroring_sink_state_cb;
+       unsigned int magic_num;
+       char *coupled_sink_ip;
+} scmirroring_secondary_sink_s;
+
 #define WIFIDIRECT_DISPLAY_FEATURE "http://tizen.org/feature/network.wifi.direct.display"
 
 #define CHECK_FEATURE_SUPPORTED(feature_name)\
diff --git a/include/scmirroring_secondary_sink.h b/include/scmirroring_secondary_sink.h
new file mode 100644 (file)
index 0000000..71c6607
--- /dev/null
@@ -0,0 +1,603 @@
+/*
+* Copyright (c) 2011 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.
+*/
+
+#ifndef __TIZEN_MEDIA_SCMIRRORING_SECONDARY_SINK_H__
+#define __TIZEN_MEDIA_SCMIRRORING_SECONDARY_SINK_H__
+
+#include <scmirroring_type.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @file scmirroring_secondary_sink.h
+ * @brief This file contains the screen mirroring source API and functions related with screen mirroring as sink device.
+ */
+
+/**
+ * @addtogroup CAPI_MEDIA_SCREEN_MIRRORING_MODULE
+ * @{
+ */
+
+/**
+ * @brief Creates a new screen mirroring sink handle.
+ * @since_tizen 2.4
+ *
+ * @remarks You must release @a scmirroring_secondary_sink using scmirroring_secondary_sink_destroy().
+ *
+ * @param[out] scmirroring_secondary_sink      A newly returned handle to the screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_NULL
+ *
+ * @see scmirroring_secondary_sink_destroy()
+ */
+int scmirroring_secondary_sink_create(scmirroring_secondary_sink_h *scmirroring_secondary_sink);
+
+/**
+ * @brief Registers a callback function to be called when state change happens.
+ * @details This function registers user callback and this callback is called when each status is changed.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[in] callback The callback function to invoke
+ * @param[in] user_data The user data passed to the callback registration function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ *
+ * @see scmirroring_secondary_sink_create()
+ */
+int scmirroring_secondary_sink_set_state_changed_cb(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_sink_state_cb callback, void *user_data);
+
+/**
+ * @brief Sets server IP and port.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[in] ip The server IP address to connect to
+ * @param[in] port The server port to connect to
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ *
+ * @see scmirroring_secondary_sink_create()
+ */
+int scmirroring_secondary_sink_set_ip_and_port(scmirroring_secondary_sink_h scmirroring_secondary_sink, const char *ip, const char *port);
+
+/**
+ * @brief Pass window handle created by application and surface type(x11/evas).
+ * @details This function will use handle created by the application to set the overlay &
+ *          display on the surface passed by the application
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[in] type Surface type(x11/evas)
+ * @param[in] display_surface The display_surface created by application to force sink to display content over it
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ *
+ * @see scmirroring_secondary_sink_create()
+ */
+int scmirroring_secondary_sink_set_display(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_display_type_e type, void *display_surface);
+
+/**
+ * @brief Sets resolutions of screen mirroring sink.
+ * @details This function sets resolutions of screen mirroring sink using scmirroring_resolution_e as following.
+ *          (ex. SCMIRRORING_RESOLUTION_1920x1080_P30 | SCMIRRORING_RESOLUTION_1280x720_P30)
+ *          Use it only when you want to set specific resolutions but if screen mirroring source dose not support
+ *          the resolutions which you set, the screen mirroring sink will be disconnected.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[in] resolution Resolution of screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ *
+ * @see scmirroring_secondary_sink_create()
+ */
+int scmirroring_secondary_sink_set_resolution(scmirroring_secondary_sink_h scmirroring_secondary_sink, int resolution);
+
+/**
+ * @brief Prepares the screen mirroring sink handle and allocates specific resources.
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_NULL
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PREPARED
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ */
+int scmirroring_secondary_sink_prepare(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+/**
+ * @brief Creates connection and prepare for receiving data from SCMIRRORING source.
+ *
+ * @since_tizen 2.4
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_PREPARED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_CONNECTED
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ * @see scmirroring_secondary_sink_prepare()
+ */
+int scmirroring_secondary_sink_connect(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+/**
+ * @brief Starts receiving data from the SCMIRRORING source and display it(mirror).
+ *
+ * @since_tizen 2.4
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_CONNECTED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PLAYING
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ * @see scmirroring_secondary_sink_prepare()
+ * @see scmirroring_secondary_sink_connect()
+ */
+int scmirroring_secondary_sink_start(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+/**
+ * @brief Pauses receiving data from the SCMIRRORING source.
+ * @details This function pauses receiving data from the SCMIRRORING source,
+ *     which means it sends RTSP PAUSE message to source.
+ *
+ * @since_tizen 2.4
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_PLAYING
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PAUSED
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ * @see scmirroring_secondary_sink_prepare()
+ * @see scmirroring_secondary_sink_connect()
+ * @see scmirroring_secondary_sink_start()
+ */
+int scmirroring_secondary_sink_pause(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+/**
+ * @brief Resumes receiving data from the SCMIRRORING source.
+ * @details This function pauses receiving data from the SCMIRRORING source, which means it sends RTSP PLAY message to source.
+ *
+ * @since_tizen 2.4
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_PAUSED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PLAYING
+ *
+ * @see scmirroring_secondary_sink_pause()
+ */
+int scmirroring_secondary_sink_resume(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+/**
+ * @brief Disconnects and stops receiving data from the SCMIRRORING source.
+ *
+ * @since_tizen 2.4
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_CONNECTED
+ *  or #SCMIRRORING_SINK_STATE_PLAYING or #SCMIRRORING_SINK_STATE_PAUSED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_DISCONNECTED
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ * @see scmirroring_secondary_sink_prepare()
+ * @see scmirroring_secondary_sink_connect()
+ * @see scmirroring_secondary_sink_start()
+ */
+int scmirroring_secondary_sink_disconnect(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+/**
+ * @brief Unprepares screen mirroring.
+ * @details This function unprepares screen mirroring, which closes specific resources.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_NULL
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ * @see scmirroring_secondary_sink_prepare()
+ */
+int scmirroring_secondary_sink_unprepare(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+/**
+ * @brief Unregisters the callback function user registered.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ */
+int scmirroring_secondary_sink_unset_state_changed_cb(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+/**
+ * @brief Destroys screen mirroring sink handle.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_NULL
+ *
+ * @see scmirroring_secondary_sink_create()
+ */
+int scmirroring_secondary_sink_destroy(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+/**
+ * @brief Gets negotiated video codec of screen mirroring sink.
+ * @details The video codec is negotiated by screen mirroring source.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[out] codec Codec of video
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
+int scmirroring_secondary_sink_get_negotiated_video_codec(scmirroring_secondary_sink_h *scmirroring_secondary_sink, scmirroring_video_codec_e *codec);
+
+/**
+ * @brief Gets negotiated video resolution of screen mirroring sink.
+ * @details The video resolution is negotiated by screen mirroring source.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[out] width Width of video
+ * @param[out] height Height of video
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
+int scmirroring_secondary_sink_get_negotiated_video_resolution(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *width, int *height);
+
+/**
+ * @brief Gets negotiated frame rate of screen mirroring sink.
+ * @details The video frame rate is negotiated by screen mirroring source.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[out] frame_rate Frame rate of video
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
+int scmirroring_secondary_sink_get_negotiated_video_frame_rate(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *frame_rate);
+
+/**
+ * @brief Gets negotiated audio codec of screen mirroring sink.
+ * @details The audio codec is negotiated by screen mirroring source.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[out] codec Codec of audio
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
+int scmirroring_secondary_sink_get_negotiated_audio_codec(scmirroring_secondary_sink_h *scmirroring_secondary_sink, scmirroring_audio_codec_e *codec);
+
+/**
+ * @brief Gets negotiated audio channel of screen mirroring sink.
+ * @details The audio channel is negotiated by screen mirroring source.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[out] channel Channel of audio
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
+int scmirroring_secondary_sink_get_negotiated_audio_channel(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *channel);
+
+/**
+ * @brief Gets negotiated audio sample rate of screen mirroring sink.
+ * @details The audio sample rate is negotiated by screen mirroring source.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[out] sample_rate Sample rate of audio
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
+int scmirroring_secondary_sink_get_negotiated_audio_sample_rate(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *sample_rate);
+
+/**
+ * @brief Gets negotiated audio bitwidth of screen mirroring sink.
+ * @details The audio bitwidth is negotiated by screen mirroring source.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[out] bitwidth Bitwidth of audio
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
+int scmirroring_secondary_sink_get_negotiated_audio_bitwidth(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *bitwidth);
+
+/**
+ * @brief Gets the current state of screen mirroring sink.
+ * @details The current state of screen mirroring sink is changed by calling CAPIs. And it provides the state of screen mirroring sink the time this api is called.
+ *
+ * @since_tizen 5.0
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[out] state The current state of screen mirroring sink
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ */
+int scmirroring_secondary_sink_get_current_state(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_sink_state_e *state);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/**
+ * @}
+ */
+
+#endif /*__TIZEN_MEDIA_SCMIRRORING_SECONDARY_SINK_H__*/
index 76c8cf326d0cd3aee7c59af43b8ebd045886094f..b57d858018be5eab38eaff1526e916014db9eced 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-screen-mirroring
 Summary:    A screen mirroring library in Tizen C API
-Version:    0.1.95
+Version:    0.1.96
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
diff --git a/src/scmirroring_secondary_sink.c b/src/scmirroring_secondary_sink.c
new file mode 100644 (file)
index 0000000..139142f
--- /dev/null
@@ -0,0 +1,746 @@
+/*
+* Copyright (c) 2011 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 <stdio.h>
+#include <mmf/mm_wfd_sink.h>
+#include <scmirroring_secondary_sink.h>
+#include <scmirroring_private.h>
+
+static scmirroring_error_e __scmirroring_secondary_sink_error_convert(const char *func, int error)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+       const char *errorstr = NULL;
+
+       switch (error) {
+       case MM_ERROR_NONE:
+               ret = SCMIRRORING_ERROR_NONE;
+               errorstr = "ERROR_NONE";
+               break;
+
+       case MM_ERROR_WFD_NO_FREE_SPACE:
+               ret = SCMIRRORING_ERROR_OUT_OF_MEMORY;
+               errorstr = "OUT_OF_MEMORY";
+               break;
+
+       case MM_ERROR_WFD_NOT_INITIALIZED:
+       case MM_ERROR_COMMON_INVALID_ATTRTYPE:
+       case MM_ERROR_COMMON_INVALID_PERMISSION:
+       case MM_ERROR_COMMON_OUT_OF_ARRAY:
+       case MM_ERROR_COMMON_OUT_OF_RANGE:
+       case MM_ERROR_COMMON_ATTR_NOT_EXIST:
+               ret = SCMIRRORING_ERROR_INVALID_PARAMETER;
+               errorstr = "INVALID_PARAMETER";
+               break;
+
+       default:
+               ret = SCMIRRORING_ERROR_INVALID_OPERATION;
+               errorstr = "INVALID_OPERATION";
+       }
+
+       if (ret != SCMIRRORING_ERROR_NONE)
+               scmirroring_error("[%s] %s (0x%08x) : core frameworks error code(0x%08x)", func, errorstr, ret, error);
+       else
+               scmirroring_debug("[%s] %s", func, errorstr);
+
+       return ret;
+}
+
+static scmirroring_sink_state_e __SCMIRRORING_SINK_STATE_convert(MMWFDSinkStateType mm_state)
+{
+       scmirroring_sink_state_e state = SCMIRRORING_SINK_STATE_NONE;
+
+       switch (mm_state) {
+       case MM_WFD_SINK_STATE_NONE:
+               state = SCMIRRORING_SINK_STATE_NONE;
+               break;
+       case MM_WFD_SINK_STATE_NULL:
+               state = SCMIRRORING_SINK_STATE_NULL;
+               break;
+       case MM_WFD_SINK_STATE_PREPARED:
+               state = SCMIRRORING_SINK_STATE_PREPARED;
+               break;
+       case MM_WFD_SINK_STATE_CONNECTED:
+               state = SCMIRRORING_SINK_STATE_CONNECTED;
+               break;
+       case MM_WFD_SINK_STATE_PLAYING:
+               state = SCMIRRORING_SINK_STATE_PLAYING;
+               break;
+       case MM_WFD_SINK_STATE_PAUSED:
+               state = SCMIRRORING_SINK_STATE_PAUSED;
+               break;
+       case MM_WFD_SINK_STATE_DISCONNECTED:
+               state = SCMIRRORING_SINK_STATE_DISCONNECTED;
+               break;
+       default:
+               state = SCMIRRORING_SINK_STATE_NONE;
+               break;
+       }
+
+       return state;
+}
+
+void __mm_scmirroring_secondary_sink_set_message_cb(int error_type, MMWFDSinkStateType state_type, void *uData)
+{
+       scmirroring_error_e error = __scmirroring_secondary_sink_error_convert(__func__, error_type);
+       scmirroring_sink_state_e state = __SCMIRRORING_SINK_STATE_convert(state_type);
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)uData;
+
+       /* call application callback */
+       if (handle && handle->scmirroring_sink_state_cb && handle->scmirroring_sink_state_cb->state_cb)
+               handle->scmirroring_sink_state_cb->state_cb(error, state, handle->scmirroring_sink_state_cb->user_data);
+
+       return;
+}
+
+int scmirroring_secondary_sink_create(scmirroring_secondary_sink_h *scmirroring_secondary_sink)
+{
+       CHECK_FEATURE_SUPPORTED(WIFIDIRECT_DISPLAY_FEATURE);
+
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)calloc(1, sizeof(scmirroring_secondary_sink_s));
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Fail to allocate memory for handle");
+
+       handle->mm_handle = 0;
+       handle->ip = NULL;
+       handle->port = NULL;
+       handle->use_hdcp = TRUE;
+       handle->scmirroring_sink_state_cb = NULL;
+       handle->magic_num = SCMIRRORING_MAGIC_NUMBER;
+
+       ret = mm_wfd_sink_create(&handle->mm_handle);
+       if (ret != MM_ERROR_NONE) {
+               SCMIRRORING_SAFE_FREE(handle);
+               scmirroring_error("Fail to Create");
+               return __scmirroring_secondary_sink_error_convert(__func__, ret);
+       }
+
+       *scmirroring_secondary_sink = (scmirroring_secondary_sink_h)handle;
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_set_ip_and_port(scmirroring_secondary_sink_h scmirroring_secondary_sink, const char *ip, const char *port)
+{
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+       scmirroring_retvm_if(ip == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "ip is NULL");
+       scmirroring_retvm_if(port == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "port is NULL");
+
+       scmirroring_debug("ip[%s] port[%s]", ip, port);
+
+       SCMIRRORING_SAFE_FREE(handle->ip);
+       handle->ip = strdup(ip);
+       scmirroring_retvm_if(handle->ip == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Out of memory for ip");
+
+       SCMIRRORING_SAFE_FREE(handle->port);
+       handle->port = strdup(port);
+       scmirroring_retvm_if(handle->port == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Out of memory for port");
+
+       scmirroring_debug_fleave();
+
+       return SCMIRRORING_ERROR_NONE;
+}
+
+int scmirroring_secondary_sink_prepare(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       ret = mm_wfd_sink_prepare(handle->mm_handle);
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_connect(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+       char server_uri[255] = {0, };
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       if (handle->ip == NULL) {
+               scmirroring_error("INVALID_IP(NULL) (0x%08x)", SCMIRRORING_ERROR_INVALID_PARAMETER);
+               return SCMIRRORING_ERROR_INVALID_PARAMETER;
+       }
+
+       if (handle->port == NULL) {
+               scmirroring_error("INVALID_PORT(NULL) (0x%08x)", SCMIRRORING_ERROR_INVALID_PARAMETER);
+               return SCMIRRORING_ERROR_INVALID_PARAMETER;
+       }
+
+       memset(server_uri, 0x00, sizeof(server_uri));
+       snprintf(server_uri, sizeof(server_uri), "rtsp://%s:%s/wfd1.0/streamid=0", handle->ip, handle->port);
+
+       scmirroring_error("server_uri[%s]", server_uri);
+       printf("server_uri[%s]", server_uri);
+
+       ret = mm_wfd_sink_connect(handle->mm_handle, server_uri);
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_unprepare(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       ret = mm_wfd_sink_unprepare(handle->mm_handle);
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_destroy(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       ret = mm_wfd_sink_destroy(handle->mm_handle);
+
+       handle->mm_handle = 0;
+       handle->magic_num = 0;
+       SCMIRRORING_SAFE_FREE(handle->ip);
+       SCMIRRORING_SAFE_FREE(handle->port);
+       SCMIRRORING_SAFE_FREE(handle->scmirroring_sink_state_cb);
+       SCMIRRORING_SAFE_FREE(handle);
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_start(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       ret = mm_wfd_sink_start(handle->mm_handle);
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_disconnect(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       ret = mm_wfd_sink_disconnect(handle->mm_handle);
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_set_state_changed_cb(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_sink_state_cb callback, void *user_data)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+       scmirroring_retvm_if(callback == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+       if (handle->scmirroring_sink_state_cb == NULL) {
+               handle->scmirroring_sink_state_cb = (scmirroring_sink_state_cb_s *)calloc(1, sizeof(scmirroring_sink_state_cb_s));
+               if (handle->scmirroring_sink_state_cb == NULL) {
+                       scmirroring_error("Error Set CB");
+                       return SCMIRRORING_ERROR_OUT_OF_MEMORY;
+               }
+       } else {
+               memset(handle->scmirroring_sink_state_cb, 0, sizeof(scmirroring_sink_state_cb_s));
+       }
+
+       handle->scmirroring_sink_state_cb->user_data = user_data;
+       handle->scmirroring_sink_state_cb->state_cb = callback;
+
+       ret = mm_wfd_sink_set_message_callback(handle->mm_handle, __mm_scmirroring_secondary_sink_set_message_cb, handle);
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_unset_state_changed_cb(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       ret = mm_wfd_sink_set_message_callback(handle->mm_handle, NULL, NULL);
+
+       SCMIRRORING_SAFE_FREE(handle->scmirroring_sink_state_cb);
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_set_display(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_display_type_e type, void *display_surface)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+       scmirroring_retvm_if(display_surface == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "display_surface is NULL");
+
+       if ((type != SCMIRRORING_DISPLAY_TYPE_OVERLAY) && (type != SCMIRRORING_DISPLAY_TYPE_EVAS)) {
+               scmirroring_error("Invalid display type [%d]", type);
+               return SCMIRRORING_ERROR_INVALID_PARAMETER;
+       }
+
+       scmirroring_debug("display type(%d)", type);
+
+       ret = mm_wfd_sink_set_attribute(handle->mm_handle, NULL, "display_surface_type", type, NULL);
+       if (ret != MM_ERROR_NONE) {
+               scmirroring_error("Fail to Set Display Type");
+               return __scmirroring_secondary_sink_error_convert(__func__, ret);
+       }
+
+       ret = mm_wfd_sink_set_attribute(handle->mm_handle, NULL, "display_overlay", display_surface, sizeof(void *), NULL);
+       if (ret != MM_ERROR_NONE) {
+               scmirroring_error("Fail to Set Display Overlay");
+               return __scmirroring_secondary_sink_error_convert(__func__, ret);
+       }
+
+       ret = mm_wfd_sink_set_attribute(handle->mm_handle, NULL, "display_visible", TRUE, NULL);
+       if (ret != MM_ERROR_NONE) {
+               scmirroring_error("Fail to Set Display Visible as TRUE");
+               return __scmirroring_secondary_sink_error_convert(__func__, ret);
+       }
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_set_resolution(scmirroring_secondary_sink_h scmirroring_secondary_sink, int resolution)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       if ((resolution < SCMIRRORING_RESOLUTION_UNKNOWN) || (resolution >= SCMIRRORING_RESOLUTION_MAX)) {
+               scmirroring_error("Invalid resolution : %d", resolution);
+               return SCMIRRORING_ERROR_INVALID_PARAMETER;
+       }
+
+       scmirroring_debug("resolution(%d)", resolution);
+       ret = mm_wfd_sink_set_resolution(handle->mm_handle, resolution);
+       if (ret != MM_ERROR_NONE) {
+               scmirroring_error("Fail to Set resolution");
+               return __scmirroring_secondary_sink_error_convert(__func__, ret);
+       }
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_pause(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       ret = mm_wfd_sink_pause(handle->mm_handle);
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_resume(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       ret = mm_wfd_sink_resume(handle->mm_handle);
+
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_get_negotiated_video_codec(scmirroring_secondary_sink_h *scmirroring_secondary_sink, scmirroring_video_codec_e *codec)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+       int mm_codec = MM_WFD_SINK_VIDEO_CODEC_NONE;
+
+       scmirroring_secondary_sink_s *handle = NULL;
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
+       scmirroring_retvm_if(codec == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "codec is NULL");
+
+       handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       *codec = SCMIRRORING_VIDEO_CODEC_NONE;
+
+       ret = mm_wfd_sink_get_negotiated_video_codec(handle->mm_handle, &mm_codec);
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+       if (ret != SCMIRRORING_ERROR_NONE)
+               return ret;
+
+       switch (mm_codec) {
+       case MM_WFD_SINK_VIDEO_CODEC_H264:
+               *codec = SCMIRRORING_VIDEO_CODEC_H264;
+               break;
+       default:
+               *codec = SCMIRRORING_VIDEO_CODEC_NONE;
+               break;
+       }
+
+       scmirroring_debug("codec: %d", *codec);
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_get_negotiated_video_resolution(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *width, int *height)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = NULL;
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
+       scmirroring_retvm_if(width == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "width is NULL");
+       scmirroring_retvm_if(height == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "height is NULL");
+
+       handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       *width = 0;
+       *height = 0;
+
+       ret = mm_wfd_sink_get_negotiated_video_resolution(handle->mm_handle, width, height);
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+       if (ret != SCMIRRORING_ERROR_NONE)
+               return ret;
+
+       scmirroring_debug("width: %d, height: %d", *width, *height);
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_get_negotiated_video_frame_rate(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *frame_rate)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = NULL;
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
+       scmirroring_retvm_if(frame_rate == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "frame_rate is NULL");
+
+       handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       *frame_rate = 0;
+
+       ret = mm_wfd_sink_get_negotiated_video_frame_rate(handle->mm_handle, frame_rate);
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+       if (ret != SCMIRRORING_ERROR_NONE)
+               return ret;
+
+       scmirroring_debug("frame rate: %d", *frame_rate);
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_get_negotiated_audio_codec(scmirroring_secondary_sink_h *scmirroring_secondary_sink, scmirroring_audio_codec_e *codec)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+       int mm_codec = MM_WFD_SINK_AUDIO_CODEC_NONE;
+
+       scmirroring_secondary_sink_s *handle = NULL;
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
+       scmirroring_retvm_if(codec == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "codec is NULL");
+
+       handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       *codec = SCMIRRORING_AUDIO_CODEC_NONE;
+
+       ret = mm_wfd_sink_get_negotiated_audio_codec(handle->mm_handle, &mm_codec);
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+       if (ret != SCMIRRORING_ERROR_NONE)
+               return ret;
+
+       switch (mm_codec) {
+       case MM_WFD_SINK_AUDIO_CODEC_AAC:
+               *codec = SCMIRRORING_AUDIO_CODEC_AAC;
+               break;
+       case MM_WFD_SINK_AUDIO_CODEC_AC3:
+               *codec = SCMIRRORING_AUDIO_CODEC_AC3;
+               break;
+       case MM_WFD_SINK_AUDIO_CODEC_LPCM:
+               *codec = SCMIRRORING_AUDIO_CODEC_LPCM;
+               break;
+       default:
+               *codec = SCMIRRORING_AUDIO_CODEC_NONE;
+               break;
+       }
+
+       scmirroring_debug("codec: %d", *codec);
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_get_negotiated_audio_channel(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *channel)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = NULL;
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
+       scmirroring_retvm_if(channel == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "channel is NULL");
+
+       handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       *channel = 0;
+
+       ret = mm_wfd_sink_get_negotiated_audio_channel(handle->mm_handle, channel);
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+       if (ret != SCMIRRORING_ERROR_NONE)
+               return ret;
+
+       scmirroring_debug("channel: %d", *channel);
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_get_negotiated_audio_sample_rate(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *sample_rate)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = NULL;
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
+       scmirroring_retvm_if(sample_rate == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "sample_rate is NULL");
+
+       handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       *sample_rate = 0;
+
+       ret = mm_wfd_sink_get_negotiated_audio_sample_rate(handle->mm_handle, sample_rate);
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+       if (ret != SCMIRRORING_ERROR_NONE)
+               return ret;
+
+       scmirroring_debug("sample rate: %d", *sample_rate);
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_get_negotiated_audio_bitwidth(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *bitwidth)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_secondary_sink_s *handle = NULL;
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
+       scmirroring_retvm_if(bitwidth == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "bitwidth is NULL");
+
+       handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       *bitwidth = 0;
+
+       ret = mm_wfd_sink_get_negotiated_audio_bitwidth(handle->mm_handle, bitwidth);
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+       if (ret != SCMIRRORING_ERROR_NONE)
+               return ret;
+
+       scmirroring_debug("bitwidth: %d", *bitwidth);
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+int scmirroring_secondary_sink_get_current_state(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_sink_state_e *state)
+{
+       int result = MM_ERROR_NONE;
+       int mm_state = MM_WFD_SINK_STATE_NONE;
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)(scmirroring_secondary_sink);
+
+       scmirroring_debug_fenter();
+       scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
+       scmirroring_retvm_if(state == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "state is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       result = mm_wfd_sink_get_current_state(handle->mm_handle, &mm_state);
+       if (result == MM_ERROR_NONE) {
+               *state = __SCMIRRORING_SINK_STATE_convert(mm_state);
+               scmirroring_debug("ScreenMirroring current state is [%d]", *state);
+       }
+       scmirroring_debug_fleave();
+       return __scmirroring_secondary_sink_error_convert(__func__, result);
+}
+
+int scmirroring_secondary_sink_set_coupled_ip(scmirroring_secondary_sink_h scmirroring_secondary_sink, char* coupled_ip)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+       scmirroring_debug_fenter();
+       scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+       if (coupled_ip == NULL) {
+               scmirroring_error("Invalid coupled ip parameter [%s]", coupled_ip);
+               return SCMIRRORING_ERROR_INVALID_PARAMETER;
+       }
+       scmirroring_debug("coupled_ip (%s)", coupled_ip);
+
+       ret = mm_wfd_sink_set_coupled_ip(handle->mm_handle, coupled_ip);
+       if (ret != MM_ERROR_NONE) {
+               scmirroring_error("Fail to Set Coupled IP");
+               return __scmirroring_secondary_sink_error_convert(__func__, ret);
+       }
+       ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
diff --git a/test_sink/scmirroring_secondary_sink_test.c b/test_sink/scmirroring_secondary_sink_test.c
new file mode 100644 (file)
index 0000000..6aff3ab
--- /dev/null
@@ -0,0 +1,1199 @@
+/*
+* Copyright (c) 2011 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 <stdlib.h>
+#include <string.h>
+#include <glib/gprintf.h>
+#include <scmirroring_secondary_sink.h>
+#include <scmirroring_private.h>
+#include <wifi-direct.h>
+#include <wifi-direct-internal.h>
+
+#include <Elementary.h>
+#include <appcore-efl.h>
+
+#define MAX_STRING_LEN    2048
+#define SINKTEST_EXECUTE_DELAY 5000
+#define MAIN_MENU 0
+#define SUBMENU_RESOLUTION 1
+#define SUBMENU_GETTING_STREAM_INFO 2
+#define SUBMENU_SETTING_SINK 3
+#define SUBMENU_SETTING_WINDOW_SIZE 4
+
+//#define TEST_WITH_WIFI_DIRECT
+
+#define PACKAGE "screen_mirroring_sink_test"
+static int app_create(void *data);
+static int app_terminate(void *data);
+static Evas_Object* _create_win(const char *name);
+static Evas_Object *create_evas_image_object(Evas_Object *eo_parent);
+static void _win_del(void *data, Evas_Object *obj, void *event);
+static gboolean _scmirroring_start_jobs(gpointer data);
+
+struct appcore_ops ops = {
+       .create = app_create,
+       .terminate = app_terminate,
+};
+static Evas_Object* g_evas;
+static Evas_Object* g_eo = NULL;
+
+scmirroring_secondary_sink_h g_scmirroring = NULL;
+gint g_resolution = 0;
+gint g_sinktype = SCMIRRORING_DISPLAY_TYPE_OVERLAY;
+
+gint g_menu = MAIN_MENU;
+
+#ifdef TEST_WITH_WIFI_DIRECT
+static int g_peer_cnt = 0;
+static char g_peer_ip[32];
+static char g_peer_port[32];
+static char g_src_mac_addr[18] = {0, };
+#define DEFAULT_SCREEN_MIRRORING_PORT 2022
+#endif
+
+gboolean __scmirroring_secondary_sink_start(gpointer data);
+
+#ifndef TEST_WITH_WIFI_DIRECT
+static int __scmirroring_secondary_sink_create(gpointer data);
+#endif
+#ifdef TEST_WITH_WIFI_DIRECT
+static gboolean __start_wifi_display_connection();
+static gboolean __start_p2p_connection(gpointer data);
+static gboolean __disconnect_p2p_connection(void);
+#endif
+static void __quit_program(void);
+gboolean __timeout_menu_display(void *data);
+
+/* Submenu for setting resolution */
+static void __display_resolution_submenu(void);
+gboolean __timeout_resolution_submenu_display(void *data);
+static void __interpret_resolution_submenu(char *cmd);
+
+/* Submenu for getting negotiated audio and video information */
+static void __display_stream_info_submenu(void);
+gboolean __timeout_stream_info_submenu_display(void *data);
+static void __interpret_stream_info_submenu(char *cmd);
+
+/* Submenu for setting sink type */
+gboolean __timeout_sink_submenu_display(void *data);
+static void __display_sink_submenu(void);
+static void __interpret_sink_submenu(char *cmd);
+static void create_render_rect_and_bg(Evas_Object *win);
+
+/* Submenu for setting window size */
+gboolean __timeout_window_size_submenu_display(void *data);
+static void __display_window_size_submenu(void);
+static void __interpret_window_size_submenu(char *cmd);
+
+static void create_render_rect_and_bg(Evas_Object *win);
+void create_render_rect_and_bg(Evas_Object *win)
+{
+       if (!win) {
+               g_print("no win");
+               return;
+       }
+       Evas_Object *bg, *rect;
+
+       bg = elm_bg_add(win);
+       elm_win_resize_object_add(win, bg);
+       evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       evas_object_show(bg);
+
+       rect = evas_object_rectangle_add(evas_object_evas_get(win));
+       if (!rect) {
+               g_print("no rect");
+               return;
+       }
+       evas_object_color_set(rect, 0, 0, 0, 0);
+       evas_object_render_op_set(rect, EVAS_RENDER_COPY);
+
+       elm_win_resize_object_add(win, rect);
+       evas_object_size_hint_weight_set(rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       evas_object_show(rect);
+       evas_object_show(win);
+}
+
+static void _win_del(void *data, Evas_Object *obj, void *event)
+{
+       elm_exit();
+}
+
+
+static Evas_Object* _create_win(const char *name)
+{
+       Evas_Object *eo = NULL;
+       int w = 0;
+       int h = 0;
+
+       g_printf("[%s][%d] name=%s\n", __func__, __LINE__, name);
+
+       eo = elm_win_add(NULL, name, ELM_WIN_BASIC);
+       if (eo) {
+               elm_win_title_set(eo, name);
+               elm_win_borderless_set(eo, EINA_TRUE);
+               evas_object_smart_callback_add(eo, "delete,request", _win_del, NULL);
+               elm_win_autodel_set(eo, EINA_TRUE);
+               elm_win_screen_size_get(eo, NULL, NULL, &w, &h);
+               g_print("window size :%d,%d\n", w, h);
+               elm_win_alpha_set(eo, EINA_TRUE);
+       }
+       return eo;
+}
+
+static Evas_Object *create_evas_image_object(Evas_Object *eo_parent)
+{
+       if (!eo_parent)
+               return NULL;
+
+       Evas *evas = evas_object_evas_get(eo_parent);
+       Evas_Object *eo = NULL;
+
+       eo = evas_object_image_add(evas);
+
+       return eo;
+}
+
+static int app_create(void *data)
+{
+
+       gboolean result = FALSE;
+
+       g_print("app_create enter");
+
+       Evas_Object *win = NULL;
+       /* create window */
+       win = _create_win(PACKAGE);
+       if (win == NULL)
+               return -1;
+       g_evas = win;
+       create_render_rect_and_bg(g_evas);
+
+       elm_win_activate(win);
+       evas_object_show(win);
+
+       result = _scmirroring_start_jobs((void *)NULL);
+       if (result != TRUE)
+               g_print("failed _scmirroring_start_jobs ");
+
+       g_print("app_create leave");
+
+       return result;
+
+}
+static int app_terminate(void *data)
+{
+
+       if (g_evas) {
+               evas_object_del(g_evas);
+               g_evas = NULL;
+       }
+       return 0;
+}
+
+gboolean __timeout_sink_submenu_display(void *data)
+{
+       __display_sink_submenu();
+       return FALSE;
+}
+
+static void __display_sink_submenu(void)
+{
+       g_print("\n");
+       g_print("**********************************************************************\n");
+       g_print("               Setting sink \n");
+       g_print("**********************************************************************\n");
+       g_print("1 : SCMIRRORING_DISPLAY_TYPE_OVERLAY with No Surface(DEFAULT)\n");
+       g_print("2 : SCMIRRORING_DISPLAY_TYPE_OVERLAY with Surface\n");
+       g_print("3 : SCMIRRORING_DISPLAY_TYPE_EVAS\n");
+       g_print("g : Go back to main menu \n");
+       g_print("**********************************************************************\n");
+
+}
+
+static void __interpret_sink_submenu(char *cmd)
+{
+       if (strncmp(cmd, "1", 1) == 0) {
+               g_print("SCMIRRORING_DISPLAY_TYPE_OVERLAY with No Surface\n");
+               g_sinktype = -1;
+       } else if (strncmp(cmd, "2", 1) == 0) {
+               g_print("SCMIRRORING_DISPLAY_TYPE_OVERLAY with Surface\n");
+               g_sinktype = SCMIRRORING_DISPLAY_TYPE_OVERLAY;
+       } else if (strncmp(cmd, "3", 1) == 0) {
+               g_print("SCMIRRORING_DISPLAY_TYPE_EVAS\n");
+               g_sinktype = SCMIRRORING_DISPLAY_TYPE_EVAS;
+       } else if (strncmp(cmd, "g", 1) == 0) {
+               g_print("go back to main menu\n");
+               g_menu = MAIN_MENU;
+               g_timeout_add(100, __timeout_menu_display, 0);
+               return;
+       }
+
+       g_print("sink type : %d\n", g_sinktype);
+       g_timeout_add(100, __timeout_sink_submenu_display, 0);
+       return;
+}
+
+gboolean __timeout_resolution_submenu_display(void *data)
+{
+       __display_resolution_submenu();
+       return FALSE;
+}
+
+static void __display_resolution_submenu(void)
+{
+       g_print("\n");
+       g_print("**********************************************************************\n");
+       g_print("               Setting resolution \n");
+       g_print("**********************************************************************\n");
+       g_print("1 : SCMIRRORING_RESOLUTION_1920x1080_P30 [%d]\n", SCMIRRORING_RESOLUTION_1920x1080_P30);
+       g_print("2 : SCMIRRORING_RESOLUTION_1280x720_P30  [%d]\n", SCMIRRORING_RESOLUTION_1280x720_P30);
+       g_print("3 : SCMIRRORING_RESOLUTION_960x540_P30   [%d]\n", SCMIRRORING_RESOLUTION_960x540_P30);
+       g_print("4 : SCMIRRORING_RESOLUTION_864x480_P30   [%d]\n", SCMIRRORING_RESOLUTION_864x480_P30);
+       g_print("5 : SCMIRRORING_RESOLUTION_720x480_P60   [%d]\n", SCMIRRORING_RESOLUTION_720x480_P60);
+       g_print("6 : SCMIRRORING_RESOLUTION_640x480_P60   [%d]\n", SCMIRRORING_RESOLUTION_640x480_P60);
+       g_print("7 : SCMIRRORING_RESOLUTION_640x360_P30   [%d]\n", SCMIRRORING_RESOLUTION_640x360_P30);
+       g_print("r : Reset resolution \n");
+       g_print("g : Go back to main menu \n");
+       g_print("**********************************************************************\n");
+
+}
+
+static void __interpret_resolution_submenu(char *cmd)
+{
+       if (strncmp(cmd, "1", 1) == 0) {
+               g_print("resolution |= SCMIRRORING_RESOLUTION_1920x1080_P30[%d]\n", SCMIRRORING_RESOLUTION_1920x1080_P30);
+               g_resolution |= SCMIRRORING_RESOLUTION_1920x1080_P30;
+       } else if (strncmp(cmd, "2", 1) == 0) {
+               g_print("resolution |= SCMIRRORING_RESOLUTION_1280x720_P30[%d]\n", SCMIRRORING_RESOLUTION_1280x720_P30);
+               g_resolution |= SCMIRRORING_RESOLUTION_1280x720_P30;
+       } else if (strncmp(cmd, "3", 1) == 0) {
+               g_print("resolution |= SCMIRRORING_RESOLUTION_960x540_P30[%d]\n", SCMIRRORING_RESOLUTION_960x540_P30);
+               g_resolution |= SCMIRRORING_RESOLUTION_960x540_P30;
+       } else if (strncmp(cmd, "4", 1) == 0) {
+               g_print("resolution |= SCMIRRORING_RESOLUTION_864x480_P30[%d]\n", SCMIRRORING_RESOLUTION_864x480_P30);
+               g_resolution |= SCMIRRORING_RESOLUTION_864x480_P30;
+       } else if (strncmp(cmd, "5", 1) == 0) {
+               g_print("resolution |= SCMIRRORING_RESOLUTION_720x480_P60[%d]\n", SCMIRRORING_RESOLUTION_720x480_P60);
+               g_resolution |= SCMIRRORING_RESOLUTION_720x480_P60;
+       } else if (strncmp(cmd, "6", 1) == 0) {
+               g_print("resolution |= SCMIRRORING_RESOLUTION_640x480_P60[%d]\n", SCMIRRORING_RESOLUTION_640x480_P60);
+               g_resolution |= SCMIRRORING_RESOLUTION_640x480_P60;
+       } else if (strncmp(cmd, "7", 1) == 0) {
+               g_print("resolution |= SCMIRRORING_RESOLUTION_640x360_P30[%d]\n", SCMIRRORING_RESOLUTION_640x360_P30);
+               g_resolution |= SCMIRRORING_RESOLUTION_640x360_P30;
+       } else if (strncmp(cmd, "r", 1) == 0) {
+               g_resolution = 0;
+       } else if (strncmp(cmd, "g", 1) == 0) {
+               g_print("go back to main menu\n");
+               g_menu = MAIN_MENU;
+               g_timeout_add(100, __timeout_menu_display, 0);
+               return;
+       }
+
+       g_print("resolution : %d\n", g_resolution);
+
+       g_timeout_add(100, __timeout_resolution_submenu_display, 0);
+
+       return;
+}
+
+gboolean __timeout_stream_info_submenu_display(void *data)
+{
+       __display_stream_info_submenu();
+       return FALSE;
+}
+
+static void __display_stream_info_submenu(void)
+{
+       g_print("\n");
+       g_print("**********************************************************************\n");
+       g_print("               Getting negotiated audio and video information \n");
+       g_print("**********************************************************************\n");
+       g_print("1 : video codec\n");
+       g_print("2 : video resolution\n");
+       g_print("3 : video frame rate\n");
+       g_print("4 : audio codec\n");
+       g_print("5 : audio channel\n");
+       g_print("6 : audio sample rate\n");
+       g_print("7 : audio bitwidth\n");
+       g_print("g : Go back to main menu \n");
+       g_print("**********************************************************************\n");
+
+}
+
+static void __interpret_stream_info_submenu(char *cmd)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+       if (strncmp(cmd, "1", 1) == 0) {
+
+               scmirroring_video_codec_e codec;
+               ret = scmirroring_secondary_sink_get_negotiated_video_codec(&g_scmirroring, &codec);
+               if (ret != SCMIRRORING_ERROR_NONE) {
+                       g_print("Error : scmirroring_secondary_sink_get_negotiated_video_codec fail[%d]\n", ret);
+               } else {
+                       switch (codec) {
+                       case SCMIRRORING_VIDEO_CODEC_H264:
+                               g_print("video codec : H264[%d]\n", codec);
+                               break;
+                       default:
+                               g_print("video codec : NONE[%d]\n", codec);
+                               break;
+                       }
+               }
+
+       } else if (strncmp(cmd, "2", 1) == 0) {
+
+               int width, height;
+               ret = scmirroring_secondary_sink_get_negotiated_video_resolution(&g_scmirroring, &width, &height);
+               if (ret != SCMIRRORING_ERROR_NONE)
+                       g_print("Error : scmirroring_secondary_sink_get_negotiated_video_resolution fail[%d]\n", ret);
+               else
+                       g_print("video resoltuion : width[%d], height[%d]\n", width, height);
+
+       } else if (strncmp(cmd, "3", 1) == 0) {
+
+               int frame_rate;
+               ret = scmirroring_secondary_sink_get_negotiated_video_frame_rate(&g_scmirroring, &frame_rate);
+               if (ret != SCMIRRORING_ERROR_NONE)
+                       g_print("Error : scmirroring_secondary_sink_get_negotiated_video_frame_rate fail[%d]\n", ret);
+               else
+                       g_print("video frame rate[%d]\n", frame_rate);
+
+       } else if (strncmp(cmd, "4", 1) == 0) {
+               scmirroring_audio_codec_e codec;
+               ret = scmirroring_secondary_sink_get_negotiated_audio_codec(&g_scmirroring, &codec);
+               if (ret != SCMIRRORING_ERROR_NONE) {
+                       g_print("Error : scmirroring_secondary_sink_get_negotiated_audio_codec fail[%d]\n", ret);
+               } else {
+                       switch (codec) {
+                       case SCMIRRORING_AUDIO_CODEC_AAC:
+                               g_print("audio codec : AAC[%d]\n", codec);
+                               break;
+                       case SCMIRRORING_AUDIO_CODEC_AC3:
+                               g_print("audio codec : AC3[%d]\n", codec);
+                               break;
+                       case SCMIRRORING_AUDIO_CODEC_LPCM:
+                               g_print("audio codec : LPCM[%d]\n", codec);
+                               break;
+                       default:
+                               g_print("audio codec : NONE[%d]\n", codec);
+                               break;
+                       }
+               }
+
+       } else if (strncmp(cmd, "5", 1) == 0) {
+               int channel;
+               ret = scmirroring_secondary_sink_get_negotiated_audio_channel(&g_scmirroring, &channel);
+               if (ret != SCMIRRORING_ERROR_NONE)
+                       g_print("Error : scmirroring_secondary_sink_get_negotiated_audio_channel fail[%d]\n", ret);
+               else
+                       g_print("audio channel[%d]\n", channel);
+
+       } else if (strncmp(cmd, "6", 1) == 0) {
+               int sample_rate;
+               ret = scmirroring_secondary_sink_get_negotiated_audio_sample_rate(&g_scmirroring, &sample_rate);
+               if (ret != SCMIRRORING_ERROR_NONE)
+                       g_print("Error : scmirroring_secondary_sink_get_negotiated_audio_sample_rate fail[%d]\n", ret);
+               else
+                       g_print("audio sample rate[%d]\n", sample_rate);
+
+       } else if (strncmp(cmd, "7", 1) == 0) {
+               int bitwidth;
+               ret = scmirroring_secondary_sink_get_negotiated_audio_bitwidth(&g_scmirroring, &bitwidth);
+               if (ret != SCMIRRORING_ERROR_NONE)
+                       g_print("Error : scmirroring_secondary_sink_get_negotiated_audio_bitwidth fail[%d]\n", ret);
+               else
+                       g_print("audio bitwidth[%d]\n", bitwidth);
+
+       } else if (strncmp(cmd, "g", 1) == 0) {
+               g_print("go back to main menu\n");
+               g_menu = MAIN_MENU;
+               g_timeout_add(100, __timeout_menu_display, 0);
+               return;
+       }
+
+       g_timeout_add(100, __timeout_stream_info_submenu_display, 0);
+
+       return;
+}
+
+gboolean __timeout_window_size_submenu_display(void *data)
+{
+       __display_window_size_submenu();
+       return FALSE;
+
+}
+
+static void __display_window_size_submenu(void)
+{
+       g_print("\n");
+       g_print("**********************************************************************\n");
+       g_print("     Setting window size \n");
+       g_print("**********************************************************************\n");
+       g_print("1 : UHD [width:3840, height:2160] \n");
+       g_print("2 : FHD [width:1920, height:1080] \n");
+       g_print("3 : HD  [width:1280, height:720] \n");
+       g_print("g : Go back to main menu \n");
+       g_print("**********************************************************************\n");
+
+}
+
+static void __interpret_window_size_submenu(char *cmd)
+{
+       int w = 0;
+       int h = 0;
+       if (strncmp(cmd, "1", 1) == 0) {
+               w = 3840;
+               h = 2160;
+               elm_win_aux_hint_add(g_evas, "wm.policy.win.user.geometry", "1");
+               evas_object_resize(g_evas, w, h);
+               g_print("Window size is changed.[width:%d, height:%d]", w, h);
+       } else if (strncmp(cmd, "2", 1) == 0) {
+               w = 1920;
+               h = 1080;
+               elm_win_aux_hint_add(g_evas, "wm.policy.win.user.geometry", "1");
+               evas_object_resize(g_evas, w, h);
+               g_print("Window size is changed.[width:%d, height:%d]", w, h);
+       } else if (strncmp(cmd, "3", 1) == 0) {
+               w = 1280;
+               h = 720;
+               elm_win_aux_hint_add(g_evas, "wm.policy.win.user.geometry", "1");
+               evas_object_resize(g_evas, w, h);
+               g_print("Window size is changed.[width:%d, height:%d]", w, h);
+       } else if (strncmp(cmd, "g", 1) == 0) {
+               g_print("go back to main menu\n");
+               g_menu = MAIN_MENU;
+               g_timeout_add(100, __timeout_menu_display, 0);
+               return;
+       }
+
+       g_timeout_add(100, __timeout_window_size_submenu_display, 0);
+       return;
+}
+
+
+static void scmirroring_sink_state_callback(scmirroring_error_e error_code, scmirroring_sink_state_e state, void *user_data)
+{
+       g_print("Received Callback error code[%d]", error_code);
+
+       if (state == SCMIRRORING_SINK_STATE_NONE)
+               g_print(" state[%d] SCMIRRORING_SINK_STATE_NONE\n", state);
+       else if (state == SCMIRRORING_SINK_STATE_NULL)
+               g_print(" state[%d] SCMIRRORING_SINK_STATE_NULL\n", state);
+       else if (state == SCMIRRORING_SINK_STATE_PREPARED)
+               g_print(" state[%d] SCMIRRORING_SINK_STATE_PREPARED\n", state);
+       else if (state == SCMIRRORING_SINK_STATE_CONNECTED) {
+
+               g_print(" state[%d] SCMIRRORING_SINK_STATE_CONNECTED\n", state);
+               if (scmirroring_secondary_sink_start(g_scmirroring) != SCMIRRORING_ERROR_NONE)
+                       g_print("scmirroring_secondary_sink_start fail");
+
+       } else if (state == SCMIRRORING_SINK_STATE_PLAYING)
+               g_print(" state[%d] SCMIRRORING_SINK_STATE_PLAYING\n", state);
+       else if (state == SCMIRRORING_SINK_STATE_PAUSED)
+               g_print(" state[%d] SCMIRRORING_SINK_STATE_PAUSED\n", state);
+       else if (state == SCMIRRORING_SINK_STATE_DISCONNECTED) {
+               g_print(" state[%d] SCMIRRORING_SINK_STATE_DISCONNECTED\n", state);
+               if (scmirroring_secondary_sink_unprepare(g_scmirroring) != SCMIRRORING_ERROR_NONE)
+                       g_print("scmirroring_secondary_sink_unprepare fail\n");
+               if (scmirroring_secondary_sink_destroy(g_scmirroring) != SCMIRRORING_ERROR_NONE)
+                       g_print("scmirroring_secondary_sink_destroy fail\n");
+               __quit_program();
+       } else
+               g_print(" state[%d] Invalid State", state);
+
+       return;
+}
+
+static void __quit_program(void)
+{
+       g_print("Quit Program\n");
+
+#ifdef TEST_WITH_WIFI_DIRECT
+       __disconnect_p2p_connection();
+#endif
+       g_scmirroring = 0;
+       elm_exit();
+}
+
+static void __displaymenu(void)
+{
+       g_print("\n");
+       g_print("=====================================================================\n");
+       g_print("                               SCMIRRORING Sink Testsuite(press q to quit) \n");
+       g_print("=====================================================================\n");
+#ifndef TEST_WITH_WIFI_DIRECT
+       g_print("a : a ip port(ex. a 192.168.49.1 2022)\n");
+       g_print("s : start\n");
+#else
+       g_print("b : Connecting and Starting sink with mac address which you wanna connect src device. (ex. b f8:d0:bd:7f:e9:7c)\n");
+#endif
+       g_print("P : Pause\n");
+       g_print("R : Resume\n");
+       g_print("D : Disconnect\n");
+       g_print("T : desTroy\n");
+       g_print("L : Setting resolution\n");
+       g_print("G : Getting negotiated audio and video information\n");
+       g_print("S : Setting Sink\n");
+       g_print("C : Setting window size\n");
+       g_print("q : quit\n");
+       g_print("-----------------------------------------------------------------------------------------\n");
+}
+
+gboolean __timeout_menu_display(void *data)
+{
+       __displaymenu();
+
+       return FALSE;
+}
+
+#ifdef TEST_WITH_WIFI_DIRECT
+bool _connected_peer_cb(wifi_direct_connected_peer_info_s *peer, void *user_data)
+{
+       int peer_port = 0;
+       if (wifi_direct_get_peer_display_port(peer->mac_address, &peer_port) != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Can not get port info\n Use default(2022)\n");
+               peer_port = DEFAULT_SCREEN_MIRRORING_PORT;
+       }
+       if (peer_port == 0) {
+               g_print("Can not get port info\n Use default(2022)\n");
+               peer_port = DEFAULT_SCREEN_MIRRORING_PORT;
+       }
+
+       g_print("[_connected_peer_cb] Connected to IP [%s]\n", peer->ip_address);
+       g_print("[_connected_peer_cb] Connected to Port [%d]\n", peer_port);
+       g_print("[_connected_peer_cb] Connected device_name [%s]\n", peer->device_name);
+       g_print("[_connected_peer_cb] Connected to mac_address [%s]\n", peer->mac_address);
+       g_print("[_connected_peer_cb] Connected to interface_address [%s]\n", peer->interface_address);
+
+       memset(g_peer_ip, 0x00, sizeof(g_peer_ip));
+       memset(g_peer_port, 0x00, sizeof(g_peer_port));
+
+       snprintf(g_peer_ip, sizeof(g_peer_port), "%s", peer->ip_address);
+       snprintf(g_peer_port, sizeof(g_peer_port), "%d", peer_port);
+
+       g_timeout_add(SINKTEST_EXECUTE_DELAY, __scmirroring_secondary_sink_start, NULL);
+
+       return TRUE;
+}
+
+void _activation_cb(int error_code, wifi_direct_device_state_e device_state, void *user_data)
+{
+       gint ret = FALSE;
+       switch (device_state) {
+       case WIFI_DIRECT_DEVICE_STATE_ACTIVATED:
+               g_print("device_state : WIFI_DIRECT_DEVICE_STATE_ACTIVATED\n");
+               ret = __start_wifi_display_connection();
+               if (ret == TRUE) {
+                       g_print("__start_wifi_display_connection success\n");
+               } else {
+                       g_print("__start_wifi_display_connection fail\n");
+                       g_print("Quit Program\n");
+                       ret = wifi_direct_deinitialize();
+                       if (ret != WIFI_DIRECT_ERROR_NONE)
+                               g_print("wifi_direct_deinitialize is failed\n");
+
+                       g_scmirroring = 0;
+                       elm_exit();
+               }
+               break;
+       case WIFI_DIRECT_DEVICE_STATE_DEACTIVATED:
+               g_print("device_state : WIFI_DIRECT_DEVICE_STATE_DEACTIVATED\n");
+               break;
+       default:
+               g_print("device_state : ERROR\n");
+               break;
+       }
+
+       return;
+}
+
+bool _discovered_peer_cb(wifi_direct_discovered_peer_info_s *peer, void *user_data)
+{
+       g_print("[%d] discovered device peer : %s, %s, %d\n", g_peer_cnt, peer->device_name, peer->mac_address, peer->is_connected);
+
+       g_peer_cnt++;
+
+       return TRUE;
+}
+
+void _discover_cb(int error_code, wifi_direct_discovery_state_e discovery_state, void *user_data)
+{
+       int ret = WIFI_DIRECT_ERROR_NONE;
+       /*g_print("Discovered [ error : %d discovery state : %d ]\n", error_code, discovery_state); */
+
+       switch (discovery_state) {
+       case WIFI_DIRECT_ONLY_LISTEN_STARTED:
+               g_print("discovery_state : WIFI_DIRECT_ONLY_LISTEN_STARTED \n");
+               break;
+       case WIFI_DIRECT_DISCOVERY_STARTED:
+               g_print("discovery_state : WIFI_DIRECT_DISCOVERY_STARTED \n");
+               break;
+       case WIFI_DIRECT_DISCOVERY_FOUND:
+               g_print("discovery_state : WIFI_DIRECT_DISCOVERY_FOUND \n");
+               ret = wifi_direct_foreach_discovered_peers(_discovered_peer_cb, (void *)NULL);
+               if (ret != WIFI_DIRECT_ERROR_NONE)
+                       g_print("Error : wifi_direct_foreach_discovered_peers failed : %d\n", ret);
+               break;
+       case WIFI_DIRECT_DISCOVERY_FINISHED:
+               g_print("discovery_state : WIFI_DIRECT_DISCOVERY_FINISHED \n");
+               break;
+       default:
+               g_print("discovery_state : ERROR\n");
+               break;
+       }
+
+       return;
+}
+
+void _ip_assigned_cb(const char *mac_address, const char *ip_address, const char *interface_address, void *user_data)
+{
+       g_print("[_ip_assigned_cb] IP assigned [ ip addr : %s if addr : %s mac_addr:%s ]\n", ip_address, interface_address, mac_address);
+
+       int peer_port = 0;
+       wifi_direct_discovered_peer_info_s *peer_info = NULL;
+
+       if (wifi_direct_get_peer_display_port((char *)mac_address, &peer_port) != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Can not get port info\n Use default(2022)\n");
+               peer_port = DEFAULT_SCREEN_MIRRORING_PORT;
+       }
+       if (peer_port == 0) {
+               g_print("Can not get port info\n Use default(2022)\n");
+               peer_port = DEFAULT_SCREEN_MIRRORING_PORT;
+       }
+       if (wifi_direct_get_peer_info((char *)mac_address, &peer_info) != WIFI_DIRECT_ERROR_NONE)
+               g_print("Can not get peer info and device name\n");
+
+       if (peer_info != NULL && peer_info->device_name != NULL)
+               g_print("[_ip_assigned_cb] Connected to device_name [%s]\n", peer_info->device_name);
+
+       g_print("[_ip_assigned_cb] Connected to IP [%s]\n", ip_address);
+       g_print("[_ip_assigned_cb] Connected to Port [%d]\n", peer_port);
+       g_print("[_ip_assigned_cb] Connected to mac_address [%s]\n", mac_address);
+       g_print("[_ip_assigned_cb] Connected to interface_address [%s]\n", interface_address);
+
+       memset(g_peer_ip, 0x00, sizeof(g_peer_ip));
+       memset(g_peer_port, 0x00, sizeof(g_peer_port));
+
+       snprintf(g_peer_ip, sizeof(g_peer_port), "%s", ip_address);
+       snprintf(g_peer_port, sizeof(g_peer_port), "%d", peer_port);
+
+       g_timeout_add(SINKTEST_EXECUTE_DELAY, __scmirroring_secondary_sink_start, NULL);
+}
+
+void _connection_cb(int error_code, wifi_direct_connection_state_e connection_state, const char *mac_address, void *user_data)
+{
+       int ret = WIFI_DIRECT_ERROR_NONE;
+
+       g_print("Connected [ error : %d connection state : %d mac_addr:%s ]\n", error_code, connection_state, mac_address);
+
+       switch (connection_state) {
+       case WIFI_DIRECT_CONNECTION_REQ:
+               g_print("WIFI_DIRECT_CONNECTION_REQ : Connection is requested\n");
+               ret = wifi_direct_accept_connection((char *)mac_address);
+               if (ret != WIFI_DIRECT_ERROR_NONE)
+                       g_print("Error : wifi_direct_accept_connection failed : %d\n", ret);
+               break;
+       case WIFI_DIRECT_CONNECTION_WPS_REQ:
+               g_print("WIFI_DIRECT_CONNECTION_WPS_REQ : WPS is requested\n");
+               break;
+       case WIFI_DIRECT_CONNECTION_IN_PROGRESS:
+               g_print("WIFI_DIRECT_CONNECTION_IN_PROGRESS : Connection in progress\n");
+               break;
+       case WIFI_DIRECT_CONNECTION_RSP:
+       {
+               bool is_go = FALSE;
+               g_print("WIFI_DIRECT_CONNECTION_RSP : Connected\n");
+               ret = wifi_direct_is_group_owner(&is_go);
+               if (ret != WIFI_DIRECT_ERROR_NONE)
+                       g_print("Error : wifi_direct_is_group_owner failed : %d\n", ret);
+
+               if (is_go) {
+                       g_print("Connected as Group Owner\n");
+               } else {
+                       ret = wifi_direct_foreach_connected_peers(_connected_peer_cb, (void *)NULL);
+                       if (ret != WIFI_DIRECT_ERROR_NONE) {
+                               g_print("Error : wifi_direct_foreach_connected_peers failed : %d\n", ret);
+                               return;
+                       }
+                       g_print("Connected as Group Client\n");
+               }
+               break;
+       }
+       case WIFI_DIRECT_DISASSOCIATION_IND:
+               g_print("WIFI_DIRECT_DISASSOCIATION_IND : Disconnected by remote Group Client\n");
+               break;
+       case WIFI_DIRECT_DISCONNECTION_RSP:
+               g_print("WIFI_DIRECT_DISCONNECTION_RSP : Disconnected by local device\n");
+               break;
+       case WIFI_DIRECT_DISCONNECTION_IND:
+               g_print("WIFI_DIRECT_DISCONNECTION_IND : Disconnected by remote Group Owner\n");
+               break;
+       case WIFI_DIRECT_GROUP_CREATED:
+               g_print("WIFI_DIRECT_GROUP_CREATED : Group is created\n");
+               break;
+       case WIFI_DIRECT_GROUP_DESTROYED:
+               g_print("WIFI_DIRECT_GROUP_DESTROYED : Group is destroyed\n");
+               break;
+       default:
+               break;
+       }
+       return;
+}
+
+
+static int __wifi_direct_device_connect()
+{
+       if (strlen(g_src_mac_addr) > 17 || strlen(g_src_mac_addr) <= 0) {
+               g_print("\nWrong Mac_address");
+               return SCMIRRORING_ERROR_INVALID_OPERATION;
+       }
+
+       int err =  wifi_direct_connect(g_src_mac_addr);
+       if (err != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Failed to connect  [%d]\n", err);
+               return SCMIRRORING_ERROR_INVALID_OPERATION;
+       }
+       return SCMIRRORING_ERROR_NONE;
+}
+
+#endif
+
+static void __interpret(char *cmd)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+       gchar **value;
+       value = g_strsplit(cmd, " ", 0);
+
+       if (strncmp(cmd, "D", 1) == 0) {
+               g_print("Disconnect\n");
+               ret = scmirroring_secondary_sink_disconnect(g_scmirroring);
+       } else if (strncmp(cmd, "P", 1) == 0) {
+               g_print("Pause\n");
+               ret = scmirroring_secondary_sink_pause(g_scmirroring);
+       } else if (strncmp(cmd, "R", 1) == 0) {
+               g_print("Resume\n");
+               ret = scmirroring_secondary_sink_resume(g_scmirroring);
+       } else if (strncmp(cmd, "T", 1) == 0) {
+               g_print("Destroy\n");
+               ret = scmirroring_secondary_sink_unprepare(g_scmirroring);
+               ret = scmirroring_secondary_sink_destroy(g_scmirroring);
+       } else if (strncmp(cmd, "q", 1) == 0) {
+               __quit_program();
+       } else if (strncmp(cmd, "S", 1) == 0) {
+               g_menu = SUBMENU_SETTING_SINK;
+               g_timeout_add(100, __timeout_sink_submenu_display, 0);
+               return;
+       } else if (strncmp(cmd, "L", 1) == 0) {
+               g_menu = SUBMENU_RESOLUTION;
+               g_timeout_add(100, __timeout_resolution_submenu_display, 0);
+               return;
+       } else if (strncmp(cmd, "G", 1) == 0) {
+               g_menu = SUBMENU_GETTING_STREAM_INFO;
+               g_timeout_add(100, __timeout_stream_info_submenu_display, 0);
+               return;
+       } else if (strncmp(cmd, "C", 1) == 0) {
+               g_menu = SUBMENU_SETTING_WINDOW_SIZE;
+               g_timeout_add(100, __timeout_window_size_submenu_display, 0);
+               return;
+       }
+#ifndef TEST_WITH_WIFI_DIRECT
+       else if (strncmp(cmd, "a", 1) == 0) {
+               ret = __scmirroring_secondary_sink_create(NULL);
+               if (ret == SCMIRRORING_ERROR_NONE) {
+                       ret = scmirroring_secondary_sink_set_ip_and_port(g_scmirroring, value[1], value[2]);
+                       g_print("Input server IP and port number IP[%s] Port[%s]\n", value[1], value[2]);
+               }
+       } else if (strncmp(cmd, "s", 1) == 0) {
+               g_print("Start\n");
+               ret = __scmirroring_secondary_sink_start(NULL);
+       }
+#else
+       else if (strncmp(cmd, "b", 1) == 0) {
+               strncpy(g_src_mac_addr, value[1], sizeof(g_src_mac_addr));
+               g_src_mac_addr[17] = '\0';
+               g_print("Src mac address : %s\n", g_src_mac_addr);
+               ret = __wifi_direct_device_connect();
+       }
+#endif
+       else
+               g_print("unknown menu \n");
+
+       if (ret != SCMIRRORING_ERROR_NONE)
+               g_print("Error Occured [%d]", ret);
+
+       g_timeout_add(100, __timeout_menu_display, 0);
+
+       return;
+}
+
+gboolean __input(GIOChannel *channel)
+{
+       char buf[MAX_STRING_LEN + 3];
+       gsize read;
+       GError *error = NULL;
+
+       g_io_channel_read_chars(channel, buf, MAX_STRING_LEN, &read, &error);
+       buf[read] = '\0';
+       g_strstrip(buf);
+
+       if (g_menu == MAIN_MENU)
+               __interpret(buf);
+       else if (g_menu == SUBMENU_RESOLUTION)
+               __interpret_resolution_submenu(buf);
+       else if (g_menu == SUBMENU_GETTING_STREAM_INFO)
+               __interpret_stream_info_submenu(buf);
+       else if (g_menu == SUBMENU_SETTING_SINK)
+               __interpret_sink_submenu(buf);
+       else if (g_menu == SUBMENU_SETTING_WINDOW_SIZE)
+               __interpret_window_size_submenu(buf);
+
+       return TRUE;
+}
+
+#ifdef TEST_WITH_WIFI_DIRECT
+static gboolean __start_wifi_display_connection()
+{
+       int go_intent = 0;
+       static int is_initialized = FALSE;
+       wifi_direct_state_e direct_state = WIFI_DIRECT_STATE_DEACTIVATED;
+       gint ret = FALSE;
+
+       if (is_initialized == TRUE)
+               return TRUE;
+       is_initialized = TRUE;
+
+       /*Enable Screen Mirroring*/
+       ret = wifi_direct_init_display();
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_display_init failed : %d\n", ret);
+               return FALSE;
+       }
+
+       /*Enable Wifi Direct - You can set this as true if you want to see it from wifi-direct list*/
+       ret = wifi_direct_set_display_availability(TRUE);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_display_init failed : %d\n", ret);
+               return FALSE;
+       }
+
+       ret = wifi_direct_set_display(WIFI_DISPLAY_TYPE_SINK, 2022, 0);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_display_set_device failed : %d\n", ret);
+               return FALSE;
+       }
+
+       ret = wifi_direct_get_group_owner_intent(&go_intent);
+       g_print("go_intent = [%d]\n", go_intent);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_get_group_owner_intent failed : %d\n", ret);
+               return FALSE;
+       }
+
+       go_intent = 1;
+       ret = wifi_direct_set_group_owner_intent(go_intent);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_get_group_owner_intent failed : %d\n", ret);
+               return FALSE;
+       }
+       g_print("wifi_direct_set_group_owner_intent() result=[%d] go_intent[%d]\n", ret, go_intent);
+
+       ret = wifi_direct_set_max_clients(1);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_set_max_clients failed : %d\n", ret);
+               return FALSE;
+       }
+
+       ret = wifi_direct_get_state(&direct_state);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_get_state failed : %d\n", ret);
+               return FALSE;
+       }
+
+       if (direct_state > WIFI_DIRECT_STATE_ACTIVATING) {
+               char *device_name = NULL;
+
+               ret = wifi_direct_start_discovery(0, 20);
+               if (ret != WIFI_DIRECT_ERROR_NONE) {
+                       g_print("Error : wifi_direct_start_discovery failed : %d\n", ret);
+                       return FALSE;
+               }
+
+               ret = wifi_direct_get_device_name(&device_name);
+               if (ret != WIFI_DIRECT_ERROR_NONE) {
+                       g_print("Error : wifi_direct_get_device_name failed : %d\n", ret);
+                       return FALSE;
+               }
+
+               g_print("Device Name : [%s]\n", device_name);
+               if (device_name)
+                       free(device_name);
+
+       } else {
+               g_print("Error : Direct not activated yet\n");
+       }
+
+       g_print("====== p2p connection established ======\n");
+
+       return TRUE;
+}
+
+
+static gboolean __start_p2p_connection(gpointer data)
+{
+       int ret = WIFI_DIRECT_ERROR_NONE;
+       wifi_direct_state_e direct_state = WIFI_DIRECT_STATE_DEACTIVATED;
+
+       g_print("====== Start p2p connection ======\n");
+
+       ret = wifi_direct_initialize();
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_initialize failed : %d\n", ret);
+               return FALSE;
+       }
+
+       struct ug_data *ugd = (struct ug_data *)data;
+
+       /* Activation / Deactivation state Callback */
+       ret = wifi_direct_set_device_state_changed_cb(_activation_cb, (void *)ugd);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_set_device_state_changed_cb failed : %d\n", ret);
+               goto error;
+       }
+
+       /* Discovery state Callback */
+       ret = wifi_direct_set_discovery_state_changed_cb(_discover_cb, (void *)ugd);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_set_discovery_state_changed_cb failed : %d\n", ret);
+               goto error;
+       }
+
+       /* Connection state Callback */
+       ret = wifi_direct_set_connection_state_changed_cb(_connection_cb, (void *)ugd);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_set_connection_state_changed_cb failed : %d\n", ret);
+               goto error;
+       }
+
+       /* IP address assigning state callback */
+       ret = wifi_direct_set_client_ip_address_assigned_cb(_ip_assigned_cb, (void *)ugd);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_set_client_ip_address_assigned_cb failed : %d\n", ret);
+               goto error;
+       }
+
+       ret = wifi_direct_get_state(&direct_state);
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_get_state failed : %d\n", ret);
+               goto error;
+       }
+
+       if (direct_state < WIFI_DIRECT_STATE_ACTIVATED) {
+               g_print("wifi direct status < WIFI_DIRECT_STATE_ACTIVATED\n");
+               g_print("\n------Starting to activate scmirroring------\n");
+               ret = wifi_direct_activate();
+               if (ret < WIFI_DIRECT_ERROR_NONE) {
+                       g_print("Error : wifi_direct_activate failed : %d\n", ret);
+                       return FALSE;
+               }
+       } else {
+               g_print("wifi direct status >= WIFI_DIRECT_STATE_ACTIVATED.. Disconnect all first\n");
+               ret = wifi_direct_disconnect_all();
+               if (!ret)
+                       g_print("wifi_direct_disconnect_all success\n");
+               else
+                       g_print("wifi_direct_disconnect_all fail\n");
+
+               ret = __start_wifi_display_connection();
+               if (ret == TRUE) {
+                       g_print("__start_wifi_display_connection success\n");
+               } else {
+                       g_print("__start_wifi_display_connection fail\n");
+                       goto error;
+               }
+       }
+
+       return TRUE;
+
+error:
+       ret = wifi_direct_deinitialize();
+
+       return FALSE;
+}
+
+static gboolean __disconnect_p2p_connection(void)
+{
+       int ret = WIFI_DIRECT_ERROR_NONE;
+
+       ret = wifi_direct_deactivate();
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_deactivate failed : %d\n", ret);
+               return FALSE;
+       }
+
+       ret = wifi_direct_deinitialize();
+       if (ret != WIFI_DIRECT_ERROR_NONE) {
+               g_print("Error : wifi_direct_deinitialize failed : %d\n", ret);
+               return FALSE;
+       }
+
+       g_print("------p2p connection disconnected------\n");
+
+       return TRUE;
+}
+#endif
+
+#ifndef TEST_WITH_WIFI_DIRECT
+static int __scmirroring_secondary_sink_create(gpointer data)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       ret = scmirroring_secondary_sink_create(&g_scmirroring);
+       if (ret != SCMIRRORING_ERROR_NONE) {
+               g_print("scmirroring_secondary_sink_create fail [%d]", ret);
+               return SCMIRRORING_ERROR_INVALID_OPERATION;
+       }
+
+       //char ip[50]={0};
+       //strncpy(ip,"192.168.0.23",50);
+       //g_print("IP is %s\n", ip);
+       //ret=scmirroring_sink_set_coupled_ip(g_scmirroring,ip);
+       if (g_sinktype != -1) {
+               if (g_sinktype == SCMIRRORING_DISPLAY_TYPE_OVERLAY) {
+                       evas_object_show(g_evas);
+                       ret = scmirroring_secondary_sink_set_display(g_scmirroring, SCMIRRORING_DISPLAY_TYPE_OVERLAY, (void *)g_evas);
+               } else if (g_sinktype == SCMIRRORING_DISPLAY_TYPE_EVAS) {
+                       g_eo = create_evas_image_object(g_evas);
+                       evas_object_image_size_set(g_eo, 800, 1200);
+                       evas_object_image_fill_set(g_eo, 0, 0, 800, 1200);
+                       evas_object_resize(g_eo, 800, 1200);
+                       evas_object_show(g_evas);
+                       ret = scmirroring_secondary_sink_set_display(g_scmirroring, SCMIRRORING_DISPLAY_TYPE_EVAS, (void *)g_eo);
+               }
+
+               if (ret != SCMIRRORING_ERROR_NONE) {
+                       g_print("scmirroring_secondary_sink_set_display fail [%d]", ret);
+                       return FALSE;
+               }
+       }
+
+       ret = scmirroring_secondary_sink_prepare(g_scmirroring);
+       if (ret != SCMIRRORING_ERROR_NONE) {
+               g_print("scmirroring_secondary_sink_prepare fail [%d]", ret);
+               return SCMIRRORING_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+#endif
+
+gboolean __scmirroring_secondary_sink_start(gpointer data)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+       g_print("__scmirroring_secondary_sink_start <enter>\n");
+
+#ifdef TEST_WITH_WIFI_DIRECT
+       ret = scmirroring_secondary_sink_create(&g_scmirroring);
+       if (ret != SCMIRRORING_ERROR_NONE) {
+               g_print("scmirroring_secondary_sink_create fail [%d]", ret);
+               return FALSE;
+       }
+
+       if (g_resolution != 0) {
+               ret = scmirroring_secondary_sink_set_resolution(g_scmirroring, g_resolution);
+               if (ret != SCMIRRORING_ERROR_NONE)
+                       g_print("Failed to set resolution, error[%d]\n", ret);
+       }
+
+       if (g_sinktype != -1) {
+
+               if (g_sinktype == SCMIRRORING_DISPLAY_TYPE_OVERLAY) {
+                       evas_object_show(g_evas);
+                       ret = scmirroring_secondary_sink_set_display(g_scmirroring, SCMIRRORING_DISPLAY_TYPE_OVERLAY, (void *)g_evas);
+               } else if (g_sinktype == SCMIRRORING_DISPLAY_TYPE_EVAS) {
+                       g_eo = create_evas_image_object(g_evas);
+                       evas_object_image_size_set(g_eo, 800, 1200);
+                       evas_object_image_fill_set(g_eo, 0, 0, 800, 1200);
+                       evas_object_resize(g_eo, 800, 1200);
+                       evas_object_show(g_evas);
+                       ret = scmirroring_secondary_sink_set_display(g_scmirroring, SCMIRRORING_DISPLAY_TYPE_EVAS, (void *)g_eo);
+               }
+
+               if (ret != SCMIRRORING_ERROR_NONE) {
+                       g_print("scmirroring_secondary_sink_set_display fail [%d]", ret);
+                       return FALSE;
+               }
+       }
+
+       ret = scmirroring_secondary_sink_prepare(g_scmirroring);
+       if (ret != SCMIRRORING_ERROR_NONE) {
+               g_print("scmirroring_secondary_sink_prepare fail [%d]", ret);
+               return FALSE;
+       }
+
+       ret = scmirroring_secondary_sink_set_ip_and_port(g_scmirroring, g_peer_ip, g_peer_port);
+       if (ret != SCMIRRORING_ERROR_NONE) {
+               g_print("scmirroring_secondary_sink_set_ip_and_port fail [%d]", ret);
+               return FALSE;
+       }
+
+       g_print("Input server IP and port number IP[%s] Port[%s]\n", g_peer_ip, g_peer_port);
+#endif
+
+       ret = scmirroring_secondary_sink_set_state_changed_cb(g_scmirroring, scmirroring_sink_state_callback, NULL);
+       if (ret != SCMIRRORING_ERROR_NONE) {
+               g_print("scmirroring_secondary_sink_set_state_changed_cb fail [%d]", ret);
+               return FALSE;
+       }
+
+       ret = scmirroring_secondary_sink_connect(g_scmirroring);
+       if (ret != SCMIRRORING_ERROR_NONE) {
+               g_print("scmirroring_secondary_sink_connect fail [%d]", ret);
+               return FALSE;
+       }
+
+       g_print("__scmirroring_secondary_sink_start <leave>\n");
+       return FALSE;
+}
+
+gboolean _scmirroring_start_jobs(gpointer data)
+{
+#ifdef TEST_WITH_WIFI_DIRECT
+       int ret = WIFI_DIRECT_ERROR_NONE;
+
+       ret = __start_p2p_connection(data);
+       if (ret == FALSE)
+               return FALSE;
+#endif
+
+       return TRUE;
+}
+
+int main(int argc, char *argv[])
+{
+       int ret = 0;
+       GIOChannel *stdin_channel;
+
+       stdin_channel = g_io_channel_unix_new(0);
+       g_io_channel_set_flags(stdin_channel, G_IO_FLAG_NONBLOCK, NULL);
+       g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)__input, NULL);
+
+       __displaymenu();
+
+       ops.data = NULL;
+       ret = appcore_efl_main(PACKAGE, &argc, &argv, &ops);
+
+       return ret;
+}