Initial draft of R2 feature 'Secondary Sink'. 08/205408/1 tizen_dev
authorHyunsoo Park <hance.park@samsung.com>
Fri, 3 May 2019 05:31:13 +0000 (14:31 +0900)
committerHyunsoo Park <hance.park@samsung.com>
Fri, 3 May 2019 05:31:13 +0000 (14:31 +0900)
It enables 'Coupling' between Primary sink and Secondary sink.
- Setting coupled status and address.
[Setting values]
Source side
'coupling_mode' : server mode (It would try to set coupling to connected sink)
Sink side
'coupled_sink_address' : coupled sink address (It is set if coupling is succeeded)

Change-Id: I4b8e1aceb58b101e6e91b7b463b6c26a16716839
Signed-off-by: Hyunsoo Park <hance.park@samsung.com>
17 files changed:
include/scmirroring_internal.h
include/scmirroring_primary_sink.h
include/scmirroring_private.h
include/scmirroring_src.h
include/scmirroring_src_ini.h
include/scmirroring_type.h
miracast_server/miracast_server.h
miracast_server/miracast_server_impl.c
src/scmirroring_primary_sink.c
src/scmirroring_secondary_sink.c
src/scmirroring_sink.c
src/scmirroring_src.c
src/scmirroring_src_ini.c
test/scmirroring_test.c
test_sink/scmirroring_primary_sink_test.c
test_sink/scmirroring_secondary_sink_test.c
test_sink/scmirroring_sink_test.c

index b4763e9a9471778ad06a99bbb792b0d19f4d7548..8af1812be03731c174f93c99518378f81dc7754a 100644 (file)
@@ -54,7 +54,6 @@ typedef enum {
        SCMIRRORING_STATE_PLAYING,          /**< Screen mirroring is now playing media */
        SCMIRRORING_STATE_PAUSED,           /**< Screen mirroring is paused while playing media */
        SCMIRRORING_STATE_TEARDOWN,         /**< Teardown Screen mirroring */
-       SCMIRRORING_STATE_TEARDOWN_FOR_SINK,/**< Teardown Screen mirroring */
        SCMIRRORING_STATE_MAX               /* Number of screen mirroring states */
 } scmirroring_state_e;
 
