Fix bugs and improvements 06/40806/1 accepted/tizen_3.0.2015.q2_common tizen_3.0.2015.q2_common accepted/tizen/3.0.2015.q2/common/20150615.091815 accepted/tizen/common/20150609.171331 accepted/tizen/mobile/20150610.001441 accepted/tizen/tv/20150610.001428 accepted/tizen/wearable/20150610.001457 submit/tizen/20150609.083647 submit/tizen_3.0.2015.q2_common/20150615.075539
authorHyunjun <zzoon.ko@samsung.com>
Tue, 9 Jun 2015 08:11:42 +0000 (17:11 +0900)
committerHyunjun <zzoon.ko@samsung.com>
Tue, 9 Jun 2015 08:11:42 +0000 (17:11 +0900)
Change-Id: I4b8b42f38eb44ef4e741318319a8f451e9d22331

17 files changed:
AUTHORS [changed mode: 0755->0644]
CMakeLists.txt [changed mode: 0755->0644]
LICENSE.APLv2.0 [changed mode: 0755->0644]
NOTICE [changed mode: 0755->0644]
capi-media-screen-mirroring.manifest [changed mode: 0755->0644]
capi-media-screen-mirroring.pc.in [changed mode: 0755->0644]
doc/images/capi_media_screen_mirroring_sink_state_diagram.png [new file with mode: 0644]
doc/screen_mirroring_doc.h [changed mode: 0755->0644]
include/scmirroring_private.h
include/scmirroring_sink.h
include/scmirroring_src.h
miracast_server/miracast_server.c
org.tizen.scmirroring.server.service
packaging/capi-media-screen-mirroring.spec
src/scmirroring_src.c
test/scmirroring_test.c
test/scmirroring_wifi_direct_test.c

diff --git a/AUTHORS b/AUTHORS
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/NOTICE b/NOTICE
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index ca37499..7376f27
@@ -1,6 +1,33 @@
 <manifest>
+       <define>
+               <domain name="miracast-server" policy="restricted" />
+               <request>
+                       <smack request="system::use_internet" type="rwxat"/>
+                       <smack request="device::app_logging" type="w"/>
+                       <smack request="device::sys_logging" type="w"/>
+                       <smack request="security-server::api-privilege-by-pid" type="w"/>
+                       <smack request="dbus" type="rwxat"/>
+                       <smack request="xorg" type="rwx"/>
+                       <smack request="system::share" type="rwxat"/>
+                       <smack request="pulseaudio" type="rwxat"/>
+                       <smack request="pulseaudio::record" type="rwxat"/>
+                       <smack request="device::hwcodec" type="rw"/>
+                       <smack request="drmfw" type="rw"/>
+                       <smack request="wifi-direct" type="rwx"/>
+                       <smack request="wifi-direct::admin" type="rwx"/>
+                       <smack request="wifi-direct::discover" type="rwx"/>
+                       <smack request="wifi-direct::info" type="rwx"/>
+                       <smack request="wifi-direct::native" type="rwx"/>
+               </request>
+               <permit>
+                       <smack permit="dbus" type="rwxat"/>
+                       <smack permit="system::use_internet" type="rwxat"/>
+               </permit>
+       </define>
        <request>
                <domain name="_" />
        </request>
+       <assign>
+               <filesystem path="/usr/bin/miracast_server" label="miracast-server" exec_label="miracast-server" />
+       </assign>
 </manifest>
