From: Hyunsoo Park Date: Fri, 3 May 2019 05:31:13 +0000 (+0900) Subject: Initial draft of R2 feature 'Secondary Sink'. X-Git-Tag: submit/tizen/20190507.101459^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F08%2F205408%2F1;p=platform%2Fcore%2Fapi%2Fscreen-mirroring.git Initial draft of R2 feature 'Secondary Sink'. 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 --- diff --git a/include/scmirroring_internal.h b/include/scmirroring_internal.h index b4763e9..8af1812 100644 --- a/include/scmirroring_internal.h +++ b/include/scmirroring_internal.h @@ -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; diff --git a/include/scmirroring_primary_sink.h b/include/scmirroring_primary_sink.h index 242f6cb..529c1e2 100644 --- a/include/scmirroring_primary_sink.h +++ b/include/scmirroring_primary_sink.h @@ -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. diff --git a/include/scmirroring_private.h b/include/scmirroring_private.h index 7f78fb0..93d6239 100644 --- a/include/scmirroring_private.h +++ b/include/scmirroring_private.h @@ -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; diff --git a/include/scmirroring_src.h b/include/scmirroring_src.h index fa1dc04..1f15a4d 100644 --- a/include/scmirroring_src.h +++ b/include/scmirroring_src.h @@ -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. diff --git a/include/scmirroring_src_ini.h b/include/scmirroring_src_ini.h index 56893a5..ae6b42f 100644 --- a/include/scmirroring_src_ini.h +++ b/include/scmirroring_src_ini.h @@ -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); diff --git a/include/scmirroring_type.h b/include/scmirroring_type.h index 73d3e6f..1943ffb 100644 --- a/include/scmirroring_type.h +++ b/include/scmirroring_type.h @@ -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 diff --git a/miracast_server/miracast_server.h b/miracast_server/miracast_server.h index 4a7b4f6..b91c4c9 100644 --- a/miracast_server/miracast_server.h +++ b/miracast_server/miracast_server.h @@ -50,6 +50,7 @@ struct _MiracastServer { gint resolution; gint connection_mode; gint multisink; + gint coupling_mode; gpointer _gst_reserved[GST_PADDING]; }; diff --git a/miracast_server/miracast_server_impl.c b/miracast_server/miracast_server_impl.c index f64077b..82a0a2e 100644 --- a/miracast_server/miracast_server_impl.c +++ b/miracast_server/miracast_server_impl.c @@ -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"); diff --git a/src/scmirroring_primary_sink.c b/src/scmirroring_primary_sink.c index f274fd2..eaa4beb 100644 --- a/src/scmirroring_primary_sink.c +++ b/src/scmirroring_primary_sink.c @@ -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(); diff --git a/src/scmirroring_secondary_sink.c b/src/scmirroring_secondary_sink.c index 6facf98..ef309f4 100755 --- a/src/scmirroring_secondary_sink.c +++ b/src/scmirroring_secondary_sink.c @@ -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(); diff --git a/src/scmirroring_sink.c b/src/scmirroring_sink.c index 0faac23..74fbc25 100644 --- a/src/scmirroring_sink.c +++ b/src/scmirroring_sink.c @@ -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"; } diff --git a/src/scmirroring_src.c b/src/scmirroring_src.c index 2d9ef9b..ddb0cdf 100644 --- a/src/scmirroring_src.c +++ b/src/scmirroring_src.c @@ -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); diff --git a/src/scmirroring_src_ini.c b/src/scmirroring_src_ini.c index 3cdf995..db79b28 100644 --- a/src/scmirroring_src_ini.c +++ b/src/scmirroring_src_ini.c @@ -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"); diff --git a/test/scmirroring_test.c b/test/scmirroring_test.c index 84ccec9..615aaf9 100644 --- a/test/scmirroring_test.c +++ b/test/scmirroring_test.c @@ -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); diff --git a/test_sink/scmirroring_primary_sink_test.c b/test_sink/scmirroring_primary_sink_test.c index 6ca83af..974226f 100644 --- a/test_sink/scmirroring_primary_sink_test.c +++ b/test_sink/scmirroring_primary_sink_test.c @@ -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 diff --git a/test_sink/scmirroring_secondary_sink_test.c b/test_sink/scmirroring_secondary_sink_test.c index f0f31df..de81852 100755 --- a/test_sink/scmirroring_secondary_sink_test.c +++ b/test_sink/scmirroring_secondary_sink_test.c @@ -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(); diff --git a/test_sink/scmirroring_sink_test.c b/test_sink/scmirroring_sink_test.c index c936dde..aafae01 100644 --- a/test_sink/scmirroring_sink_test.c +++ b/test_sink/scmirroring_sink_test.c @@ -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);