index 242f6cbe9c2280b4a3c2bdf9b8a6b064de881950..529c1e2f21e2b11b8c0acc29d649d28cf29a6cb5 100644 (file)
@@ -592,6 +592,8 @@ int scmirroring_primary_sink_get_negotiated_audio_bitwidth(scmirroring_primary_s
  * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
  */
 int scmirroring_primary_sink_get_current_state(scmirroring_primary_sink_h scmirroring_primary_sink, scmirroring_sink_state_e *state);
+int scmirroring_primary_sink_set_coupled_sink_status(scmirroring_primary_sink_h scmirroring_primary_sink, int status);
+
 
 /**
  * @brief Creates screen mirroring source handle.
@@ -854,6 +856,7 @@ int scmirroring_primary_src_resume(scmirroring_primary_sink_h scmirroring_primar
  * @see scmirroring_primary_src_start()
  */
 int scmirroring_primary_src_set_direct_streaming(scmirroring_primary_sink_h scmirroring_primary_sink_src, scmirroring_direct_streaming_e enable, const char *uri_srcname);
+int scmirroring_primary_src_set_coupling_mode(scmirroring_primary_sink_h scmirroring, scmirroring_coupling_mode_e coupling_mode);
 
 /**
  * @brief Change transport for AV streaming.
index 7f78fb0a0881867945e8368e1642f96585ef3c1e..93d6239985eaa40ab2f0cb536fdbcf7d650be71e 100644 (file)
@@ -133,6 +133,7 @@ typedef struct {
        scmirroring_direct_streaming_e direct_streaming;
        char *filesrc;
        scmirroring_av_transport_e av_transport;
+       scmirroring_coupling_mode_e coupling_mode;
 } scmirroring_src_s;
 
 typedef struct {
@@ -145,11 +146,11 @@ typedef struct {
 } scmirroring_sink_s;
 
 typedef struct {
+       unsigned int magic_num;
        MMHandleType mm_handle;
        char *ip;
        char *port;
        bool use_hdcp;
-       unsigned int magic_num;
        char *server_name;
        int resolution;
        int connected;
@@ -165,6 +166,8 @@ typedef struct {
        scmirroring_direct_streaming_e direct_streaming;
        char *filesrc;
        scmirroring_av_transport_e av_transport;
+       char *coupled_sink_address;
+       scmirroring_coupling_mode_e coupling_mode; //MAKE SERVER COUPLING MODE
 } scmirroring_primary_sink_s;
 
 
index fa1dc0463bac8a13062248e5f95e21c0d47c87af..1f15a4dd7ea7de0d81411041e927f3eedad7370c 100644 (file)
@@ -166,6 +166,7 @@ int scmirroring_src_set_server_name(scmirroring_src_h scmirroring_src, const cha
  * @see scmirroring_src_create()
  */
 int scmirroring_src_set_multisink_ability(scmirroring_src_h scmirroring_src, scmirroring_multisink_e multisink);
+int scmirroring_src_set_coupling_mode(scmirroring_src_h scmirroring, scmirroring_coupling_mode_e coupling_mode);
 
 /**
  * @brief Connects to server for screen mirroring as source, asynchronously.
index 56893a5dda99fcdee0d49b682b2e4b16e5bff791..ae6b42fbe966de6a5ee08c4b26f542fd5560e842 100644 (file)
@@ -90,6 +90,7 @@ typedef struct __scmirroring_src_ini {
 
        gint dump_ts;
 
+       gint wfd2_supported;
 } scmirroring_src_ini_t;
 
 /* default values if each values are not specified in inifile */
@@ -142,6 +143,10 @@ typedef struct __scmirroring_src_ini {
 #define DEFAULT_UIBC_GEN_CAPABILITY 15
 #define DEFAULT_DUMP_TS                                0
 
+/* R2 features */
+#define DEFAULT_WFD2_SUPPORTED 0
+
+
 
 int
 scmirroring_src_ini_load(void);
index 73d3e6f9c3dbe5bdc1f265767178e0f1bc26c684..1943ffb00adbdd599c1e1e9e1aca7d4420185cbf 100644 (file)
@@ -145,6 +145,22 @@ typedef enum {
        SCMIRRORING_DIRECT_STREAMING_ENABLED          /**< Enable direct streaming for files */
 } scmirroring_direct_streaming_e;
 
+/**
+ * @brief Enumeration for screen mirroring direct streaming mode.
+ * @since_tizen 5.5
+ */
+typedef enum {
+       SCMIRRORING_COUPLING_MODE_DISABLED = 0,    /**< Disable coupling mode of miracast server */
+       SCMIRRORING_COUPLING_MODE_ENABLED          /**< Enable coupling mode of miracast server */
+} scmirroring_coupling_mode_e;
+
+typedef enum {
+  SCMIRRORING_COUPLING_STATUS_NOT_COUPLED = 0,
+  SCMIRRORING_COUPLING_STATUS_COUPLED,
+  SCMIRRORING_COUPLING_STATUS_TEARDOWN_COUPLING,
+  SCMIRRORING_COUPLING_STATUS_MAX
+} scmirroring_coupled_sink_status_e;
+
 /**
  * @brief Enumeration for screen mirroring AV streaming transport.
  * @since_tizen 3.0
index 4a7b4f61dc55d2a99f88c0089497fd81104553e2..b91c4c9e9c457d0c8237e033f7abf60ee475f948 100644 (file)
@@ -50,6 +50,7 @@ struct _MiracastServer {
        gint resolution;
        gint connection_mode;
        gint multisink;
+    gint coupling_mode;
 
        gpointer _gst_reserved[GST_PADDING];
 };
index f64077beb66d879689a6afe2fba80cbf95f0a853..82a0a2e59f2e9e4c3e3ae252f896282ea0edff12 100644 (file)
@@ -52,7 +52,7 @@
 
 #define SWITCH_TO_UDP 0
 #define SWITCH_TO_TCP 1
-#define SECONDARY_SINK_IP "192.168.0.10"
+#define COUPLED_SINK_ADDRESS "192.168.0.50"
 
 static gint g_server_status = MIRACAST_WFD_SOURCE_OFF;
 
@@ -148,6 +148,7 @@ static void miracast_server_init(MiracastServer *obj)
        obj->factory = NULL;
        obj->resolution = 0;
        obj->multisink = SCMIRRORING_MULTISINK_ENABLE;
+       obj->coupling_mode = FALSE;
 }
 
 static void miracast_server_class_init(MiracastServerClass *klass)
@@ -497,9 +498,9 @@ __client_closed(GstRTSPClient *client, gpointer user_data)
        scmirroring_debug("client %p: connection closed", client);
 
        /* Sends Secondary sink ip to scmirroring_src */
-       if(g_strcmp0(gst_rtsp_connection_get_ip(connection), SECONDARY_SINK_IP) == 0){
-               gchar * msg = g_malloc(sizeof(char *) * 30);
-               g_sprintf(msg, "SECONDARY_IP:%s",gst_rtsp_connection_get_ip(connection));
+       if(g_strcmp0(gst_rtsp_connection_get_ip(connection), COUPLED_SINK_ADDRESS) == 0){
+               gchar * msg = g_malloc(sizeof(char *) * 50);
+               g_sprintf(msg, "MESSAGE:COUPLED_SINK_ADDRESS:%s", gst_rtsp_connection_get_ip(connection));
                klass->send_response(server_obj,msg);
                g_free(msg);
                usleep(250000);
@@ -710,7 +711,10 @@ int __miracast_server_start(MiracastServer *server_obj)
 
        gst_rtsp_media_factory_wfd_set_dump_ts(factory, scmirroring_src_ini_get_structure()->dump_ts);
        if (server_obj->multisink == SCMIRRORING_MULTISINK_ENABLE)
-               gst_rtsp_media_factory_set_shared(GST_RTSP_MEDIA_FACTORY_CAST(factory), TRUE);
+               gst_rtsp_media_factory_set_shared(GST_RTSP_MEDIA_FACTORY_CAST(factory), TRUE);  
+
+       gst_rtsp_wfd_server_set_wfd2_supported(server,
+               scmirroring_src_ini_get_structure()->wfd2_supported);
 
        g_signal_connect(GST_RTSP_MEDIA_FACTORY(factory), "media-constructed", (GCallback) __media_constructed, server_obj);
 
@@ -755,6 +759,26 @@ failed:
        return SCMIRRORING_ERROR_INVALID_OPERATION;
 }
 
+static int __miracast_server_set_coupling_mode(MiracastServer *server_obj, gboolean coupling_mode)
+{
+       GstRTSPWFDServer *server = NULL;
+       server = (GstRTSPWFDServer *)server_obj->server;
+       if (server == NULL) {
+               scmirroring_error("No server object");
+               goto failed;
+       }
+
+       if (gst_rtsp_wfd_server_set_coupling_mode(server, coupling_mode) != ERROR_NONE) {
+               scmirroring_error("Failed to set coupling mode to server object");
+               goto failed;
+       }
+
+       return SCMIRRORING_ERROR_NONE;
+failed:
+       scmirroring_error("Failed to set coupling mode");
+       return SCMIRRORING_ERROR_INVALID_OPERATION;
+}
+
 static int __miracast_server_switch_transport(MiracastServer *server_obj, gint transport)
 {
        GstRTSPWFDServer *server = NULL;
@@ -886,6 +910,20 @@ void __miracast_server_interpret(MiracastServer *server, gchar *buf)
 
                g_strfreev(streaming_info);
 
+       } else if (g_strrstr(buf, "SET COUPLING_MODE")) {
+               gchar **coupling_info;
+               gint coupling = 0;
+
+               coupling_info = g_strsplit(buf, " ", 0);
+
+               coupling = atoi(coupling_info[2]);
+               server->coupling_mode = coupling;
+
+               __miracast_server_set_coupling_mode(server, server->coupling_mode );
+
+               g_strfreev(coupling_info);
+
+               klass->send_response(server, "OK:SET");
        } else if (g_strrstr(buf, "SWITCH UDP")) {
                scmirroring_debug("Swithc AV streaming transport to UDP");
 
index f274fd206af79e15e542af0aecf2254847302180..eaa4bebbbb6c0de3c785fbe6c058e98704f95620 100644 (file)
@@ -69,7 +69,7 @@ static scmirroring_error_e __scmirroring_primary_sink_error_convert(const char *
        return ret;
 }
 
-static scmirroring_sink_state_e __SCMIRRORING_SINK_STATE_convert(MMWFDSinkStateType mm_state)
+static scmirroring_sink_state_e __scmirroring_primary_sink_state_convert(MMWFDSinkStateType mm_state)
 {
        scmirroring_sink_state_e state = SCMIRRORING_SINK_STATE_NONE;
 
@@ -106,7 +106,7 @@ static scmirroring_sink_state_e __SCMIRRORING_SINK_STATE_convert(MMWFDSinkStateT
 void __mm_scmirroring_primary_sink_set_message_cb(int error_type, MMWFDSinkStateType state_type, void *uData)
 {
        scmirroring_error_e error = __scmirroring_primary_sink_error_convert(__func__, error_type);
-       scmirroring_sink_state_e state = __SCMIRRORING_SINK_STATE_convert(state_type);
+       scmirroring_sink_state_e state = __scmirroring_primary_sink_state_convert(state_type);
        scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)uData;
 
        /* call application callback */
@@ -127,14 +127,31 @@ int scmirroring_primary_sink_create(scmirroring_primary_sink_h *scmirroring_prim
        scmirroring_retvm_if(scmirroring_primary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink is NULL");
 
        scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)calloc(1, sizeof(scmirroring_primary_sink_s));
-       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Fail to allocate memory for handle");
+
+       scmirroring_error("New to Create");
+
+       handle->magic_num = SCMIRRORING_MAGIC_NUMBER;
 
        handle->mm_handle = 0;
+       handle->use_hdcp = TRUE;
+       handle->scmirroring_sink_state_cb = NULL;
+
        handle->ip = NULL;
        handle->port = NULL;
+       handle->filesrc = NULL;
+       handle->connected = NOT_CONNECTED_TO_SERVER;
        handle->use_hdcp = TRUE;
-       handle->scmirroring_sink_state_cb = NULL;
-       handle->magic_num = SCMIRRORING_MAGIC_NUMBER;
+       handle->resolution = 0;
+       handle->connect_mode = SCMIRRORING_CONNECTION_WIFI_DIRECT;
+       handle->scmirroring_state_cb = NULL;
+       handle->sock = -1;
+       handle->channel = NULL;
+       handle->sock_path = NULL;
+       handle->current_state = SCMIRRORING_STATE_CREATED;
+       handle->server_name = g_strdup("scmirroring");
+       handle->multisink = SCMIRRORING_MULTISINK_DISABLE;
+       handle->av_transport = SCMIRRORING_AV_TRANSPORT_UDP;
+       handle->coupling_mode = SCMIRRORING_COUPLING_MODE_DISABLED;
 
        ret = mm_wfd_sink_create_r2(&handle->mm_handle);
        if (ret != MM_ERROR_NONE) {
@@ -722,7 +739,7 @@ int scmirroring_primary_sink_get_current_state(scmirroring_primary_sink_h scmirr
 
        result = mm_wfd_sink_get_current_state(handle->mm_handle, &mm_state);
        if (result == MM_ERROR_NONE) {
-               *state = __SCMIRRORING_SINK_STATE_convert(mm_state);
+               *state = __scmirroring_primary_sink_state_convert(mm_state);
                scmirroring_debug("ScreenMirroring current state is [%d]", *state);
        }
        scmirroring_debug_fleave();
@@ -753,6 +770,36 @@ int scmirroring_primary_sink_set_coupled_sink(scmirroring_primary_sink_h scmirro
        return ret;
 }
 
+int scmirroring_primary_sink_set_coupled_sink_status(scmirroring_primary_sink_h scmirroring_primary_sink, int status)
+{
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)scmirroring_primary_sink;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink is NULL");
+       scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink is invalid handle");
+
+       if ((status < SCMIRRORING_COUPLING_STATUS_NOT_COUPLED) || (status >= SCMIRRORING_COUPLING_STATUS_MAX)) {
+               scmirroring_error("Invalid status : %d", status);
+               return SCMIRRORING_ERROR_INVALID_PARAMETER;
+       }
+
+       scmirroring_debug("coupled sink status(%d)", status);
+       ret = mm_wfd_sink_set_coupled_sink_status(handle->mm_handle, status);
+       if (ret != MM_ERROR_NONE) {
+               scmirroring_error("Fail to Set resolution");
+               return __scmirroring_primary_sink_error_convert(__func__, ret);
+       }
+
+       ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
 static gboolean __scmirroring_primary_src_callback_call(gpointer data)
 {
        scmirroring_primary_sink_s *scmirroring = (scmirroring_primary_sink_s *) data;
@@ -934,6 +981,17 @@ static int __scmirroring_primary_src_get_status(gchar *str)
        return SCMIRRORING_STATE_CREATED;
 }
 
+static int __scmirroring_primary_src_get_messages(scmirroring_primary_sink_s *scmirroring, gchar *key, gchar* value)
+{
+       if (g_strrstr(key, "COUPLED_SINK_ADDRESS")) {
+               //if this is set, coupled_sink_status would be 0b01.
+               scmirroring->coupled_sink_address = g_strdup(value);
+
+               return SCMIRRORING_STATE_CONNECTED;
+       }
+       return SCMIRRORING_STATE_CREATED;
+}
+
 static void __scmirroring_primary_src_set_callback_info(scmirroring_primary_sink_s *scmirroring, int error_code, int state)
 {
        scmirroring_state_cb_s *cb_info = scmirroring->scmirroring_state_cb;
@@ -963,23 +1021,30 @@ static void __scmirroring_primary_src_interpret(scmirroring_primary_sink_s *scmi
 
        scmirroring_debug("error: %s, status: %s", response[0], response[1]);
 
-       /* if front-half message is "OK" or "FAIL", it is ERROR:STATE pair*/
+       /* state messages */
        if(g_strcmp0("OK",response[0]) == 0 || g_strcmp0("FAIL",response[0]) == 0){
                error_code = __scmirroring_primary_src_get_error(response[0]);
-               src_state = __scmirroring_primary_src_get_status(response[1]);;
-               g_strfreev(response);
+               src_state = __scmirroring_primary_src_get_status(response[1]);
+
                if (scmirroring->current_state != src_state) {
                        scmirroring->current_state = src_state;
                        __scmirroring_primary_src_set_callback_info(scmirroring, error_code, src_state);
                } else {
                        scmirroring_debug("Current state is already %d", src_state);
                }
-       }else{
-               /* for coupled sink */
-               error_code = SCMIRRORING_ERROR_NONE;
-               src_state = SCMIRRORING_STATE_TEARDOWN_FOR_SINK;
+       /* other messages, state is depended on response[1] and actual messages are response[2] */
+       } else if (g_strcmp0("MESSAGE", response[0]) == 0 ) {
+               error_code = __scmirroring_primary_src_get_error(response[0]);
+               src_state = __scmirroring_primary_src_get_messages(scmirroring, response[1], response[2]);
+               scmirroring_debug("message key : %s , value : %s", response[1], response[2]);
                __scmirroring_primary_src_set_callback_info(scmirroring, error_code, src_state);
+
+               if (!g_strcmp0("COUPLED_SINK_ADDRESS", response[1])) {
+                       g_print("yes , coupled_sink_address");
+                       scmirroring_primary_sink_set_coupled_sink_status(scmirroring, 1);
+               }
        }
+       g_strfreev(response);
 
        return;
 }
@@ -1129,6 +1194,26 @@ static int __scmirroring_primary_src_send_set_direct_streaming(scmirroring_prima
        return ret;
 }
 
+static int __scmirroring_primary_src_send_set_coupling_mode(scmirroring_primary_sink_h scmirroring)
+{
+       /* Set coupling mode to miracast server */
+       char *cmd = NULL;
+       int ret = SCMIRRORING_ERROR_NONE;
+       scmirroring_primary_sink_s *_scmirroring = (scmirroring_primary_sink_s *)scmirroring;
+
+       cmd = g_strdup_printf("SET COUPLING_MODE %d", _scmirroring->coupling_mode);
+       ret = __scmirroring_primary_src_send_cmd_to_server(_scmirroring, cmd);
+       if (ret != SCMIRRORING_ERROR_NONE) {
+               SCMIRRORING_SAFE_G_FREE(cmd);
+               scmirroring_error("Failed to be ready [%d]", ret);
+               return SCMIRRORING_ERROR_INVALID_OPERATION;
+       }
+
+       SCMIRRORING_SAFE_G_FREE(cmd);
+
+       return ret;
+}
+
 static int __scmirroring_primary_src_send_switch_transport(scmirroring_primary_sink_h scmirroring)
 {
        /* Set tranport protocol to miracast server */
@@ -1180,6 +1265,7 @@ int scmirroring_primary_src_create(scmirroring_primary_sink_h *scmirroring)
        _scmirroring->server_name = g_strdup("scmirroring");
        _scmirroring->multisink = SCMIRRORING_MULTISINK_DISABLE;
        _scmirroring->av_transport = SCMIRRORING_AV_TRANSPORT_UDP;
+       _scmirroring->coupling_mode = SCMIRRORING_COUPLING_MODE_DISABLED;
 
        *scmirroring = (scmirroring_primary_sink_h)_scmirroring;
 
@@ -1630,6 +1716,40 @@ int scmirroring_primary_src_set_direct_streaming(scmirroring_primary_sink_h scmi
        return ret;
 }
 
+
+int scmirroring_primary_src_set_coupling_mode(scmirroring_primary_sink_h scmirroring, scmirroring_coupling_mode_e coupling_mode)
+{
+       CHECK_FEATURE_SUPPORTED(WIFIDIRECT_DISPLAY_FEATURE);
+
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_primary_sink_s *_scmirroring = (scmirroring_primary_sink_s *)scmirroring;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(_scmirroring == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       scmirroring_retvm_if(_scmirroring->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "Invalid handle");
+       scmirroring_error("scmirroring_primary_src_set_coupling_mode1");
+
+       if ((coupling_mode < SCMIRRORING_COUPLING_MODE_DISABLED) || (coupling_mode > SCMIRRORING_COUPLING_MODE_ENABLED)) {
+               scmirroring_error("INVALID coupling mode : %d", coupling_mode);
+               return SCMIRRORING_ERROR_INVALID_PARAMETER;
+       }
+       scmirroring_error("scmirroring_primary_src_set_coupling_mode2");
+
+
+       _scmirroring->coupling_mode = coupling_mode;    
+       scmirroring_error("scmirroring_primary_src_set_coupling_mode3");
+
+       if (_scmirroring->connected)
+               ret = __scmirroring_primary_src_send_set_coupling_mode(_scmirroring);   
+       scmirroring_error("scmirroring_primary_src_set_coupling_mode4");
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
 int scmirroring_primary_src_AV_transport_switch(scmirroring_primary_sink_h scmirroring,
                scmirroring_av_transport_e transport)
 {
@@ -1696,13 +1816,8 @@ int scmirroring_primary_src_destroy(scmirroring_primary_sink_h scmirroring)
                        scmirroring_error("Failed to disconnect server [%d]", ret);
        }
 
-       _scmirroring->magic_num = 0;
-
-       SCMIRRORING_SAFE_FREE(_scmirroring->ip);
-       SCMIRRORING_SAFE_FREE(_scmirroring->port);
        SCMIRRORING_SAFE_FREE(_scmirroring->scmirroring_state_cb);
        SCMIRRORING_SAFE_G_FREE(_scmirroring->server_name);
-       SCMIRRORING_SAFE_FREE(_scmirroring);
 
        scmirroring_debug_fleave();
 
index 6facf98db8760b74a8b0aca96a2b90354aaf85a4..ef309f45d24a8177890f76cc6b10c0e02077ca22 100755 (executable)
@@ -57,7 +57,7 @@ static scmirroring_error_e __scmirroring_secondary_sink_error_convert(const char
        return ret;
 }
 
-static scmirroring_sink_state_e __SCMIRRORING_SINK_STATE_convert(MMWFDSinkStateType mm_state)
+static scmirroring_sink_state_e __scmirroring_secondary_sink_state_convert(MMWFDSinkStateType mm_state)
 {
        scmirroring_sink_state_e state = SCMIRRORING_SINK_STATE_NONE;
 
@@ -94,7 +94,7 @@ static scmirroring_sink_state_e __SCMIRRORING_SINK_STATE_convert(MMWFDSinkStateT
 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_sink_state_e state = __scmirroring_secondary_sink_state_convert(state_type);
        scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)uData;
 
        /* call application callback */
@@ -545,7 +545,7 @@ int scmirroring_secondary_sink_get_current_state(scmirroring_secondary_sink_h sc
 
        result = mm_wfd_sink_get_current_state(handle->mm_handle, &mm_state);
        if (result == MM_ERROR_NONE) {
-               *state = __SCMIRRORING_SINK_STATE_convert(mm_state);
+               *state = __scmirroring_secondary_sink_state_convert(mm_state);
                scmirroring_debug("ScreenMirroring current state is [%d]", *state);
        }
        scmirroring_debug_fleave();
index 0faac238c4dffafc4775ccec60c07b3536a6f6ca..74fbc2559fc1c4f650eea42afa077e4ffd5da776 100644 (file)
@@ -44,7 +44,7 @@ static scmirroring_error_e __scmirroring_sink_error_convert(const char *func, in
                errorstr = "INVALID_PARAMETER";
                break;
 
-       default:
+       default: //MM_ERROR_WFD_INTERNAL (0x80000906)
                ret = SCMIRRORING_ERROR_INVALID_OPERATION;
                errorstr = "INVALID_OPERATION";
        }
index 2d9ef9b5bc25a82312d4cb027bdc5769f078f0c6..ddb0cdf300f5c9511a33a49726721b23fc42c3f8 100644 (file)
@@ -243,7 +243,10 @@ static void __scmirroring_src_interpret(scmirroring_src_s *scmirroring, char *bu
        /* if front-half message is "OK" or "FAIL", it is ERROR:STATE pair*/
        if(g_strcmp0("OK",response[0]) == 0 || g_strcmp0("FAIL",response[0]) == 0){
                error_code = __scmirroring_src_get_error(response[0]);
-               src_state = __scmirroring_src_get_status(response[1]);;
+               src_state = __scmirroring_src_get_status(response[1]);
+               if(response[2] != NULL){
+                       scmirroring_debug("response2 : %s",  response[2]);
+                       }
                g_strfreev(response);
                if (scmirroring->current_state != src_state) {
                        scmirroring->current_state = src_state;
@@ -251,16 +254,15 @@ static void __scmirroring_src_interpret(scmirroring_src_s *scmirroring, char *bu
                } else {
                        scmirroring_debug("Current state is already %d", src_state);
                }
-
-       }else{
+       } else if (g_strcmp0("SECONDARY_SINK",response[0]) == 0 ) {
                /* for coupled sink */
                error_code = SCMIRRORING_ERROR_NONE;
-               src_state = SCMIRRORING_STATE_TEARDOWN_FOR_SINK;
-               scmirroring_debug("__scmirroring_src_interpret is here %d : %d", error_code, src_state);
+               src_state = SCMIRRORING_STATE_TEARDOWN;
                __scmirroring_src_set_callback_info(scmirroring, error_code, src_state);
        }
 
        return;
+
 }
 
 gboolean __scmirroring_src_read_cb(GIOChannel *src, GIOCondition condition, gpointer data)
@@ -386,6 +388,26 @@ static int __scmirroring_src_send_set_multisink(scmirroring_src_h scmirroring)
        return ret;
 }
 
+static int __scmirroring_src_send_set_coupling_mode(scmirroring_src_h scmirroring)
+{
+       /* Set coupling mode to miracast server */
+       char *cmd = NULL;
+       int ret = SCMIRRORING_ERROR_NONE;
+       scmirroring_src_s *_scmirroring = (scmirroring_src_s *)scmirroring;
+
+       cmd = g_strdup_printf("SET COUPLING_MODE %d", _scmirroring->coupling_mode);
+       ret = __scmirroring_src_send_cmd_to_server(_scmirroring, cmd);
+       if (ret != SCMIRRORING_ERROR_NONE) {
+               SCMIRRORING_SAFE_G_FREE(cmd);
+               scmirroring_error("Failed to be ready [%d]", ret);
+               return SCMIRRORING_ERROR_INVALID_OPERATION;
+       }
+
+       SCMIRRORING_SAFE_G_FREE(cmd);
+
+       return ret;
+}
+
 static int __scmirroring_src_send_set_direct_streaming(scmirroring_src_h scmirroring)
 {
        /* Set resolution to miracast server */
@@ -658,6 +680,35 @@ int scmirroring_src_set_multisink_ability(scmirroring_src_h scmirroring, scmirro
        return ret;
 }
 
+int scmirroring_src_set_coupling_mode(scmirroring_src_h scmirroring, scmirroring_coupling_mode_e coupling_mode)
+{
+       CHECK_FEATURE_SUPPORTED(WIFIDIRECT_DISPLAY_FEATURE);
+
+       int ret = SCMIRRORING_ERROR_NONE;
+
+       scmirroring_src_s *_scmirroring = (scmirroring_src_s *)scmirroring;
+
+       scmirroring_debug_fenter();
+
+       scmirroring_retvm_if(_scmirroring == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       scmirroring_retvm_if(_scmirroring->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "Invalid handle");
+       scmirroring_error("scmirroring_primary_src_set_coupling_mode1");
+
+       if ((coupling_mode < SCMIRRORING_COUPLING_MODE_DISABLED) || (coupling_mode > SCMIRRORING_COUPLING_MODE_ENABLED)) {
+               scmirroring_error("INVALID coupling mode : %d", coupling_mode);
+               return SCMIRRORING_ERROR_INVALID_PARAMETER;
+       }
+       _scmirroring->coupling_mode = coupling_mode;    
+
+       if (_scmirroring->connected)
+               ret = __scmirroring_src_send_set_coupling_mode(_scmirroring);   
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
+
 int scmirroring_src_connect(scmirroring_src_h scmirroring)
 {
        CHECK_FEATURE_SUPPORTED(WIFIDIRECT_DISPLAY_FEATURE);
index 3cdf995a0271a4b0f6bd13ebc7e30f100087d363..db79b28f5d7900f16dd642ccc36f90e9e084fad1 100644 (file)
@@ -132,6 +132,8 @@ scmirroring_src_ini_load(void)
 
                g_scmirroring_src_ini.dump_ts = iniparser_getint(dict, "general:dump ts", DEFAULT_DUMP_TS);
 
+               g_scmirroring_src_ini.wfd2_supported = iniparser_getint(dict, "general:wfd2 wfd2_supported", DEFAULT_WFD2_SUPPORTED);
+
        } else { /* if dict is not available just fill the structure with default value */
                scmirroring_debug("failed to load ini. using hardcoded default\n");
 
@@ -192,6 +194,8 @@ scmirroring_src_ini_load(void)
                strncpy(g_scmirroring_src_ini.gst_param[3], DEFAULT_GST_PARAM, SCMIRRORING_SRC_INI_MAX_PARAM_STRLEN - 1);
                strncpy(g_scmirroring_src_ini.gst_param[4], DEFAULT_GST_PARAM, SCMIRRORING_SRC_INI_MAX_PARAM_STRLEN - 1);
                g_scmirroring_src_ini.dump_ts = DEFAULT_DUMP_TS;
+
+               g_scmirroring_src_ini.wfd2_supported = DEFAULT_WFD2_SUPPORTED;
        }
 
        /* free dict as we got our own structure */
@@ -238,6 +242,7 @@ scmirroring_src_ini_load(void)
        scmirroring_debug("gst_param5 : %s\n", g_scmirroring_src_ini.gst_param[4]);
 
        scmirroring_debug("dump ts : %d\n", g_scmirroring_src_ini.dump_ts);
+       scmirroring_debug("wfd2 wfd2_supported : %d\n", g_scmirroring_src_ini.wfd2_supported);
 
        scmirroring_debug("---------------------------------------------------\n");
 
index 84ccec91b0ad91c6ad17b93c0b1cc80684318e27..615aaf91e2c074ef7fb3bcc26567a643a6ccb4e0 100644 (file)
@@ -50,10 +50,11 @@ static void __displaymenu(void)
        g_print("c : set resolution(ex. c 0 (0 : 1920x1080_P30, 1 : 1280x720_P30, 2 : 960x540_P30, 3: 640x360_P30)\n");
        g_print("f : set connection mode(ex. f 0 (0 : wifi_direct, 1 : Other)\n");
        g_print("g : set multisink mode(ex. g 1 (0 : disable, 1 : enable)\n");
+       g_print("O : set cOupling mode(ex. O 1 (0 : disable, 1 : enable)\n");
        g_print("C : Connect\n");
        g_print("I : dIsconnect\n");
        g_print("S : Start  \n");
-       g_print("P : Pause \n");
+       g_print("P : Pause  \n");
        g_print("R : Resume \n");
        g_print("s : Direct Streaming (ex. s 1 file:///tmp/file.mp4 (0:disable, 1:enable))\n");
        g_print("u : Switch to UDP\n");
@@ -121,6 +122,9 @@ static void __interpret(char *cmd)
        } else if (strncmp(cmd, "P", 1) == 0) {
                g_print("Pause\n");
                ret = scmirroring_src_pause(g_scmirroring);
+       } else if (strncmp(cmd, "O", 1) == 0) {
+               ret = scmirroring_src_set_coupling_mode(g_scmirroring, atoi(value[1]));
+               g_print("coupling mode [%d]\n", atoi(value[1]));
        } else if (strncmp(cmd, "R", 1) == 0) {
                g_print("Resume\n");
                ret = scmirroring_src_resume(g_scmirroring);
index 6ca83af7bd862c921dd5abe84f6c26ae63ae6d22..974226f62e4941a1a277c1895909319456ff8449 100644 (file)
@@ -36,7 +36,8 @@
 #define SUBMENU_SETTING_WINDOW_SIZE 4
 //#define TEST_WITH_WIFI_DIRECT
 #define TEST_PRIMARY_SINK
-#define PACKAGE "screen_mirroring_sink_test"
+#define COUPLED_SINK_ADDRESS "192.168.0.50"
+#define PACKAGE "screen_mirroring_primary_sink_test"
 static int app_create(void *data);
 static int app_terminate(void *data);
 static Evas_Object* _create_win(const char *name);
@@ -77,7 +78,6 @@ static gboolean __start_p2p_connection(gpointer data);
 static gboolean __disconnect_p2p_connection(void);
 #endif
 static void __quit_program_sink(void);
-static void __quit_program_source(void);
 gboolean __timeout_menu_display(void *data);
 
 /* for source*/
@@ -489,27 +489,14 @@ static void __interpret_window_size_submenu(char *cmd)
        return;
 }
 
-//UserCallback
+//Source user callback
 static void scmirroring_source_state_callback(scmirroring_error_e error_code, scmirroring_state_e state, void *user_data)
 {
        g_print("\n\nReceived Callback error code[%d], state[%d]\n\n", error_code, state);
-
-       //if state 8, copy it to sink's sec_ip and make coupled_state = coupled.
-       if(state == 8){
-               g_print("Stop\n");
-               int ret=0;
-               ret = scmirroring_primary_src_stop(scmirroring_primary_sink);
-               g_print("Stopped and ret is [%d]\n",ret);
-               g_print("Stopped\n");
-               g_usleep(100000);
-               g_print("Destroy\n");
-               ret = scmirroring_primary_src_destroy(scmirroring_primary_sink);
-               g_print("Destroyed and ret is [%d]\n",ret);
-       }
-
        return;
 }
 
+//Sink user callback
 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);
@@ -521,11 +508,9 @@ static void scmirroring_sink_state_callback(scmirroring_error_e error_code, scmi
        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_primary_sink_start(scmirroring_primary_sink) != SCMIRRORING_ERROR_NONE)
                        g_print("scmirroring_primary_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)
@@ -536,32 +521,21 @@ static void scmirroring_sink_state_callback(scmirroring_error_e error_code, scmi
                        g_print("scmirroring_primary_sink_unprepare fail\n");
                if (scmirroring_primary_sink_destroy(scmirroring_primary_sink) != SCMIRRORING_ERROR_NONE)
                        g_print("scmirroring_primary_sink_destroy fail\n");
-               __quit_program_sink();
        } else
                g_print(" state[%d] Invalid State", state);
 
        return;
 }
 
-static void __quit_program_source(void)
-{
-    g_print("Quit Program\n");
-
-    scmirroring_primary_sink = 0;
-    //g_main_loop_quit(g_loop);
-}
-
-
 static void __quit_program_sink(void)
 {
-       g_print("Quit Program\n");
+       g_print("Quit sink\n");
 
 #ifdef TEST_WITH_WIFI_DIRECT
        __disconnect_p2p_connection();
 #endif
        scmirroring_primary_sink = 0;
        elm_exit();
-       g_main_loop_quit(g_loop);
 }
 
 static void __displaymenu(void)
@@ -576,11 +550,11 @@ static void __displaymenu(void)
        g_print("=====================================================================\n");
        g_print("M : Make mirroring source handle(create handle)\n");
        g_print("A : set ip & port(ex. a 192.168.49.1 2022)\n");
+       g_print("O : set coupling_mode(ex. O 1) \n");
        g_print("C : Connect\n");
        g_print("S : Start  \n");
        g_print("T : sTop\n");
        g_print("D : Destroy\n");
-       g_print("Q : quit\n");
        g_print("---------------------------------------------------------------------\n");
 #endif
 
@@ -589,6 +563,7 @@ static void __displaymenu(void)
        g_print("=====================================================================\n");
 #ifndef TEST_WITH_WIFI_DIRECT
        g_print("a : a ip port(ex. a 192.168.49.1 2022)\n");
+       g_print("P : Prepare sink\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");
@@ -837,8 +812,14 @@ static void __interpret(char *cmd)
        } else if (strncmp(cmd, "A", 1) == 0) {
                ret = scmirroring_primary_src_set_ip_and_port(scmirroring_primary_sink, 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, "O", 1) == 0) {
+               ret = scmirroring_primary_src_set_coupling_mode(scmirroring_primary_sink, atoi(value[1]));
+               g_print("cOupling mode [%d]\n", atoi(value[1]));
        } else if (strncmp(cmd, "C", 1) == 0) {
-               g_print("Connect\n");
+               g_print("Set state Changed callback function and Connect\n");
+               ret = scmirroring_primary_src_set_state_changed_cb(scmirroring_primary_sink, scmirroring_source_state_callback, NULL);
+               if (ret != SCMIRRORING_ERROR_NONE)
+                       g_print("Failed to set state changed callback\n");
                ret = scmirroring_primary_src_connect(scmirroring_primary_sink);
        } else if (strncmp(cmd, "S", 1) == 0) {
                g_print("Start\n");
@@ -849,13 +830,13 @@ static void __interpret(char *cmd)
        } else if (strncmp(cmd, "D", 1) == 0) {
                g_print("Destroy\n");
                ret = scmirroring_primary_src_destroy(scmirroring_primary_sink);
-               g_print("Destroyed\n");
-       } else if (strncmp(cmd, "Q", 1) == 0) {
-               __quit_program_source();
        }
 
        //Sink side
-       else if (strncmp(cmd, "d", 1) == 0) {
+       else if (strncmp(cmd, "P", 1) == 0) {
+               g_print("prepared \n");
+               ret = scmirroring_primary_sink_prepare(scmirroring_primary_sink);
+       } else if (strncmp(cmd, "d", 1) == 0) {
                g_print("Disconnect\n");
                ret = scmirroring_primary_sink_disconnect(scmirroring_primary_sink);
        } else if (strncmp(cmd, "p", 1) == 0) {
@@ -1143,9 +1124,6 @@ static int __scmirroring_primary_sink_create(gpointer data)
                g_print("scmirroring_primary_sink_create fail [%d]", ret);
                return SCMIRRORING_ERROR_INVALID_OPERATION;
        }
-       char address[50]={0};
-       strncpy(address,"00:00:00:00:00",50);
-       scmirroring_sink_set_coupled_sink(scmirroring_primary_sink,0,address);
 
        if (g_sinktype != -1) {
                if (g_sinktype == SCMIRRORING_DISPLAY_TYPE_OVERLAY) {
@@ -1166,11 +1144,6 @@ static int __scmirroring_primary_sink_create(gpointer data)
                }
        }
 
-       ret = scmirroring_primary_sink_prepare(scmirroring_primary_sink);
-       if (ret != SCMIRRORING_ERROR_NONE) {
-               g_print("scmirroring_primary_sink_prepare fail [%d]", ret);
-               return SCMIRRORING_ERROR_INVALID_OPERATION;
-       }
        return ret;
 }
 #endif
index f0f31dfe8eb8f3be77ff3159601514211670a06f..de81852537771761c86d9cc4774539134278d184 100755 (executable)
@@ -57,6 +57,7 @@ gboolean __scmirroring_secondary_sink_start(gpointer data);
 static void __quit_program(void);
 gboolean __timeout_menu_display(void *data);
 
+int _scmirroring_secondary_sink_create(void);
 
 
 static int app_create(void *data)
@@ -76,7 +77,7 @@ static int app_terminate(void *data)
 
 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);
+       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);
@@ -98,9 +99,10 @@ static void scmirroring_sink_state_callback(scmirroring_error_e error_code, scmi
                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();
+//             if (scmirroring_secondary_sink_destroy(g_scmirroring) != SCMIRRORING_ERROR_NONE)
+//                     g_print("scmirroring_secondary_sink_destroy fail\n");
+//             __quit_program();
+//             g_scmirroring = 0;
        } else
                g_print(" state[%d] Invalid State", state);
 
@@ -123,7 +125,8 @@ static void __displaymenu(void)
        g_print("=====================================================================\n");
        g_print("               SCMIRRORING Secondary Sink Testsuite(press q to quit) \n");
        g_print("=====================================================================\n");
-       g_print("m : Make mirroring s-sink handle(create handle)\n");
+       g_print("m : Make mirroring s-sink handle(create handle and do prepare)\n");
+       g_print("p : prepare\n");
        g_print("a : a ip port(ex. a 192.168.49.1 2022)\n");
        g_print("c : Connect\n");
        g_print("s : start\n");
@@ -196,17 +199,19 @@ static void __interpret(char *cmd)
        } else if (strncmp(cmd, "a", 1) == 0) {
                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, "p", 1) == 0) {
+               ret = scmirroring_secondary_sink_prepare(g_scmirroring);
        } else if (strncmp(cmd, "s", 1) == 0) {
                g_print("Start\n");
                ret = __scmirroring_secondary_sink_start(NULL);
-       }else if (strncmp(cmd, "d", 1) == 0) {
+       } else if (strncmp(cmd, "d", 1) == 0) {
                g_print("Disconnect\n");
                ret = scmirroring_secondary_sink_disconnect(g_scmirroring);
        } else if (strncmp(cmd, "u", 1) == 0) {
                g_print("Destroy\n");
                ret = scmirroring_secondary_sink_unprepare(g_scmirroring);
        } else if (strncmp(cmd, "t", 1) == 0) {
-               g_print("Destroy\n");
+               g_print("Unprepare\n");
                ret = scmirroring_secondary_sink_destroy(g_scmirroring);
        } else if (strncmp(cmd, "q", 1) == 0) {
                __quit_program();
index c936dde5b77afaa52cf962cb76c266469e6e81fc..aafae0179304ff0e5c19ef576a50114e70f39e2c 100644 (file)
@@ -1066,10 +1066,6 @@ static int __scmirroring_sink_create(gpointer data)
                g_print("scmirroring_sink_create fail [%d]", ret);
                return SCMIRRORING_ERROR_INVALID_OPERATION;
        }
-
-       char address[50]={0};
-       strncpy(address,"00:00:00:00:00",50);
-       ret=scmirroring_sink_set_coupled_sink(g_scmirroring,0,address);
        if (g_sinktype != -1) {
                if (g_sinktype == SCMIRRORING_DISPLAY_TYPE_OVERLAY) {
                        evas_object_show(g_evas);