-
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/doc/images/capi_media_screen_mirroring_sink_state_diagram.png b/doc/images/capi_media_screen_mirroring_sink_state_diagram.png
new file mode 100644 (file)
index 0000000..a5bcc18
Binary files /dev/null and b/doc/images/capi_media_screen_mirroring_sink_state_diagram.png differ
old mode 100755 (executable)
new mode 100644 (file)
index df322aa..916b047
 /**
  * @ingroup CAPI_MEDIA_FRAMEWORK
  * @defgroup CAPI_MEDIA_SCREEN_MIRRORING_MODULE Screen Mirroring
+ * @brief The @ref CAPI_MEDIA_SCREEN_MIRRORING_MODULE API provides functions for screen mirroring as sink.
+ * @section CAPI_MEDIA_SCREEN_MIRRORING_MODULE_HEADER Required Header
+ *    \#include <scmirroring_type.h>
+ *    \#include <scmirroring_sink.h>
+ * @section CAPI_MEDIA_SCREEN_MIRRORING_OVERVIEW Overview
+ * The @ref CAPI_MEDIA_SCREEN_MIRRORING_MODULE API allows you to implement screen mirroring application as sink.
  *
- * @brief The @ref CAPI_MEDIA_SCREEN_MIRRORING_MODULE API provides functions for screen mirroring as source or sink.
+ */
+
+/*
+ * @ingroup CAPI_MEDIA_SCREEN_MIRRORING_MODULE
+ * @defgroup CAPI_MEDIA_SCREEN_MIRRORING_SINK_MODULE Screen Mirroring sink
+ * @brief The @ref CAPI_MEDIA_SCREEN_MIRRORING_SINK_MODULE API provides functions for screen mirroring as sink.
  *
- * @section CAPI_MEDIA_SCREEN_MIRRORING_MODULE_HEADER Required Header
- *    \#include <scmirroring_src.h>
+ * @section CAPI_MEDIA_SCREEN_MIRRORING_SINK_MODULE_HEADER Required Header
  *    \#include <scmirroring_sink.h>
  *
- * @section CAPI_MEDIA_SCREEN_MIRRORING_OVERVIEW Overview
- * The @ref CAPI_MEDIA_SCREEN_MIRRORING_MODULE API allows you to implement screen mirroring application as source or sink.
+ * @section CAPI_MEDIA_SCREEN_MIRRORING_SINK_OVERVIEW Overview
+ * The @ref CAPI_MEDIA_SCREEN_MIRRORING_SINK_MODULE API allows you to implement screen mirroring application as sink.
+ * It gives the ability to connect to the screen mirroring source, start / disconnect / pause / resume screen mirroring sink, set resolution and display, register state change callback function.
+ *
+ * @subsection CAPI_MEDIA_SCREEN_MIRRORING_SINK_LIFE_CYCLE_STATE_DIAGRAM State Diagram
+ * The following diagram shows the life cycle and states of the screen mirroring sink.
+ * @image html capi_media_screen_mirroring_sink_state_diagram.png
+ *
+ *
+ * @subsection CAPI_MEDIA_SCREEN_MIRRORING_SINK_LIFE_CYCLE_STATE_TRANSITIONS State Transitions
+ * <div><table class="doxtable" >
+ *        <tr>
+ *              <th><b>FUNCTION</b></th>
+ *        <th><b>PRE-STATE</b></th>
+ *               <th><b>POST-STATE</b></th>
+ *               <th><b>SYNC TYPE</b></th>
+ *       </tr>
+ *       <tr>
+ *             <td>scmirroring_sink_create()</td>
+ *               <td>NONE</td>
+ *              <td>NULL</td>
+ *             <td>SYNC</td>
+ *     </tr>
+ *        <tr>
+ *               <td>scmirroring_sink_destroy()</td>
+ *               <td>NULL</td>
+ *               <td>NONE</td>
+ *               <td>SYNC</td>
+ *        </tr>
+ *        <tr>
+ *              <td>scmirroring_sink_prepare()</td>
+ *             <td>NULL</td>
+ *        <td>PREPARED</td>
+ *        <td>SYNC</td>
+ *        </tr>
+ *        <tr>
+ *              <td>scmirroring_sink_unprepare()</td>
+ *               <td>PREARED, DISCONNECTED</td>
+ *              <td>NULL</td>
+ *              <td>SYNC</td>
+ *       </tr>
+ *       <tr>
+ *             <td>scmirroring_sink_connect()</td>
+ *              <td>PREARED</td>
+ *             <td>CONNECTED</td>
+ *        <td>ASYNC</td>
+ *        </tr>
+ *        <tr>
+ *              <td>scmirroring_sink_start()</td>
+ *               <td>CONNECTED</td>
+ *             <td>PLAYING</td>
+ *               <td>ASYNC</td>
+ *       </tr>
+ *       <tr>
+ *             <td>scmirroring_sink_disconnect()</td>
+ *             <td>CONNECTED, PAUSED or PLAYING </td>
+ *               <td>DISCONNECTED </td>
+ *               <td>SYNC</td>
+ *       </tr>
+ *       <tr>
+ *             <td>scmirroring_sink_pause()</td>
+ *              <td>PLAYING</td>
+ *        <td>PAUSED</td>
+ *             <td>ASYNC</td>
+ *     </tr>
+ *       <tr>
+ *             <td>scmirroring_sink_resume()</td>
+ *              <td>PAUSED</td>
+ *        <td>PLAYING</td>
+ *             <td>ASYNC</td>
+ *     </tr>
+ * </table></div>
+ *
+ *
+ *@subsection CAPI_MEDIA_SCREEN_MIRRORING_SINK_LIFE_CYCLE_STATE_DEPENDENT_FUNCTIONS State Dependent Function Calls
+ * The following table shows state-dependent function calls.
+ * It is forbidden to call the functions listed below in wrong state.
+ * Violation of this rule may result in unpredictable behavior.
+ * <div><table class="doxtable" >
+ * <tr>
+ *    <th><b>FUNCTION</b></th>
+ *    <th><b>VALID STATES</b></th>
+ *    <th><b>DESCRIPTION</b></th>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_create() </td>
+ *    <td>NONE</td>
+ *    <td>-</td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_destroy()</td>
+ *    <td>NULL</td>
+ *    <td></td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_set_state_changed_cb()</td>
+ *    <td>NULL/ PREPARED/ CONNECTED/ PLAYING/ PAUSED/ DISCONNECTED</td>
+ *    <td>This function must be called after scmirroring_sink_create().</td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_unset_state_changed_cb()</td>
+ *    <td>NULL/ PREPARED/ CONNECTED/ PLAYING/ PAUSED/ DISCONNECTED</td>
+ *    <td>This function must be called after register callback function.</td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_set_display()</td>
+ *    <td>NULL</td>
+ *    <td>This function must be called before scmirroring_sink_prepare().</td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_set_resolution()</td>
+ *    <td>NULL</td>
+ *    <td></td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_prepare() </td>
+ *    <td>NULL</td>
+ *    <td>This function must be called after scmirroring_sink_create().</td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_unprepare() </td>
+ *    <td>PREPARED/ DISCONNECTED </td>
+ *    <td></td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_set_ip_and_port() </td>
+ *    <td>NULL/ PREPARED</td>
+ *    <td>This function must be called before scmirroring_sink_connect().</td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_connect()</td>
+ *    <td>PREPARED</td>
+ *    <td>This function must be called after scmirroring_sink_prepare().</td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_pause()</td>
+ *    <td>PLAYING</td>
+ *    <td>This function must be called after scmirroring_sink_start().</td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_resume()</td>
+ *    <td>PAUSED</td>
+ *    <td>This function must be called after scmirroring_sink_pause().</td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_start()</td>
+ *    <td>CONNECTED</td>
+ *    <td>This function must be called after scmirroring_sink_connect().</td>
+ * </tr>
+ * <tr>
+ *    <td>scmirroring_sink_disconnect() </td>
+ *    <td>CONNECTED/ PLAYING/ PAUSED</td>
+ *    <td></td>
+ * </tr>
+ * </table></div>
+ *
+ * @subsection CAPI_MEDIA_SCREEN_MIRRORING_SINK_LIFE_CYCLE_ASYNCHRONOUS_OPERATIONS Asynchronous Operations
+ * All functions that change the state are synchronous except scmirroring_sink_connect(), scmirroring_sink_start(), scmirroring_sink_pause(), and scmirroring_sink_resume().
+ * Thus the result is passed to the application via the callback mechanism.
+ *
+ * @subsection CAPI_MEDIA_SCREEN_MIRRORING_SINK_LIFE_CYCLE_CALLBACK_OPERATIONS Callback(Event) Operations
+ * <div><table class="doxtable" >
+ *     <tr>
+ *        <th><b>REGISTER</b></th>
+ *        <th><b>UNREGISTER</b></th>
+ *        <th><b>CALLBACK</b></th>
+ *        <th><b>DESCRIPTION</b></th>
+ *     </tr>
+ *              <tr>
+ *        <td>scmirroring_sink_set_state_changed_cb()</td>
+ *        <td>scmirroring_sink_unset_state_changed_cb()</td>
+ *        <td>scmirroring_state_cb()</td>
+ *        <td>This callback is called for state and error of screen mirroring.</td>
+ *     </tr>
+ *</table></div>
  */
 
+
 #endif /* __TIZEN_SCREEN_MIRRORING_DOC_H__ */
index 90b2cc19248f17c0fe19aaebdbac3835acc19be6..824238d090ddb4c4c2d11445a924215873a5e08e 100755 (executable)
@@ -115,6 +115,7 @@ typedef struct
        GIOChannel *channel;
        char *sock_path;
        int connect_mode;
+       int current_state;
        scmirroring_state_cb_s *scmirroring_state_cb;
 } scmirroring_src_s;
 
index e3aa2a9da6b44a3f5582b6943645d0959836ab38..38d7f30ff35c7dbb45df41f0ca0517c99441b170 100755 (executable)
@@ -29,7 +29,7 @@ extern "C" {
  */
 
 /**
- * @addtogroup CAPI_MEDIA_SCREEN_MIRRORING_MODULE
+ * @addtogroup CAPI_MEDIA_SCREEN_MIRRORING_SINK_MODULE
  * @{
  */
 
index 1ca21e41733c49b01bfb65855fcdb72906758e73..4e2fea6fc282fac252dc23485a21ae02a0388517 100755 (executable)
@@ -29,7 +29,7 @@ extern "C" {
  */
 
 /**
- * @addtogroup CAPI_MEDIA_SCREEN_MIRRORING_MODULE
+ * @addtogroup CAPI_MEDIA_SCREEN_MIRRORING_SRC_MODULE
  * @{
  */
 
@@ -377,7 +377,7 @@ int scmirroring_src_disconnect(scmirroring_src_h scmirroring_src);
  * @see scmirroring_src_create()
  * @see scmirroring_src_set_state_changed_cb()
  */
-int scmirroring_src_unset_state_cb(scmirroring_src_h scmirroring_src);
+int scmirroring_src_unset_state_changed_cb(scmirroring_src_h scmirroring_src);
 
 /**
  * @brief Destroys server and screen mirroring source handle.
index 7d68455674c099abd969e47a594d99ab03c9ae2f..fa7e8a823217a43d4206bb23fc39da2892235de5 100755 (executable)
@@ -24,6 +24,7 @@
 #include <unistd.h>
 #include <sys/un.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
 #include <gio/gio.h>
 
 #include <gst/rtsp-server/rtsp-server-wfd.h>
 #define MAX_MSG_LEN 128
 #define MEDIA_IPC_PATH "/tmp/.miracast_ipc_rtspserver"
 
+#define PROC_DBUS_OBJECT "/org/tizen/scmirroring/server"
+#define PROC_DBUS_INTERFACE "org.tizen.scmirroring.server"
+#define PROC_DBUS_STATUS_CHANGE_SIGNAL "miracast_wfd_source_status_changed"
+
+#define MIRACAST_WFD_SOURCE_ON 1
+#define MIRACAST_WFD_SOURCE_OFF 0
+
 GMainLoop *g_mainloop = NULL;
 GObject *g_server_object = NULL;
+static gint g_server_status = MIRACAST_WFD_SOURCE_OFF;
 
+static int __miracast_server_emit_status_signal(int status);
 static const GDBusMethodInfo scmirroring_server_method_info_method =
 {
        -1,
@@ -53,7 +63,7 @@ static const GDBusMethodInfo * const scmirroring_server_method_info_pointers[] =
 static const GDBusInterfaceInfo scmirroring_server_interface_info =
 {
        -1,
-       "org.tizen.scmirroring.server",
+       PROC_DBUS_INTERFACE,
        (GDBusMethodInfo **) &scmirroring_server_method_info_pointers,
        (GDBusSignalInfo **) NULL,
        (GDBusPropertyInfo **) NULL,
@@ -65,9 +75,12 @@ static GDBusNodeInfo *introspection_data = NULL;
 /* Introspection data for the service we are exporting */
 static const gchar introspection_xml[] =
   "<node>"
-  "  <interface name='org.tizen.scmirroring.server'>"
+  "  <interface name='"PROC_DBUS_INTERFACE"'>"
   "    <method name='launch_method'>"
   "    </method>"
+  "    <method name='get_miracast_wfd_source_status'>"
+  "      <arg type='i' name='status' direction='out'/>"
+  "    </method>"
   "  </interface>"
   "</node>";
 
@@ -82,11 +95,19 @@ handle_method_call (GDBusConnection       *connection,
                     GDBusMethodInvocation *invocation,
                     gpointer               user_data)
 {
+       scmirroring_debug("handle_method_call is called\n");
+
+       if(method_name != NULL)
+               scmirroring_debug("method_name is %s\n", method_name);
+
        if (g_strcmp0 (method_name, "launch_method") == 0)
        {
-               scmirroring_debug("handle_method_call is called\n");
                g_dbus_method_invocation_return_value (invocation, NULL);
        }
+       else if(g_strcmp0 (method_name, "get_miracast_wfd_source_status") == 0)
+       {
+               g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", g_server_status));
+       }
 }
 
 
@@ -107,7 +128,7 @@ on_bus_acquired (GDBusConnection *connection,
 
        scmirroring_debug ("on_bus_acquired called\n");
        registration_id = g_dbus_connection_register_object (connection,
-                                                       "/org/tizen/scmirroring/server",
+                                                       PROC_DBUS_OBJECT,
                                                        introspection_data->interfaces[0],
                                                        &interface_vtable,
                                                        NULL,
@@ -170,6 +191,7 @@ static void miracast_server_object_init(MiracastServerObject * obj)
        obj->server = NULL;
        obj->client = NULL;
        obj->factory = NULL;
+       obj->resolution = -1;
 }
 
 static void miracast_server_object_class_init(MiracastServerObjectClass * klass)
@@ -195,8 +217,9 @@ int __miracast_server_send_resp(MiracastServerObject *server, char *cmd)
        }
 
        _cmd = g_strdup(cmd);
+       _cmd[strlen(_cmd)] = '\0';
 
-       if (write(client_sock, _cmd, strlen(_cmd)) != strlen(_cmd)) {
+       if (write(client_sock, _cmd, strlen(_cmd) + 1) != strlen(_cmd) + 1) {
                scmirroring_error("sendto failed [%s]", strerror(errno));
                ret = SCMIRRORING_ERROR_INVALID_OPERATION;
        } else {
@@ -213,12 +236,19 @@ static void __miracast_server_quit_program(MiracastServerObject * server)
 
        void *pool;
        int i;
+       int ret = 0;
 
        if (server->server == NULL) {
                scmirroring_error ("server is already NULL");
                goto done;
        }
 
+       ret = __miracast_server_emit_status_signal(MIRACAST_WFD_SOURCE_OFF);
+       if(ret != SCMIRRORING_ERROR_NONE )
+       {
+               scmirroring_error("Failed to emit miracast server off signal");
+       }
+
        pool = (void*)gst_rtsp_server_get_session_pool (server->server);
        gst_rtsp_session_pool_cleanup (pool);
        g_object_unref (pool);
@@ -237,6 +267,22 @@ done:
 static void __miracast_server_signal_handler(int signo)
 {
        scmirroring_error("__miracast_server_signal_handler call quit_program() %d", signo);
+       int ret = 0;
+
+       switch(signo)
+       {
+               case SIGINT:
+               case SIGQUIT:
+               case SIGTERM:
+                       ret = __miracast_server_emit_status_signal(MIRACAST_WFD_SOURCE_OFF);
+                       if(ret != SCMIRRORING_ERROR_NONE )
+                       {
+                               scmirroring_error("Failed to emit miracast server off signal");
+                       }
+                       break;
+               default:
+                       break;
+       }
        exit(1);
 }
 
@@ -307,7 +353,7 @@ static bool __miracast_server_setup()
        object = g_object_new (MIRACAST_SERVER_TYPE_OBJECT, NULL);
 
        g_bus_own_name (G_BUS_TYPE_SYSTEM,
-                           "org.tizen.scmirroring.server",
+                           PROC_DBUS_INTERFACE,
                            G_BUS_NAME_OWNER_FLAGS_NONE,
                            on_bus_acquired,
                            on_name_acquired,
@@ -366,6 +412,12 @@ static gboolean __miracast_server_ready_channel(int *sockfd)
                return FALSE;
        }
 
+       /*change permission of sock file*/
+       if (chmod(MEDIA_IPC_PATH, 0770) < 0)
+               scmirroring_error ("chmod failed [%s]", strerror(errno));
+       if (chown(MEDIA_IPC_PATH, 200, 5000) < 0)
+               scmirroring_error ("chown failed [%s]", strerror(errno));
+
        scmirroring_debug("Listening...");
        *sockfd = sock;
 
@@ -465,14 +517,58 @@ ERROR:
 
 #define TEST_MOUNT_POINT  "/wfd1.0/streamid=0"
 
+static void
+__client_closed (GstRTSPClient * client)
+{
+       if (client == NULL) return;
+
+       scmirroring_debug ("client %p: connection closed", client);
+
+       return;
+}
+
+static void
+__new_session (GstRTSPClient * client, GstRTSPSession *session)
+{
+       if (client == NULL) return;
+
+       scmirroring_debug ("New session(%p) is made for client %p", session, client);
+
+       return;
+}
+
+static void
+__teardown_req (GstRTSPClient * client, GstRTSPContext *ctx)
+{
+       if (client == NULL) return;
+
+       scmirroring_debug ("Got TEARDOWN request for client %p", client);
+
+       return;
+}
+
 static void 
 __miracast_server_client_connected_cb (GstRTSPServer * server,
     GstRTSPClient * client, gpointer user_data)
 {
        MiracastServerObject *server_obj = (MiracastServerObject *)user_data;
+       int ret = SCMIRRORING_ERROR_NONE;
 
        scmirroring_debug("There is a client, connected");
        server_obj->client = (void *)client;
+
+       ret = __miracast_server_emit_status_signal(MIRACAST_WFD_SOURCE_ON);
+       if(ret != SCMIRRORING_ERROR_NONE )
+       {
+               scmirroring_error("Failed to emit miracast server on signal");
+       }
+
+       g_signal_connect(G_OBJECT(client), "teardown-request", G_CALLBACK(__teardown_req), NULL);
+       g_signal_connect(G_OBJECT(client), "closed", G_CALLBACK(__client_closed), NULL);
+       g_signal_connect(G_OBJECT(client), "new-session", G_CALLBACK(__new_session), NULL);
+
+       /* Sending connected response to client */
+       __miracast_server_send_resp(server_obj, "OK:CONNECTED");
 }
 
 int __miracast_server_start(MiracastServerObject * server_obj)
@@ -516,14 +612,37 @@ int __miracast_server_start(MiracastServerObject * server_obj)
                        scmirroring_src_ini_get_structure()->mtu_size
                        );
 
-       gst_rtsp_wfd_server_set_supported_reso(server,
+
+       if (server_obj->resolution == SCMIRRORING_RESOLUTION_1920x1080_P30) {
+               gst_rtsp_wfd_server_set_video_native_reso(server, GST_WFD_VIDEO_CEA_RESOLUTION);
+               gst_rtsp_wfd_server_set_supported_reso(server, GST_WFD_CEA_1920x1080P30);
+       } else if (server_obj->resolution == SCMIRRORING_RESOLUTION_1280x720_P30) {
+               gst_rtsp_wfd_server_set_video_native_reso(server, GST_WFD_VIDEO_CEA_RESOLUTION);
+               gst_rtsp_wfd_server_set_supported_reso(server, GST_WFD_CEA_1280x720P30);
+       } else if (server_obj->resolution == SCMIRRORING_RESOLUTION_960x540_P30) {
+               gst_rtsp_wfd_server_set_video_native_reso(server, GST_WFD_VIDEO_HH_RESOLUTION);
+               gst_rtsp_wfd_server_set_supported_reso(server, GST_WFD_HH_960x540P30);
+       } else if (server_obj->resolution == SCMIRRORING_RESOLUTION_864x480_P30) {
+               gst_rtsp_wfd_server_set_video_native_reso(server, GST_WFD_VIDEO_HH_RESOLUTION);
+               gst_rtsp_wfd_server_set_supported_reso(server, GST_WFD_HH_864x480P30);
+       } else if (server_obj->resolution == SCMIRRORING_RESOLUTION_720x480_P60) {
+               gst_rtsp_wfd_server_set_video_native_reso(server, GST_WFD_VIDEO_CEA_RESOLUTION);
+               gst_rtsp_wfd_server_set_supported_reso(server, GST_WFD_CEA_720x480P60);
+       } else if (server_obj->resolution == SCMIRRORING_RESOLUTION_640x480_P60) {
+               gst_rtsp_wfd_server_set_video_native_reso(server, GST_WFD_VIDEO_CEA_RESOLUTION);
+               gst_rtsp_wfd_server_set_supported_reso(server, GST_WFD_CEA_640x480P60);
+       } else if (server_obj->resolution == SCMIRRORING_RESOLUTION_640x360_P30) {
+               gst_rtsp_wfd_server_set_video_native_reso(server, GST_WFD_VIDEO_HH_RESOLUTION);
+               gst_rtsp_wfd_server_set_supported_reso(server, GST_WFD_HH_640x360P30);
+       } else {
+               gst_rtsp_wfd_server_set_video_native_reso(server, GST_WFD_VIDEO_CEA_RESOLUTION);
+               gst_rtsp_wfd_server_set_supported_reso(server,
                        scmirroring_src_ini_get_structure()->video_reso_supported);
+       }
 
        gst_rtsp_media_factory_wfd_set_dump_ts (factory,
                        scmirroring_src_ini_get_structure()->dump_ts);
 
-       gst_rtsp_media_factory_set_launch (GST_RTSP_MEDIA_FACTORY(factory),
-                       "( " VIDEO_PIPELINE " )");
        g_object_ref (factory);
        gst_rtsp_mount_points_add_factory (mounts, TEST_MOUNT_POINT, GST_RTSP_MEDIA_FACTORY(factory));
        g_object_unref (mounts);
@@ -554,9 +673,9 @@ void __miracast_server_interpret(MiracastServerObject * server, char *buf)
        if (g_strrstr(buf, SCMIRRORING_STATE_CMD_START)) {
                ret = __miracast_server_start(server);
                if (ret == SCMIRRORING_ERROR_NONE) {
-                       __miracast_server_send_resp(server, "OK:CONNECTED");
+                       __miracast_server_send_resp(server, "OK:LISTENING");
                } else {
-                       __miracast_server_send_resp(server, "FAIL:CONNECTED");
+                       __miracast_server_send_resp(server, "FAIL:LISTENING");
                }
        } else if (g_strrstr(buf, "SET IP")) {
                gchar **addr_info;
@@ -594,7 +713,7 @@ void __miracast_server_interpret(MiracastServerObject * server, char *buf)
                resolution_info = g_strsplit(buf, " ", 0);
 
                resolution = atoi(resolution_info[2]);
-               scmirroring_debug("Connection mode %d", resolution);
+               scmirroring_debug("Resolution %d", resolution);
 
                server->resolution = resolution;
 
@@ -649,10 +768,27 @@ gboolean __miracast_server_client_read_cb(GIOChannel *src,
                if (read == 0) {
                        scmirroring_error("Read 0 bytes");
                        return FALSE;
+               } else {
+                       scmirroring_debug("Read %d bytes", read);
+               }
+
+               int i = 0;
+               int idx = 0;
+
+               /* Handling multiple commands like "CMD1\0CMD2\0CMD3\0" */
+               for (i = 0; i < read; i++) {
+                       gchar *str = NULL;
+                       if (buf[i] == '\0') {
+                               str = buf + idx;
+                               idx = i + 1;
+                       } else {
+                               continue;
+                       }
+                       scmirroring_debug("Handling %s", str);
+                       __miracast_server_interpret (server, str);
+                       if (idx >= read) break;
                }
-               buf[read] = '\0';
-               g_strstrip(buf);
-               __miracast_server_interpret (server, buf);
+
        } else if (condition & G_IO_ERR) {
                scmirroring_error("got G_IO_ERR");
                return FALSE;
@@ -698,6 +834,7 @@ gboolean __miracast_server_read_cb(GIOChannel *src,
        /* To avoid blocking in g_io_channel_read_chars */
        g_io_channel_set_encoding(channel, NULL, NULL);
        g_io_channel_set_buffered(channel, FALSE);
+       g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
 
        server->client_channel = channel;
 
@@ -708,6 +845,58 @@ gboolean __miracast_server_read_cb(GIOChannel *src,
        return TRUE;
 }
 
+
+static int __miracast_server_emit_status_signal(int status)
+{
+       GError *err = NULL;
+       GDBusConnection *conn = NULL;
+       gboolean ret;
+
+       if (status != MIRACAST_WFD_SOURCE_ON && status != MIRACAST_WFD_SOURCE_OFF) {
+               scmirroring_error ("invalid arguments [%d]", status);
+               return -1;
+       }
+
+       if (g_server_status == status) {
+               scmirroring_debug ("The server status is not changed, status [%d] ", status);
+               return 0;
+       }
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+       if (!conn && err) {
+               scmirroring_error("g_bus_get_sync() error (%s) ", err->message);
+               g_error_free (err);
+               return -1;
+       }
+
+       ret = g_dbus_connection_emit_signal (conn,
+               NULL, PROC_DBUS_OBJECT, PROC_DBUS_INTERFACE, PROC_DBUS_STATUS_CHANGE_SIGNAL,
+               g_variant_new ("(i)", status), &err);
+       if (!ret && err) {
+               scmirroring_error("g_dbus_connection_emit_signal() error (%s) ", err->message);
+               goto error;
+       }
+
+       ret = g_dbus_connection_flush_sync(conn, NULL, &err);
+       if (!ret && err) {
+               scmirroring_error("g_dbus_connection_flush_sync() error (%s) ", err->message);
+               goto error;
+       }
+
+       g_object_unref(conn);
+       scmirroring_debug ("sending miracast server status [%s] success",
+               (status == MIRACAST_WFD_SOURCE_ON) ? "On" : "Off");
+
+       g_server_status = status;
+
+       return 0;
+
+error:
+       g_error_free (err);
+       g_object_unref(conn);
+       return -1;
+}
+
 int main(int argc, char *argv[])
 {
        int sockfd = -1;
@@ -752,4 +941,3 @@ int main(int argc, char *argv[])
        scmirroring_debug("MIRACAST SERVER EXIT \n");
        exit(0);
 }
-
index 3c1c6a3fa7834905793314af3c2d508d93c8df1c..19ead856c06294dd9637afed45a0622f049b8e79 100644 (file)
@@ -1,4 +1,5 @@
 [D-BUS Service]
 Name=org.tizen.scmirroring.server
-Exec=/bin/sh -c 'export GST_DEBUG=2,*rtsp*:5;/usr/bin/miracast_server'
+Exec=/bin/sh -c 'export GST_DEBUG=2,*rtsp*:5;export DISPLAY=:0;/usr/bin/miracast_server'
 User=system
+Group=video
index b4c3e8e938e5e23b68ed529817a0ea3ad445d596..bb49f34d19ac44572db34a048b8fa505b293f93f 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       capi-media-screen-mirroring
 Summary:    A screen mirroring library in Tizen C API
-Version:    0.1.23
+Version:    0.1.30
 Release:    0
 Group:      Multimedia/API
 License:    Apache License, Version 2.0
@@ -56,8 +56,8 @@ make %{?jobs:-j%jobs}
 %install
 rm -rf %{buildroot}
 %make_install
-mkdir -p %{buildroot}/usr/share/dbus-1/services/
-install -m 755 org.tizen.scmirroring.server.service %{buildroot}/usr/share/dbus-1/services/
+mkdir -p %{buildroot}/usr/share/dbus-1/system-services/
+install -m 755 org.tizen.scmirroring.server.service %{buildroot}/usr/share/dbus-1/system-services/
 mkdir -p %{buildroot}/%{_datadir}/license
 cp -rf %{_builddir}/%{name}-%{version}/LICENSE.APLv2.0 %{buildroot}%{_datadir}/license/%{name}
 
@@ -76,7 +76,7 @@ cp -rf config/scmirroring_src.ini %{buildroot}/usr/etc/scmirroring_src.ini
 %files
 %manifest capi-media-screen-mirroring.manifest
 %{_libdir}/libcapi-media-screen-mirroring.so*
-%{_datadir}/dbus-1/services/org.tizen.scmirroring.server.service
+%{_datadir}/dbus-1/system-services/org.tizen.scmirroring.server.service
 #License
 %{_datadir}/license/%{name}
 %{_bindir}/miracast_server
index 26c99b2ef16dcdc8631a9bb8c7956f7cd22d54ef..37eb0e149966425d91e413247729f7b09b614741 100755 (executable)
@@ -18,6 +18,8 @@
 #include <sys/types.h>
 #include <sys/un.h>
 #include <sys/socket.h>
+#include <linux/socket.h>
+#include <netinet/tcp.h>
 
 #include <scmirroring_src.h>
 #include <scmirroring_private.h>
@@ -67,8 +69,9 @@ static int __scmirroring_src_send_cmd_to_server(scmirroring_src_s *scmirroring,
        scmirroring_retvm_if(cmd == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "cmd is NULL");
 
        _cmd = g_strdup(cmd);
+       _cmd[strlen(_cmd)] = '\0';
 
-       if (write(scmirroring->sock, _cmd, strlen(_cmd)) != (signed int) strlen(_cmd)) {
+       if (write(scmirroring->sock, _cmd, strlen(_cmd) + 1) != (signed int) strlen(_cmd) + 1) {
                scmirroring_error("sendto failed [%s]", strerror(errno));
                ret = SCMIRRORING_ERROR_INVALID_OPERATION;
        } else {
@@ -122,7 +125,7 @@ static int __miracast_server_launch(scmirroring_src_s *scmirroring)
                return SCMIRRORING_ERROR_INVALID_OPERATION;
        }
 
-       scmirroring_debug("scmirroring_proxy_initialize trying for connect");
+       scmirroring_debug("Miracast server is launched successfully");
 
        return ret;
 }
@@ -206,7 +209,12 @@ static void __scmirroring_src_interpret(scmirroring_src_s *scmirroring, char *bu
        src_state = __scmirroring_src_get_status(response[1]);;
        g_strfreev(response);
 
-       __scmirroring_src_set_callback_info (scmirroring, error_code, src_state);
+       if (scmirroring->current_state != src_state) {
+               scmirroring->current_state = src_state;
+               __scmirroring_src_set_callback_info (scmirroring, error_code, src_state);
+       } else {
+               scmirroring_debug("Current state is already %d", src_state);
+       }
 
        return;
 }
@@ -223,10 +231,26 @@ gboolean __scmirroring_src_read_cb(GIOChannel *src, GIOCondition condition, gpoi
                if (read == 0) {
                        scmirroring_error("Read 0 bytes");
                        return FALSE;
+               } else {
+                       scmirroring_debug("Read %d bytes", read);
+               }
+
+               int i = 0;
+               int idx = 0;
+
+               /* Handling multiple response like "CMD1\0CMD2\0CMD3\0" */
+               for (i = 0; i < read; i++) {
+                       gchar *str = NULL;
+                       if (buf[i] == '\0') {
+                               str = buf + idx;
+                               idx = i + 1;
+                       } else {
+                               continue;
+                       }
+                       scmirroring_debug("Handling %s", str);
+                       __scmirroring_src_interpret (_scmirroring, str);
+                       if (idx >= read) break;
                }
-               buf[read] = '\0';
-               g_strstrip(buf);
-               __scmirroring_src_interpret(_scmirroring, buf);
        } else if (condition & G_IO_ERR) {
                scmirroring_error("got G_IO_ERR");
                return FALSE;
@@ -305,9 +329,6 @@ int scmirroring_src_create(scmirroring_src_h *scmirroring)
 {
        int ret = SCMIRRORING_ERROR_NONE;
        scmirroring_src_s *_scmirroring = NULL;
-       int sock = -1;
-       GIOChannel *channel = NULL;
-       struct timeval tv_timeout = { TIMEOUT_SEC, 0 };
 
        scmirroring_debug_fenter();
 
@@ -322,30 +343,11 @@ int scmirroring_src_create(scmirroring_src_h *scmirroring)
        _scmirroring->use_hdcp = TRUE;
        _scmirroring->resolution = 0;
        _scmirroring->connect_mode = SCMIRRORING_CONNECTION_WIFI_DIRECT;
-
-       /*Create TCP Socket*/
-
-       if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
-               scmirroring_error("socket failed: %s", strerror(errno));
-               return SCMIRRORING_ERROR_INVALID_OPERATION;
-       }
-
-       if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
-               scmirroring_error("setsockopt failed: %s", strerror(errno));
-               close(sock);
-               return SCMIRRORING_ERROR_INVALID_OPERATION;
-       }
-
-       channel = g_io_channel_unix_new(sock);
-       if (channel == NULL) {
-               scmirroring_error("g_io_channel_unix_new failed: %s", strerror(errno));
-       }
-
-       g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
-
-       _scmirroring->sock = sock;
-       _scmirroring->channel = channel;
-       _scmirroring->sock_path = g_strdup("/tmp/.miracast_ipc_rtspserver");
+       _scmirroring->scmirroring_state_cb = NULL;
+       _scmirroring->sock = -1;
+       _scmirroring->channel = NULL;
+       _scmirroring->sock_path = NULL;
+       _scmirroring->current_state = SCMIRRORING_STATE_NONE;
 
        *scmirroring = (scmirroring_src_h)_scmirroring;
 
@@ -364,9 +366,9 @@ int scmirroring_src_set_connection_mode(scmirroring_src_h scmirroring, scmirrori
 
        scmirroring_retvm_if(_scmirroring == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "Handle is NULL");
 
-       if((connect_mode < SCMIRRORING_CONNECTION_WIFI_DIRECT) ||(connect_mode > SCMIRRORING_CONNECTION_MAX))
+       if((connect_mode < SCMIRRORING_CONNECTION_WIFI_DIRECT) ||(connect_mode >= SCMIRRORING_CONNECTION_MAX))
        {
-               scmirroring_error("INVALID Connection mode");
+               scmirroring_error("INVALID Connection mode : %d", connect_mode);
                return SCMIRRORING_ERROR_INVALID_PARAMETER;
        }
 
@@ -393,8 +395,15 @@ int scmirroring_src_set_state_changed_cb(scmirroring_src_h scmirroring, scmirror
        scmirroring_retvm_if(_scmirroring == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "Handle is NULL");
        scmirroring_retvm_if(callback == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "callback is NULL");
 
-       _scmirroring->scmirroring_state_cb = (scmirroring_state_cb_s*)calloc(1, sizeof(scmirroring_state_cb_s));
-       scmirroring_retvm_if(_scmirroring->scmirroring_state_cb == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Error Set CB");
+       if(_scmirroring->scmirroring_state_cb == NULL)
+       {
+               _scmirroring->scmirroring_state_cb = (scmirroring_state_cb_s*)calloc(1, sizeof(scmirroring_state_cb_s));
+               scmirroring_retvm_if(_scmirroring->scmirroring_state_cb == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Error Set CB");
+       }
+       else
+       {
+               memset(_scmirroring->scmirroring_state_cb, 0, sizeof(scmirroring_state_cb_s));
+       }
 
        _scmirroring->scmirroring_state_cb->user_data = user_data;
        _scmirroring->scmirroring_state_cb->state_cb = callback;
@@ -404,6 +413,29 @@ int scmirroring_src_set_state_changed_cb(scmirroring_src_h scmirroring, scmirror
        return ret;
 }
 
+int scmirroring_src_unset_state_changed_cb(scmirroring_src_h scmirroring)
+{
+       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");
+
+       if(_scmirroring->scmirroring_state_cb != NULL)
+       {
+               _scmirroring->scmirroring_state_cb->user_data = NULL;
+               _scmirroring->scmirroring_state_cb->state_cb = NULL;
+       }
+
+       SCMIRRORING_SAFE_FREE(_scmirroring->scmirroring_state_cb);
+
+       scmirroring_debug_fleave();
+
+       return ret;
+}
+
 int scmirroring_src_set_ip_and_port(scmirroring_src_h scmirroring, const char *ip, const char *port)
 {
        int ret = SCMIRRORING_ERROR_NONE;
@@ -445,9 +477,9 @@ int scmirroring_src_set_resolution(scmirroring_src_h scmirroring, scmirroring_re
 
        scmirroring_retvm_if(_scmirroring == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "Handle is NULL");
 
-       if((resolution < SCMIRRORING_RESOLUTION_1920x1080_P30) ||(resolution > SCMIRRORING_RESOLUTION_MAX))
+       if((resolution < SCMIRRORING_RESOLUTION_1920x1080_P30) ||(resolution >= SCMIRRORING_RESOLUTION_MAX))
        {
-               scmirroring_error("INVALID resolution");
+               scmirroring_error("INVALID resolution : %d", resolution);
                return SCMIRRORING_ERROR_INVALID_PARAMETER;
        }
 
@@ -468,12 +500,40 @@ int scmirroring_src_connect(scmirroring_src_h scmirroring)
        int ret = SCMIRRORING_ERROR_NONE;
        int retry = 0;
        struct sockaddr_un serv_addr;
+       int sock = -1;
+       GIOChannel *channel = NULL;
+       struct timeval tv_timeout = { TIMEOUT_SEC, 0 };
 
        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->connected == CONNECTED_TO_SERVER, SCMIRRORING_ERROR_INVALID_OPERATION,
+               "INVALID OPERATION, already connected to server.");
+
+       /*Create TCP Socket*/
+       if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
+               scmirroring_error("socket failed: %s", strerror(errno));
+               return SCMIRRORING_ERROR_INVALID_OPERATION;
+       }
+
+       if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
+               scmirroring_error("setsockopt failed: %s", strerror(errno));
+               close(sock);
+               return SCMIRRORING_ERROR_INVALID_OPERATION;
+       }
+
+       channel = g_io_channel_unix_new(sock);
+       if (channel == NULL) {
+               scmirroring_error("g_io_channel_unix_new failed: %s", strerror(errno));
+       }
+
+       g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
+
+       _scmirroring->sock = sock;
+       _scmirroring->channel = channel;
+       _scmirroring->sock_path = g_strdup("/tmp/.miracast_ipc_rtspserver");
 
        /* Connecting to the miracast server */
        memset(&serv_addr, 0, sizeof(struct sockaddr_un));
@@ -504,7 +564,7 @@ try:
 
                        scmirroring_error("Connect error : %s", strerror(errno));
                        close(_scmirroring->sock);
-                       _scmirroring->sock = 0;
+                       _scmirroring->sock = -1;
                        return SCMIRRORING_ERROR_INVALID_OPERATION;
                }
        } else {
@@ -516,22 +576,23 @@ try:
        source = g_io_create_watch(_scmirroring->channel, G_IO_IN | G_IO_HUP | G_IO_ERR);
        int source_id = -1;
 
-       if((_scmirroring->ip != NULL) ||(_scmirroring->port != NULL))
-       {
-               ret = __scmirroring_src_send_set_ip (_scmirroring);
-               ret = __scmirroring_src_send_set_cm (_scmirroring);
-               ret = __scmirroring_src_send_set_reso (_scmirroring);
-       }
-
        /* Set callback to be called when socket is readable */
        g_source_set_callback(source, (GSourceFunc)__scmirroring_src_read_cb, _scmirroring, NULL);
        source_id = g_source_attach(source, g_main_context_get_thread_default());
 
        _scmirroring->source_id = source_id;
        _scmirroring->connected = CONNECTED_TO_SERVER;
+       _scmirroring->current_state = SCMIRRORING_STATE_READY;
 
        __scmirroring_src_set_callback_info (_scmirroring, SCMIRRORING_ERROR_NONE, SCMIRRORING_STATE_READY);
 
+       if((_scmirroring->ip != NULL) ||(_scmirroring->port != NULL))
+       {
+               ret = __scmirroring_src_send_set_ip (_scmirroring);
+               ret = __scmirroring_src_send_set_cm (_scmirroring);
+               ret = __scmirroring_src_send_set_reso (_scmirroring);
+       }
+
        scmirroring_debug_fleave();
 
        return ret;
@@ -547,9 +608,20 @@ int scmirroring_src_disconnect(scmirroring_src_h scmirroring)
 
        scmirroring_retvm_if(_scmirroring == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "Handle is NULL");
 
-       g_io_channel_shutdown (_scmirroring->channel, FALSE, NULL);
-       g_io_channel_unref(_scmirroring->channel);
-       close (_scmirroring->sock);
+       if(_scmirroring->channel != NULL)
+       {
+               g_io_channel_shutdown (_scmirroring->channel, FALSE, NULL);
+               g_io_channel_unref(_scmirroring->channel);
+               _scmirroring->channel = NULL;
+       }
+
+       if(_scmirroring->sock != -1)
+       {
+               close (_scmirroring->sock);
+               _scmirroring->sock = -1;
+       }
+
+       SCMIRRORING_SAFE_FREE(_scmirroring->sock_path);
        _scmirroring->connected = NOT_CONNECTED_TO_SERVER;
 
        scmirroring_debug_fleave();
@@ -638,9 +710,19 @@ int scmirroring_src_destroy(scmirroring_src_h scmirroring)
 
        scmirroring_retvm_if(_scmirroring == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "Handle is NULL");
 
-       ret = __scmirroring_src_send_cmd_to_server(_scmirroring, SCMIRRORING_STATE_CMD_DESTROY);
-       if(ret != SCMIRRORING_ERROR_NONE)
-               scmirroring_error("Failed to destroy [%d]", ret);
+       if(_scmirroring->connected == CONNECTED_TO_SERVER)
+       {
+               ret = __scmirroring_src_send_cmd_to_server(_scmirroring, SCMIRRORING_STATE_CMD_DESTROY);
+               if(ret != SCMIRRORING_ERROR_NONE)
+                       scmirroring_error("Failed to destroy [%d]", ret);
+       }
+       else
+       {
+               SCMIRRORING_SAFE_FREE(_scmirroring->ip);
+               SCMIRRORING_SAFE_FREE(_scmirroring->port);
+               SCMIRRORING_SAFE_FREE(_scmirroring->scmirroring_state_cb);
+               SCMIRRORING_SAFE_FREE(_scmirroring);
+       }
 
        scmirroring_debug_fleave();
 
index da750609c6456c6e2d1e094bd9ad020125c01d22..d674f3f55eb7c80c93605d3f650239e798c39114 100755 (executable)
@@ -46,7 +46,7 @@ static void __displaymenu(void)
        g_print("                          SCMIRRORING Testsuite (press q to quit) \n");
        g_print("=====================================================================\n");
        g_print("a : a ip port (ex. a 192.168.49.1 2022)\n");
-       g_print("c : set resopution (ex. c 0 (0 : 1920x1080_P30, 1 : 1280x720_P30, 2 : 960x540_P30, 3: 640x360_P30)\n");
+       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("C : Connect\n");
        g_print("I : dIsconnect\n");
index aea8588c095f5f8db9cf8ca454b3593688ca747a..4daeef88541f659da9ef52a4b10e9d9d983262b5 100755 (executable)
@@ -63,7 +63,7 @@ static void __displaymenu(void)
        g_print("=====================================================================\n");
        g_print("a : a ip port (ex. a 192.168.49.1 2022)\n");
        g_print("b : set sink device mac address (ex. b f8:d0:bd:7f:e9:7c)\n");
-       g_print("c : set resopution (ex. c 0 (0 : 1920x1080_P30, 1 : 1280x720_P30, 2 : 960x540_P30, 3: 640x360_P30)\n");
+       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("C : Connect\n");
        g_print("I : dIsconnect\n");
@@ -83,6 +83,21 @@ gboolean __timeout_menu_display(void* data)
        return FALSE;
 }
 
+static int __wifi_direct_device_connect()
+{
+       if (strlen(g_sink_mac_addr) > 17 || strlen(g_sink_mac_addr) <= 0) {
+               g_print("\nWrong Mac_address");
+               return SCMIRRORING_ERROR_INVALID_OPERATION;
+       }
+
+       int err=  wifi_direct_connect(g_sink_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;
+}
+
 static void __interpret (char *cmd)
 {
        int ret = SCMIRRORING_ERROR_NONE;
@@ -99,6 +114,7 @@ static void __interpret (char *cmd)
                strncpy (g_sink_mac_addr, value[1], sizeof (g_sink_mac_addr));
                g_sink_mac_addr[17] = '\0';
                g_print ("Sink mac address : %s\n", g_sink_mac_addr);
+               ret = __wifi_direct_device_connect();
        }
        else if (strncmp(cmd, "c", 1) == 0)
        {
@@ -268,18 +284,6 @@ void _discover_cb(int error_code, wifi_direct_discovery_state_e discovery_state,
                        break;
                case WIFI_DIRECT_DISCOVERY_FINISHED:
                        g_print("discovery_state : WIFI_DIRECT_DISCOVERY_FINISHED \n");
-
-                       if (strlen(g_sink_mac_addr) > 17 || strlen(g_sink_mac_addr) <= 0) {
-                               g_print("\nWrong Mac_address");
-                               return;
-                       }
-
-                       int err=  wifi_direct_connect(g_sink_mac_addr);
-                       if (err != WIFI_DIRECT_ERROR_NONE) {
-                               g_print("Failed to connect  [%d]\n", err);
-                               return;
-                       }
-
                        break;
                default:
                        g_print("discovery_state : ERROR\n");
@@ -291,7 +295,19 @@ void _discover_cb(int error_code, wifi_direct_discovery_state_e discovery_state,
 
 void _ip_assigned_cb(const char *mac_address, const char *ip_address, const char *interface_address, void *user_data)
 {
+       char *local_ip = NULL;
+
+       wifi_direct_get_ip_address (&local_ip);
+
+       if (!local_ip) {
+               g_print ("Failed to get local ip\n");
+               return;
+       }
+
        g_print("[_ip_assigned_cb] IP assigned [ ip addr : %s if addr : %s mac_addr:%s ]\n", ip_address, interface_address, mac_address);
+
+       scmirroring_src_set_ip_and_port(g_scmirroring, local_ip, "2022");
+       g_print ("Input server IP and port number IP[%s] Port[%s]\n", local_ip, "2022");
 }
 
 void _connection_cb(int error_code, wifi_direct_connection_state_e connection_state, const char *mac_address, void *user_data)
@@ -411,24 +427,23 @@ static gboolean __start_p2p_connection(gpointer data)
         }
     }
 
-    /*Enable Screen Mirroring*/
 #if 0
-    ret = wifi_direct_display_init();
+    /*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);
+        g_print("Error : wifi_direct_init_display failed : %d\n", ret);
         goto error;
     }
 
-    /*Enable Wifi Direct - You can set this as true if you want to see it from wifi-direct list*/
-    ret = wifi_direct_display_set_wifi_direct(FALSE);
+       ret = wifi_direct_set_display_availability(TRUE);
     if(ret != WIFI_DIRECT_ERROR_NONE)
     {
-        g_print("Error : wifi_direct_display_init failed : %d\n", ret);
+        g_print("Error : wifi_direct_set_display_availability failed : %d\n", ret);
         goto error;
     }
 
-    ret = wifi_direct_display_set_device(WIFI_DISPLAY_TYPE_PRIMARY_SINK, 77, 0);
+       ret = wifi_direct_set_display(WIFI_DISPLAY_TYPE_SRC, 2022, 0);
     if(ret != WIFI_DIRECT_ERROR_NONE)
     {
         g_print("Error : wifi_direct_display_set_device failed : %d\n", ret);