#include <tizen.h>
#include <scmirroring_type.h>
++#include <scmirroring_type_internal.h>
#ifdef __cplusplus
extern "C" {
--- /dev/null
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ /*
- * @brief This file contains the screen mirroring source API and functions related with screen mirroring as primary sink device.
++* Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ #ifndef __TIZEN_MEDIA_SCMIRRORING_PRIMARY_SINK_H__
+ #define __TIZEN_MEDIA_SCMIRRORING_PRIMARY_SINK_H__
+
+ #include <scmirroring_type.h>
+ #include <scmirroring_internal.h>
++#include <scmirroring_type_internal.h>
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif /* __cplusplus */
+
+ /**
+ * @file scmirroring_primary_sink.h
-int scmirroring_primary_sink_get_negotiated_video_codec(scmirroring_primary_sink_h *scmirroring_primary_sink, scmirroring_video_codec_e *codec);
++ * @brief This file contains APIs and functions related with screen mirroring as primary sink device.
+ */
+
+ /**
+ * @addtogroup CAPI_MEDIA_SCREEN_MIRRORING_MODULE
+ * @{
+ */
+
+ /**
+ * @brief Creates a new screen mirroring primary sink handle.
+ * @since_tizen 5.5
+ *
+ * @remarks You must release @a scmirroring_primary_sink using scmirroring_primary_sink_destroy().
+ *
+ * @param[out] scmirroring_primary_sink A newly returned handle to the screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_NULL
+ *
+ * @see scmirroring_primary_sink_destroy()
+ */
+ int scmirroring_primary_sink_create(scmirroring_primary_sink_h *scmirroring_primary_sink);
+
+ /**
+ * @brief Registers a callback function to be called when state change happens.
+ * @details This function registers user callback and this callback is called when each status is changed.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[in] callback The callback function to invoke
+ * @param[in] user_data The user data passed to the callback registration function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ *
+ * @see scmirroring_primary_sink_create()
+ */
+ int scmirroring_primary_sink_set_state_changed_cb(scmirroring_primary_sink_h scmirroring_primary_sink, scmirroring_sink_state_cb callback, void *user_data);
+
+ /**
+ * @brief Sets server IP and port.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[in] ip The server IP address to connect to
+ * @param[in] port The server port to connect to
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ *
+ * @see scmirroring_primary_sink_create()
+ */
+ int scmirroring_primary_sink_set_ip_and_port(scmirroring_primary_sink_h scmirroring_primary_sink, const char *ip, const char *port);
+
+ /**
+ * @brief Pass window handle created by application and surface type(x11/evas).
+ * @details This function will use handle created by the application to set the overlay &
+ * display on the surface passed by the application
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[in] type Surface type(x11/evas)
+ * @param[in] display_surface The display_surface created by application to force sink to display content over it
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ *
+ * @see scmirroring_primary_sink_create()
+ */
+ int scmirroring_primary_sink_set_display(scmirroring_primary_sink_h scmirroring_primary_sink, scmirroring_display_type_e type, void *display_surface);
+
+ /**
+ * @brief Sets resolutions of screen mirroring primary sink.
+ * @details This function sets resolutions of screen mirroring primary sink using scmirroring_resolution_e as following.
+ * (ex. SCMIRRORING_RESOLUTION_1920x1080_P30 | SCMIRRORING_RESOLUTION_1280x720_P30)
+ * Use it only when you want to set specific resolutions but if screen mirroring source dose not support
+ * the resolutions which you set, the screen mirroring primary sink will be disconnected.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[in] resolution Resolution of screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ *
+ * @see scmirroring_primary_sink_create()
+ */
+ int scmirroring_primary_sink_set_resolution(scmirroring_primary_sink_h scmirroring_primary_sink, int resolution);
+
+ /**
+ * @brief Prepares the screen mirroring primary sink handle and allocates specific resources.
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_NULL
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PREPARED
+ *
+ * @see scmirroring_primary_sink_create()
+ * @see scmirroring_primary_sink_set_state_changed_cb()
+ */
+ int scmirroring_primary_sink_prepare(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Creates connection and prepare for receiving data from SCMIRRORING source.
+ *
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_primary_sink_prepare()
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_PREPARED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_CONNECTED
+ *
+ * @see scmirroring_primary_sink_create()
+ * @see scmirroring_primary_sink_set_state_changed_cb()
+ * @see scmirroring_primary_sink_prepare()
+ */
+ int scmirroring_primary_sink_connect(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Starts receiving data from the SCMIRRORING source and display it(mirror).
+ *
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_primary_sink_prepare()
+ * @pre Call scmirroring_primary_sink_connect()
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_CONNECTED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PLAYING
+ *
+ * @see scmirroring_primary_sink_create()
+ * @see scmirroring_primary_sink_set_state_changed_cb()
+ * @see scmirroring_primary_sink_prepare()
+ * @see scmirroring_primary_sink_connect()
+ */
+ int scmirroring_primary_sink_start(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Pauses receiving data from the SCMIRRORING source.
+ * @details This function pauses receiving data from the SCMIRRORING source,
+ * which means it sends RTSP PAUSE message to source.
+ *
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_PLAYING
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PAUSED
+ *
+ * @see scmirroring_primary_sink_create()
+ * @see scmirroring_primary_sink_set_state_changed_cb()
+ * @see scmirroring_primary_sink_prepare()
+ * @see scmirroring_primary_sink_connect()
+ * @see scmirroring_primary_sink_start()
+ */
+ int scmirroring_primary_sink_pause(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Resumes receiving data from the SCMIRRORING source.
+ * @details This function pauses receiving data from the SCMIRRORING source, which means it sends RTSP PLAY message to source.
+ *
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_PAUSED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PLAYING
+ *
+ * @see scmirroring_primary_sink_pause()
+ */
+ int scmirroring_primary_sink_resume(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Disconnects and stops receiving data from the SCMIRRORING source.
+ *
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_CONNECTED
+ * or #SCMIRRORING_SINK_STATE_PLAYING or #SCMIRRORING_SINK_STATE_PAUSED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_DISCONNECTED
+ *
+ * @see scmirroring_primary_sink_create()
+ * @see scmirroring_primary_sink_set_state_changed_cb()
+ * @see scmirroring_primary_sink_prepare()
+ * @see scmirroring_primary_sink_connect()
+ * @see scmirroring_primary_sink_start()
+ */
+ int scmirroring_primary_sink_disconnect(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Unprepares screen mirroring.
+ * @details This function unprepares screen mirroring, which closes specific resources.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_primary_sink_prepare()
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_NULL
+ *
+ * @see scmirroring_primary_sink_create()
+ * @see scmirroring_primary_sink_set_state_changed_cb()
+ * @see scmirroring_primary_sink_prepare()
+ */
+ int scmirroring_primary_sink_unprepare(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Unregisters the callback function user registered.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ *
+ * @see scmirroring_primary_sink_create()
+ * @see scmirroring_primary_sink_set_state_changed_cb()
+ */
+ int scmirroring_primary_sink_unset_state_changed_cb(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Destroys screen mirroring primary sink handle.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_NULL
+ *
+ * @see scmirroring_primary_sink_create()
+ */
+ int scmirroring_primary_sink_destroy(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Gets negotiated video codec of screen mirroring primary sink.
+ * @details The video codec is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[out] codec Codec of video
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_primary_sink_prepare()
+ * @pre Call scmirroring_primary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
-int scmirroring_primary_sink_get_negotiated_video_resolution(scmirroring_primary_sink_h *scmirroring_primary_sink, int *width, int *height);
++int scmirroring_primary_sink_get_negotiated_video_codec(scmirroring_primary_sink_h scmirroring_primary_sink, scmirroring_video_codec_e *codec);
+
+ /**
+ * @brief Gets negotiated video resolution of screen mirroring primary sink.
+ * @details The video resolution is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[out] width Width of video
+ * @param[out] height Height of video
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_primary_sink_prepare()
+ * @pre Call scmirroring_primary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
-int scmirroring_primary_sink_get_negotiated_video_frame_rate(scmirroring_primary_sink_h *scmirroring_primary_sink, int *frame_rate);
++int scmirroring_primary_sink_get_negotiated_video_resolution(scmirroring_primary_sink_h scmirroring_primary_sink, int *width, int *height);
+
+ /**
+ * @brief Gets negotiated frame rate of screen mirroring primary sink.
+ * @details The video frame rate is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[out] frame_rate Frame rate of video
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_primary_sink_prepare()
+ * @pre Call scmirroring_primary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
-int scmirroring_primary_sink_get_negotiated_audio_codec(scmirroring_primary_sink_h *scmirroring_primary_sink, scmirroring_audio_codec_e *codec);
++int scmirroring_primary_sink_get_negotiated_video_frame_rate(scmirroring_primary_sink_h scmirroring_primary_sink, int *frame_rate);
+
+ /**
+ * @brief Gets negotiated audio codec of screen mirroring primary sink.
+ * @details The audio codec is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[out] codec Codec of audio
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_primary_sink_prepare()
+ * @pre Call scmirroring_primary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
-int scmirroring_primary_sink_get_negotiated_audio_channel(scmirroring_primary_sink_h *scmirroring_primary_sink, int *channel);
++int scmirroring_primary_sink_get_negotiated_audio_codec(scmirroring_primary_sink_h scmirroring_primary_sink, scmirroring_audio_codec_e *codec);
+
+ /**
+ * @brief Gets negotiated audio channel of screen mirroring primary sink.
+ * @details The audio channel is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[out] channel Channel of audio
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_primary_sink_prepare()
+ * @pre Call scmirroring_primary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
-int scmirroring_primary_sink_get_negotiated_audio_sample_rate(scmirroring_primary_sink_h *scmirroring_primary_sink, int *sample_rate);
++int scmirroring_primary_sink_get_negotiated_audio_channel(scmirroring_primary_sink_h scmirroring_primary_sink, int *channel);
+
+ /**
+ * @brief Gets negotiated audio sample rate of screen mirroring primary sink.
+ * @details The audio sample rate is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[out] sample_rate Sample rate of audio
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_primary_sink_prepare()
+ * @pre Call scmirroring_primary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
-int scmirroring_primary_sink_get_negotiated_audio_bitwidth(scmirroring_primary_sink_h *scmirroring_primary_sink, int *bitwidth);
++int scmirroring_primary_sink_get_negotiated_audio_sample_rate(scmirroring_primary_sink_h scmirroring_primary_sink, int *sample_rate);
+
+ /**
+ * @brief Gets negotiated audio bitwidth of screen mirroring primary sink.
+ * @details The audio bitwidth is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[out] bitwidth Bitwidth of audio
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring primary sink handle by calling scmirroring_primary_sink_create().
+ * @pre Register user callback by calling scmirroring_primary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_primary_sink_prepare()
+ * @pre Call scmirroring_primary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
- * @since_tizen 5.0
++int scmirroring_primary_sink_get_negotiated_audio_bitwidth(scmirroring_primary_sink_h scmirroring_primary_sink, int *bitwidth);
+
+ /**
+ * @brief Gets the current state of screen mirroring primary sink.
+ * @details The current state of screen mirroring primary sink izzs changed by calling CAPIs. And it provides the state of screen mirroring primary sink the time this api is called.
+ *
-int scmirroring_primary_sink_set_coupled_sink_status(scmirroring_primary_sink_h scmirroring_primary_sink, int status);
++ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_primary_sink The handle to the screen mirroring primary sink
+ * @param[out] state The current state of screen mirroring primary sink
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring 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);
+
++/**
++ * @brief Called when user wants to set 'address' of screen mirroring primary sink.
++ *
++ * @details It sets MAC address to screen mirroring primary sink's property.
++ *
++ * @since_tizen 5.5
++ *
++ * @param[in] scmirroring_primary_sink Screen mirroring primary sink handle
++ * @param[in] address Mac address of coupled screen mirroring coupled sink.
++ *
++ * @pre scmirroring_primary_sink_create()
++ *
++ * @see scmirroring_primary_sink_create()
++ */
++int scmirroring_primary_sink_set_coupled_sink(scmirroring_primary_sink_h scmirroring_primary_sink, gchar* address);
++
++/**
++ * @brief Called when user wants to set 'status' of screen mirroring primary sink.
++ *
++ * @details It sets status to screen mirroring primary sink's property.
++ *
++ * @since_tizen 5.5
++ *
++ * @param[in] scmirroring_primary_sink Screen mirroring primary sink handle
++ * @param[in] address Mac address of coupled screen mirroring coupled sink.
++ *
++ * @pre scmirroring_primary_sink_create()
++ *
++ * @see scmirroring_primary_sink_create()
++ */
++int scmirroring_primary_sink_set_coupled_sink_status(scmirroring_primary_sink_h scmirroring_primary_sink, int status);
+
+ /**
+ * @brief Creates screen mirroring source handle.
+ * @remarks You must release @a scmirroring_primary_sink using scmirroring_primary_src_destroy().
+ *
++ * @since_tizen 5.5
++ *
+ * @param[out] scmirroring_primary_sink The handle to screen mirroring source
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @see scmirroring_primary_src_destroy()
+ */
+ int scmirroring_primary_src_create(scmirroring_primary_sink_h *scmirroring_primary_sink);
+
+ /**
+ * @brief Registers user callback to get status of screen mirroring.
+ * @details This function registers user callback and this callback is called when each status is changed.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ * @param[in] callback The callback function to invoke
+ * @param[in] user_data The user data passed to the callback registration function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ *
+ * @see scmirroring_primary_src_create()
+ */
+ int scmirroring_primary_src_set_state_changed_cb(scmirroring_primary_sink_h scmirroring_primary_sink_src, scmirroring_state_cb callback, void *user_data);
+
+ /**
+ * @brief Sets connection mode of screen mirroring.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ * @param[in] connection_mode connection mode of screen mirroring
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ *
+ * @see scmirroring_primary_src_create()
+ */
+ int scmirroring_primary_src_set_connection_mode(scmirroring_primary_sink_h scmirroring_primary_sink_src, scmirroring_connection_mode_e connection_mode);
+
+ /**
+ * @brief Sets IP address and port number of screen mirroring source.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ * @param[in] ip Server IP address
+ * @param[in] port Server port
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ *
+ * @see scmirroring_primary_src_create()
+ */
+ int scmirroring_primary_src_set_ip_and_port(scmirroring_primary_sink_h scmirroring_primary_sink_src, const char *ip, const char *port);
+
+ /**
+ * @brief Sets resolution of screen mirroring source.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ * @param[in] resolution Resolution of screen mirroring source
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ *
+ * @see scmirroring_primary_src_create()
+ */
+ int scmirroring_primary_src_set_resolution(scmirroring_primary_sink_h scmirroring_primary_sink_src, scmirroring_resolution_e resolution);
+
+ /**
+ * @brief Sets name of screen mirroring source server.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ * @param[in] name Name of screen mirroring source server
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ *
+ * @see scmirroring_primary_src_create()
+ */
+ int scmirroring_primary_src_set_server_name(scmirroring_primary_sink_h scmirroring_primary_sink_src, const char *name);
+
+ /**
+ * @brief Enables/Disables screen mirroring multisink.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ * @param[in] multisink Ability to send to multisink
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ *
+ * @see scmirroring_primary_src_create()
+ */
+ int scmirroring_primary_src_set_multisink_ability(scmirroring_primary_sink_h scmirroring_primary_sink_src, scmirroring_multisink_e multisink);
+
+ /**
+ * @brief Connects to server for screen mirroring as source, asynchronously.
+ * @details This function launches server and connects to the server for screen mirroring as source to command server to start/pause/resume/stop.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_CONNECTION_TIME_OUT Connection timeout
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ * @pre Register user callback by calling scmirroring_primary_src_set_state_changed_cb().
+ * @post The screen mirroring state will be SCMIRRORING_STATE_READY
+ *
+ * @see scmirroring_primary_src_create()
+ * @see scmirroring_primary_src_set_state_changed_cb()
+ */
+ int scmirroring_primary_src_connect(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Starts screen mirroring, asynchronously.
+ * @details This function starts screen mirroring, which means it starts to negotiate and stream RTP multimedia data.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_CONNECTION_TIME_OUT Connection timeout
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ * @pre Register user callback by calling scmirroring_primary_src_set_state_changed_cb().
+ * @pre Call scmirroring_primary_src_connect()
+ * @post The screen mirroring state will be SCMIRRORING_STATE_CONNECTION_WAIT if server starts to listen
+ * @post The screen mirroring state will be SCMIRRORING_STATE_CONNECTED if client connects to the server
+ * @post The screen mirroring state will be SCMIRRORING_STATE_PLAYING if server starts to stream multimedia data
+ *
+ * @see scmirroring_primary_src_create()
+ * @see scmirroring_primary_src_set_state_changed_cb()
+ * @see scmirroring_primary_src_connect()
+ */
+ int scmirroring_primary_src_start(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Pauses screen mirroring, asynchronously.
+ * @details This function pauses screen mirroring, which means it sends RTSP PAUSE trigger message to sink.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre The screen mirroring state should be SCMIRRORING_STATE_PLAYING
+ * @post The screen mirroring state will be SCMIRRORING_STATE_PAUSED
+ *
+ * @see scmirroring_primary_src_create()
+ * @see scmirroring_primary_src_set_state_changed_cb()
+ * @see scmirroring_primary_src_connect()
+ * @see scmirroring_primary_src_start()
+ */
+ int scmirroring_primary_src_pause(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Resumes screen mirroring, asynchronously.
+ * @details This function resumes screen mirroring, which means it sends RTSP PLAY message to sink.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre The screen mirroring state should be SCMIRRORING_STATE_PAUSED
+ * @post The screen mirroring state will be SCMIRRORING_STATE_PLAYING
+ *
+ * @see scmirroring_primary_src_pause()
+ */
+ int scmirroring_primary_src_resume(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Enable streaming without reencoding for screen mirroring.
+ * @details This function enable streaming without reencoding for screen mirroring, which means files that encoded with supported formats will be streamed without decoding and reencoding.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ * @param[in] enable Ability to stream file directly
+ * @param[in] uri_srcname File name to stream directly
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory to allocate new object
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION External function not implemented
+ *
+ * @pre The screen mirroring state should be SCMIRRORING_STATE_PLAYING
+ *
+ * @see scmirroring_primary_src_create()
+ * @see scmirroring_primary_src_set_state_changed_cb()
+ * @see scmirroring_primary_src_connect()
+ * @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);
++
++/**
++ * @brief Make Miracast Server 'coupling' mode.
++ * @details This function make Miracast Server 'coupling' mode.
++ * If it is set, connected sink devices is considered as secondary sink and both are goint to try coupling.
++ *
++ * @since_tizen 5.5
++ *
++ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
++ * @param[in] coupling_mode value which set coupling mode (0 : disable, 1 : enable)
++ *
++ * @return @c 0 on success,
++ * otherwise a negative error value
++ *
++ * @retval #SCMIRRORING_ERROR_NONE Successful
++ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
++ *
++ * @pre The screen mirroring state should be SCMIRRORING_STATE_PLAYING
++ *
++ * @see scmirroring_primary_src_create()
++ * @see scmirroring_primary_src_set_state_changed_cb()
++ * @see scmirroring_primary_src_connect()
++ * @see scmirroring_primary_src_start()
++ */
+ int scmirroring_primary_src_set_coupling_mode(scmirroring_primary_sink_h scmirroring, scmirroring_coupling_mode_e coupling_mode);
+
+ /**
+ * @brief Change transport for AV streaming.
+ * @details This function changes transport for AV streaming. Default transport is UDP.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ * @param[in] transport Transport for audio/video streaming data
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory to allocate new object
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION External function not implemented
+ *
+ * @pre The screen mirroring state should be SCMIRRORING_STATE_PLAYING
+ *
+ * @see scmirroring_primary_src_create()
+ * @see scmirroring_primary_src_set_state_changed_cb()
+ * @see scmirroring_primary_src_connect()
+ * @see scmirroring_primary_src_start()
+ */
+ int scmirroring_primary_src_AV_transport_switch(scmirroring_primary_sink_h scmirroring_primary_sink_src, scmirroring_av_transport_e transport);
+
+ /**
+ * @brief Stops screen mirroring, asynchronously.
+ * @details This function stops screen mirroring, which means it sends RTSP TEARDOWN trigger message to sink.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_CONNECTION_TIME_OUT Connection timeout
+ *
+ * @pre The screen mirroring state should be SCMIRRORING_STATE_PAUSED or SCMIRRORING_STATE_PLAYING
+ * @post The screen mirroring state will be SCMIRRORING_STATE_TEARDOWN
+ *
+ * @see scmirroring_primary_src_create()
+ * @see scmirroring_primary_src_set_state_changed_cb()
+ * @see scmirroring_primary_src_connect()
+ * @see scmirroring_primary_src_start()
+ */
+ int scmirroring_primary_src_stop(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Disconnects server for screen mirroring.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_CONNECTION_TIME_OUT Connection timeout
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ * @pre Register user callback by calling scmirroring_primary_src_set_state_changed_cb().
+ * @pre Connects to server for screen mirroring source by calling scmirroring_primary_src_connect().
+ * @post The screen mirroring state will be SCMIRRORING_STATE_NULL
+ *
+ * @see scmirroring_primary_src_create()
+ * @see scmirroring_primary_src_set_state_changed_cb()
+ * @see scmirroring_primary_src_connect()
+ */
+ int scmirroring_primary_src_disconnect(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Unregisters the callback function user registered
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ * @pre Register user callback by calling scmirroring_primary_src_set_state_changed_cb().
+ *
+ * @see scmirroring_primary_src_create()
+ * @see scmirroring_primary_src_set_state_changed_cb()
+ */
+ int scmirroring_primary_src_unset_state_changed_cb(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ /**
+ * @brief Destroys server and screen mirroring source handle.
+ *
++ * @since_tizen 5.5
++ *
+ * @param[in] scmirroring_primary_sink The handle to screen mirroring source
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_CONNECTION_TIME_OUT Connection timeout
+ *
+ * @pre Create a screen mirroring source handle by calling scmirroring_primary_src_create().
+ * @pre The screen mirroring state should be SCMIRRORING_STATE_NULL
+ *
+ * @see scmirroring_primary_src_create()
+ */
+ int scmirroring_primary_src_destroy(scmirroring_primary_sink_h scmirroring_primary_sink);
+
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+
+ /**
+ * @}
+ */
+
+ #endif /* __TIZEN_MEDIA_SCMIRRORING_PRIMARY_SINK_H__ */
unsigned int magic_num;
} scmirroring_sink_s;
- unsigned int magic_num;
+ typedef struct {
+ unsigned int magic_num;
+ MMHandleType mm_handle;
+ char *ip;
+ char *port;
+ bool use_hdcp;
+ char *server_name;
+ int resolution;
+ int connected;
+ int sock;
+ int source_id;
+ GIOChannel *channel;
+ char *sock_path;
+ int connect_mode;
+ int current_state;
+ scmirroring_state_cb_s *scmirroring_state_cb;
+ scmirroring_sink_state_cb_s *scmirroring_sink_state_cb;
+ scmirroring_multisink_e multisink;
+ 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;
+
+
+ typedef struct {
++ unsigned int magic_num;
+ MMHandleType mm_handle;
+ char *ip;
+ char *port;
+ bool use_hdcp;
+ scmirroring_sink_state_cb_s *scmirroring_sink_state_cb;
+ } scmirroring_secondary_sink_s;
+
#define WIFIDIRECT_DISPLAY_FEATURE "http://tizen.org/feature/network.wifi.direct.display"
#define CHECK_FEATURE_SUPPORTED(feature_name)\
--- /dev/null
-* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ /*
- * @brief This file contains the screen mirroring source API and functions related with screen mirroring as sink device.
++* Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ #ifndef __TIZEN_MEDIA_SCMIRRORING_SECONDARY_SINK_H__
+ #define __TIZEN_MEDIA_SCMIRRORING_SECONDARY_SINK_H__
+
+ #include <scmirroring_type.h>
++#include <scmirroring_type_internal.h>
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif /* __cplusplus */
+
+ /**
+ * @file scmirroring_secondary_sink.h
-int scmirroring_secondary_sink_get_negotiated_audio_codec(scmirroring_secondary_sink_h *scmirroring_secondary_sink, scmirroring_audio_codec_e *codec);
++ * @brief This file contains APIs and functions related with screen mirroring as secondary sink device.
++
+ */
+
+ /**
+ * @addtogroup CAPI_MEDIA_SCREEN_MIRRORING_MODULE
+ * @{
+ */
+
+ /**
+ * @brief Creates a new screen mirroring secondary sink handle.
+ * @since_tizen 5.5
+ *
+ * @remarks You must release @a scmirroring_secondary_sink using scmirroring_secondary_sink_destroy().
+ *
+ * @param[out] scmirroring_secondary_sink A newly returned handle to the screen mirroring secondary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_NULL
+ *
+ * @see scmirroring_secondary_sink_destroy()
+ */
+ int scmirroring_secondary_sink_create(scmirroring_secondary_sink_h *scmirroring_secondary_sink);
+
+ /**
+ * @brief Registers a callback function to be called when state change happens.
+ * @details This function registers user callback and this callback is called when each status is changed.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @param[in] callback The callback function to invoke
+ * @param[in] user_data The user data passed to the callback registration function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ *
+ * @see scmirroring_secondary_sink_create()
+ */
+ int scmirroring_secondary_sink_set_state_changed_cb(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_sink_state_cb callback, void *user_data);
+
+ /**
+ * @brief Sets server IP and port.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @param[in] ip The server IP address to connect to
+ * @param[in] port The server port to connect to
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ *
+ * @see scmirroring_secondary_sink_create()
+ */
+ int scmirroring_secondary_sink_set_ip_and_port(scmirroring_secondary_sink_h scmirroring_secondary_sink, const char *ip, const char *port);
+
+ /**
+ * @brief Prepares the screen mirroring sink handle and allocates specific resources.
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_NULL
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PREPARED
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ */
+ int scmirroring_secondary_sink_prepare(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+ /**
+ * @brief Creates connection and prepare for receiving data from SCMIRRORING source.
+ *
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_PREPARED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_CONNECTED
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ * @see scmirroring_secondary_sink_prepare()
+ */
+ int scmirroring_secondary_sink_connect(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+ /**
+ * @brief Starts receiving data from the SCMIRRORING source and display it(mirror).
+ *
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_CONNECTED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PLAYING
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ * @see scmirroring_secondary_sink_prepare()
+ * @see scmirroring_secondary_sink_connect()
+ */
+ int scmirroring_secondary_sink_start(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+ /**
+ * @brief Pauses receiving data from the SCMIRRORING source.
+ * @details This function pauses receiving data from the SCMIRRORING source,
+ * which means it sends RTSP PAUSE message to source.
+ *
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_PLAYING
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PAUSED
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ * @see scmirroring_secondary_sink_prepare()
+ * @see scmirroring_secondary_sink_connect()
+ * @see scmirroring_secondary_sink_start()
+ */
+ int scmirroring_secondary_sink_pause(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+ /**
+ * @brief Resumes receiving data from the SCMIRRORING source.
+ * @details This function pauses receiving data from the SCMIRRORING source, which means it sends RTSP PLAY message to source.
+ *
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_PAUSED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_PLAYING
+ *
+ * @see scmirroring_secondary_sink_pause()
+ */
+ int scmirroring_secondary_sink_resume(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+ /**
+ * @brief Disconnects and stops receiving data from the SCMIRRORING source.
+ *
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_CONNECTED
+ * or #SCMIRRORING_SINK_STATE_PLAYING or #SCMIRRORING_SINK_STATE_PAUSED
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_DISCONNECTED
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ * @see scmirroring_secondary_sink_prepare()
+ * @see scmirroring_secondary_sink_connect()
+ * @see scmirroring_secondary_sink_start()
+ */
+ int scmirroring_secondary_sink_disconnect(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+ /**
+ * @brief Unprepares screen mirroring.
+ * @details This function unprepares screen mirroring, which closes specific resources.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @post The screen mirroring state will be #SCMIRRORING_SINK_STATE_NULL
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ * @see scmirroring_secondary_sink_prepare()
+ */
+ int scmirroring_secondary_sink_unprepare(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+ /**
+ * @brief Unregisters the callback function user registered.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ *
+ * @see scmirroring_secondary_sink_create()
+ * @see scmirroring_secondary_sink_set_state_changed_cb()
+ */
+ int scmirroring_secondary_sink_unset_state_changed_cb(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+ /**
+ * @brief Destroys screen mirroring secondary sink handle.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre The screen mirroring state should be #SCMIRRORING_SINK_STATE_NULL
+ *
+ * @see scmirroring_secondary_sink_create()
+ */
+ int scmirroring_secondary_sink_destroy(scmirroring_secondary_sink_h scmirroring_secondary_sink);
+
+ /**
+ * @brief Gets negotiated audio codec of screen mirroring secondary sink.
+ * @details The audio codec is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @param[out] codec Codec of audio
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
-int scmirroring_secondary_sink_get_negotiated_audio_channel(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *channel);
++int scmirroring_secondary_sink_get_negotiated_audio_codec(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_audio_codec_e *codec);
+
+ /**
+ * @brief Gets negotiated audio channel of screen mirroring secondary sink.
+ * @details The audio channel is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @param[out] channel Channel of audio
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
-int scmirroring_secondary_sink_get_negotiated_audio_sample_rate(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *sample_rate);
++int scmirroring_secondary_sink_get_negotiated_audio_channel(scmirroring_secondary_sink_h scmirroring_secondary_sink, int *channel);
+
+ /**
+ * @brief Gets negotiated audio sample rate of screen mirroring secondary sink.
+ * @details The audio sample rate is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring sink
+ * @param[out] sample_rate Sample rate of audio
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
-int scmirroring_secondary_sink_get_negotiated_audio_bitwidth(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *bitwidth);
++int scmirroring_secondary_sink_get_negotiated_audio_sample_rate(scmirroring_secondary_sink_h scmirroring_secondary_sink, int *sample_rate);
+
+ /**
+ * @brief Gets negotiated audio bitwidth of screen mirroring secondary sink.
+ * @details The audio bitwidth is negotiated by screen mirroring source.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @param[out] bitwidth Bitwidth of audio
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ * @pre Register user callback by calling scmirroring_secondary_sink_set_state_changed_cb().
+ * @pre Call scmirroring_secondary_sink_prepare()
+ * @pre Call scmirroring_secondary_sink_connect()
+ * @pre The screen mirroring state must be #SCMIRRORING_SINK_STATE_CONNECTED or #SCMIRRORING_SINK_STATE_PLAYING
+ */
++int scmirroring_secondary_sink_get_negotiated_audio_bitwidth(scmirroring_secondary_sink_h scmirroring_secondary_sink, int *bitwidth);
+
+ /**
+ * @brief Gets the current state of screen mirroring secondary sink.
+ * @details The current state of screen mirroring sink is changed by calling CAPIs. And it provides the state of screen mirroring sink the time this api is called.
+ *
+ * @since_tizen 5.5
+ *
+ * @param[in] scmirroring_secondary_sink The handle to the screen mirroring secondary sink
+ * @param[out] state The current state of screen mirroring sink
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SCMIRRORING_ERROR_NONE Successful
+ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SCMIRRORING_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #SCMIRRORING_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SCMIRRORING_ERROR_UNKNOWN Unknown Error
+ *
+ * @pre Create a screen mirroring sink handle by calling scmirroring_secondary_sink_create().
+ */
+ int scmirroring_secondary_sink_get_current_state(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_sink_state_e *state);
+
++/**
++ * @brief Called when user wants to set 'address' of screen mirroring sink.
++ *
++ * @details It sets MAC address to screen mirroring sink's property.
++ *
++ * @param[in] scmirroring_secondary_sink Screen mirroring secondary sink handle
++ * @param[in] address Mac address of coupled screen mirroring sink.
++ *
++ * @pre scmirroring_secondary_sink_create()
++ *
++ * @see scmirroring_secondary_sink_create()
++ */
++int scmirroring_secondary_sink_set_coupled_sink(scmirroring_secondary_sink_h scmirroring_secondary_sink, gchar* address);
++
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+
+ /**
+ * @}
+ */
+
+ #endif /*__TIZEN_MEDIA_SCMIRRORING_SECONDARY_SINK_H__*/
* @see scmirroring_src_create()
*/
int scmirroring_src_set_multisink_ability(scmirroring_src_h scmirroring_src, scmirroring_multisink_e multisink);
+
++/**
++ * @brief Make Miracast Server 'coupling' mode.
++ * @details This function make Miracast Server 'coupling' mode.
++ * If it is set, connected sink devices is considered as secondary sink and both are goint to try coupling.
++ *
++ * @since_tizen 5.5
++ *
++ * @param[in] scmirroring The handle to screen mirroring source
++ * @param[in] coupling_mode value which set coupling mode (0 : disable, 1 : enable)
++ *
++ * @return @c 0 on success,
++ * otherwise a negative error value
++ *
++ * @retval #SCMIRRORING_ERROR_NONE Successful
++ * @retval #SCMIRRORING_ERROR_INVALID_PARAMETER Invalid parameter
++ *
++ * @pre The screen mirroring state should be SCMIRRORING_STATE_PLAYING
++ *
++ * @see scmirroring_primary_src_create()
++ * @see scmirroring_primary_src_set_state_changed_cb()
++ * @see scmirroring_primary_src_connect()
++ * @see scmirroring_primary_src_start()
++ */
+ 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.
* @details This function launches server and connects to the server for screen mirroring as source to command server to start/pause/resume/stop.
--- /dev/null
--- /dev/null
++/*
++* Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
++*
++* Licensed under the Apache License, Version 2.0 (the "License");
++* you may not use this file except in compliance with the License.
++* You may obtain a copy of the License at
++*
++* http://www.apache.org/licenses/LICENSE-2.0
++*
++* Unless required by applicable law or agreed to in writing, software
++* distributed under the License is distributed on an "AS IS" BASIS,
++* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++* See the License for the specific language governing permissions and
++* limitations under the License.
++*/
++
++#ifndef __TIZEN_MEDIA_SCMIRRORING_TYPE_INTERNAL_H__
++#define __TIZEN_MEDIA_SCMIRRORING_TYPE_INTERNAL_H__
++
++#include <tizen.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++/**
++ * @file scmirroring_type_internal.h
++ * @brief This file contains API related to screen mirroring enumerations for classes of errors.
++ */
++
++/**
++ * @brief The handle to the screen mirroring primary sink.
++ * @since_tizen 5.5
++ */
++typedef void *scmirroring_primary_sink_h;
++
++/**
++ * @brief The handle to the screen mirroring secondary sink.
++ * @since_tizen 5.5
++ */
++typedef void *scmirroring_secondary_sink_h;
++
++/**
++ * @brief Enumeration for screen mirroring coupling 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;
++
++/**
++ * @brief Enumeration for screen mirroring coupling status.
++ * @since_tizen 5.5
++ */
++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;
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* __TIZEN_MEDIA_SCMIRRORING_TYPE_INTERNAL_H__ */
gint resolution;
gint connection_mode;
gint multisink;
- gint coupling_mode;
++ gint coupling_mode;
gpointer _gst_reserved[GST_PADDING];
};
scmirroring_debug("client %p: connection closed", client);
- /* Sends Secondary sink ip to scmirroring_src */
- if(g_strcmp0(gst_rtsp_connection_get_ip(connection), COUPLED_SINK_ADDRESS) == 0){
++ /* Sends coupled sink address to scmirroring_src */
++ if(server_obj->coupling_mode == 1){
+ 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);
+ }
klass->send_response(server_obj, "OK:STOP");
return;
Name: capi-media-screen-mirroring
Summary: A screen mirroring library in Tizen C API
- Version: 0.1.95
-Version: 0.1.97
++Version: 0.2.0
Release: 0
Group: Multimedia/API
License: Apache-2.0
%files devel
%{_includedir}/media/scmirroring_src.h
%{_includedir}/media/scmirroring_sink.h
+ %{_includedir}/media/scmirroring_primary_sink.h
+ %{_includedir}/media/scmirroring_secondary_sink.h
%{_includedir}/media/scmirroring_type.h
++%{_includedir}/media/scmirroring_type_internal.h
%{_includedir}/media/scmirroring_src_ini.h
%{_includedir}/media/scmirroring_internal.h
%{_includedir}/media/miracast_server.h
--- /dev/null
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ /*
-int scmirroring_primary_sink_get_negotiated_video_codec(scmirroring_primary_sink_h *scmirroring_primary_sink, scmirroring_video_codec_e *codec)
++* Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ #include <stdio.h>
+ #include <mmf/mm_wfd_sink.h>
+ #include <scmirroring_primary_sink.h>
+ #include <scmirroring_private.h>
+
+ #include <gio/gio.h>
+ #include <sys/types.h>
+ #include <sys/un.h>
+ #include <sys/socket.h>
+ #include <linux/socket.h>
+ #include <netinet/tcp.h>
+
+ #define MAX_MSG_LEN 128
+ #define TIMEOUT_SEC 2
+ #define CONNECTED_TO_SERVER 1
+ #define NOT_CONNECTED_TO_SERVER 0
+
+ static scmirroring_error_e __scmirroring_primary_sink_error_convert(const char *func, int error)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ const char *errorstr = NULL;
+
+ switch (error) {
+ case MM_ERROR_NONE:
+ ret = SCMIRRORING_ERROR_NONE;
+ errorstr = "ERROR_NONE";
+ break;
+
+ case MM_ERROR_WFD_NO_FREE_SPACE:
+ ret = SCMIRRORING_ERROR_OUT_OF_MEMORY;
+ errorstr = "OUT_OF_MEMORY";
+ break;
+
+ case MM_ERROR_WFD_NOT_INITIALIZED:
+ case MM_ERROR_COMMON_INVALID_ATTRTYPE:
+ case MM_ERROR_COMMON_INVALID_PERMISSION:
+ case MM_ERROR_COMMON_OUT_OF_ARRAY:
+ case MM_ERROR_COMMON_OUT_OF_RANGE:
+ case MM_ERROR_COMMON_ATTR_NOT_EXIST:
+ ret = SCMIRRORING_ERROR_INVALID_PARAMETER;
+ errorstr = "INVALID_PARAMETER";
+ break;
+
+ default:
+ ret = SCMIRRORING_ERROR_INVALID_OPERATION;
+ errorstr = "INVALID_OPERATION";
+ }
+
+ if (ret != SCMIRRORING_ERROR_NONE)
+ scmirroring_error("[%s] %s (0x%08x) : core frameworks error code(0x%08x)", func, errorstr, ret, error);
+ else
+ scmirroring_debug("[%s] %s", func, errorstr);
+
+ return ret;
+ }
+
+ static scmirroring_sink_state_e __scmirroring_primary_sink_state_convert(MMWFDSinkStateType mm_state)
+ {
+ scmirroring_sink_state_e state = SCMIRRORING_SINK_STATE_NONE;
+
+ switch (mm_state) {
+ case MM_WFD_SINK_STATE_NONE:
+ state = SCMIRRORING_SINK_STATE_NONE;
+ break;
+ case MM_WFD_SINK_STATE_NULL:
+ state = SCMIRRORING_SINK_STATE_NULL;
+ break;
+ case MM_WFD_SINK_STATE_PREPARED:
+ state = SCMIRRORING_SINK_STATE_PREPARED;
+ break;
+ case MM_WFD_SINK_STATE_CONNECTED:
+ state = SCMIRRORING_SINK_STATE_CONNECTED;
+ break;
+ case MM_WFD_SINK_STATE_PLAYING:
+ state = SCMIRRORING_SINK_STATE_PLAYING;
+ break;
+ case MM_WFD_SINK_STATE_PAUSED:
+ state = SCMIRRORING_SINK_STATE_PAUSED;
+ break;
+ case MM_WFD_SINK_STATE_DISCONNECTED:
+ state = SCMIRRORING_SINK_STATE_DISCONNECTED;
+ break;
+ default:
+ state = SCMIRRORING_SINK_STATE_NONE;
+ break;
+ }
+
+ return state;
+ }
+
+ void __mm_scmirroring_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_primary_sink_state_convert(state_type);
+ scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)uData;
+
+ /* call application callback */
+ if (handle && handle->scmirroring_sink_state_cb && handle->scmirroring_sink_state_cb->state_cb)
+ handle->scmirroring_sink_state_cb->state_cb(error, state, handle->scmirroring_sink_state_cb->user_data);
+
+ return;
+ }
+
+ int scmirroring_primary_sink_create(scmirroring_primary_sink_h *scmirroring_primary_sink)
+ {
+ CHECK_FEATURE_SUPPORTED(WIFIDIRECT_DISPLAY_FEATURE);
+
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_debug_fenter();
+
+ 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_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->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) {
+ SCMIRRORING_SAFE_FREE(handle);
+ scmirroring_error("Fail to Create");
+ return __scmirroring_primary_sink_error_convert(__func__, ret);
+ }
+
+ *scmirroring_primary_sink = (scmirroring_primary_sink_h)handle;
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_set_ip_and_port(scmirroring_primary_sink_h scmirroring_primary_sink, const char *ip, const char *port)
+ {
+ 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");
+ scmirroring_retvm_if(ip == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "ip is NULL");
+ scmirroring_retvm_if(port == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "port is NULL");
+
+ scmirroring_debug("ip[%s] port[%s]", ip, port);
+
+ SCMIRRORING_SAFE_FREE(handle->ip);
+ handle->ip = strdup(ip);
+ scmirroring_retvm_if(handle->ip == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Out of memory for ip");
+
+ SCMIRRORING_SAFE_FREE(handle->port);
+ handle->port = strdup(port);
+ scmirroring_retvm_if(handle->port == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Out of memory for port");
+
+ scmirroring_debug_fleave();
+
+ return SCMIRRORING_ERROR_NONE;
+ }
+
+ int scmirroring_primary_sink_prepare(scmirroring_primary_sink_h scmirroring_primary_sink)
+ {
+ 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");
+
+ ret = mm_wfd_sink_prepare(handle->mm_handle);
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_connect(scmirroring_primary_sink_h scmirroring_primary_sink)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ char server_uri[255] = {0, };
+
+ 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 (handle->ip == NULL) {
+ scmirroring_error("INVALID_IP(NULL) (0x%08x)", SCMIRRORING_ERROR_INVALID_PARAMETER);
+ return SCMIRRORING_ERROR_INVALID_PARAMETER;
+ }
+
+ if (handle->port == NULL) {
+ scmirroring_error("INVALID_PORT(NULL) (0x%08x)", SCMIRRORING_ERROR_INVALID_PARAMETER);
+ return SCMIRRORING_ERROR_INVALID_PARAMETER;
+ }
+
+ memset(server_uri, 0x00, sizeof(server_uri));
+ snprintf(server_uri, sizeof(server_uri), "rtsp://%s:%s/wfd1.0/streamid=0", handle->ip, handle->port);
+
+ scmirroring_error("server_uri[%s]", server_uri);
+ printf("server_uri[%s]", server_uri);
+
+ ret = mm_wfd_sink_connect(handle->mm_handle, server_uri);
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_unprepare(scmirroring_primary_sink_h scmirroring_primary_sink)
+ {
+ 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");
+
+ ret = mm_wfd_sink_unprepare(handle->mm_handle);
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_destroy(scmirroring_primary_sink_h scmirroring_primary_sink)
+ {
+ 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");
+
+ ret = mm_wfd_sink_destroy(handle->mm_handle);
+
+ handle->mm_handle = 0;
+ handle->magic_num = 0;
+ SCMIRRORING_SAFE_FREE(handle->ip);
+ SCMIRRORING_SAFE_FREE(handle->port);
+ SCMIRRORING_SAFE_FREE(handle->scmirroring_sink_state_cb);
+ SCMIRRORING_SAFE_FREE(handle);
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_start(scmirroring_primary_sink_h scmirroring_primary_sink)
+ {
+ 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");
+
+ ret = mm_wfd_sink_start(handle->mm_handle);
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_disconnect(scmirroring_primary_sink_h scmirroring_primary_sink)
+ {
+ 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");
+
+ ret = mm_wfd_sink_disconnect(handle->mm_handle);
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_set_state_changed_cb(scmirroring_primary_sink_h scmirroring_primary_sink, scmirroring_sink_state_cb callback, void *user_data)
+ {
+ 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");
+ scmirroring_retvm_if(callback == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ if (handle->scmirroring_sink_state_cb == NULL) {
+ handle->scmirroring_sink_state_cb = (scmirroring_sink_state_cb_s *)calloc(1, sizeof(scmirroring_sink_state_cb_s));
+ if (handle->scmirroring_sink_state_cb == NULL) {
+ scmirroring_error("Error Set CB");
+ return SCMIRRORING_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ memset(handle->scmirroring_sink_state_cb, 0, sizeof(scmirroring_sink_state_cb_s));
+ }
+
+ handle->scmirroring_sink_state_cb->user_data = user_data;
+ handle->scmirroring_sink_state_cb->state_cb = callback;
+
+ ret = mm_wfd_sink_set_message_callback(handle->mm_handle, __mm_scmirroring_primary_sink_set_message_cb, handle);
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_unset_state_changed_cb(scmirroring_primary_sink_h scmirroring_primary_sink)
+ {
+ 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");
+
+ ret = mm_wfd_sink_set_message_callback(handle->mm_handle, NULL, NULL);
+
+ SCMIRRORING_SAFE_FREE(handle->scmirroring_sink_state_cb);
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_set_display(scmirroring_primary_sink_h scmirroring_primary_sink, scmirroring_display_type_e type, void *display_surface)
+ {
+ 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");
+ scmirroring_retvm_if(display_surface == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "display_surface is NULL");
+
+ if ((type != SCMIRRORING_DISPLAY_TYPE_OVERLAY) && (type != SCMIRRORING_DISPLAY_TYPE_EVAS)) {
+ scmirroring_error("Invalid display type [%d]", type);
+ return SCMIRRORING_ERROR_INVALID_PARAMETER;
+ }
+
+ scmirroring_debug("display type(%d)", type);
+
+ ret = mm_wfd_sink_set_attribute(handle->mm_handle, NULL, "display_surface_type", type, NULL);
+ if (ret != MM_ERROR_NONE) {
+ scmirroring_error("Fail to Set Display Type");
+ return __scmirroring_primary_sink_error_convert(__func__, ret);
+ }
+
+ ret = mm_wfd_sink_set_attribute(handle->mm_handle, NULL, "display_overlay", display_surface, sizeof(void *), NULL);
+ if (ret != MM_ERROR_NONE) {
+ scmirroring_error("Fail to Set Display Overlay");
+ return __scmirroring_primary_sink_error_convert(__func__, ret);
+ }
+
+ ret = mm_wfd_sink_set_attribute(handle->mm_handle, NULL, "display_visible", TRUE, NULL);
+ if (ret != MM_ERROR_NONE) {
+ scmirroring_error("Fail to Set Display Visible as TRUE");
+ return __scmirroring_primary_sink_error_convert(__func__, ret);
+ }
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_set_resolution(scmirroring_primary_sink_h scmirroring_primary_sink, int resolution)
+ {
+ 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 ((resolution < SCMIRRORING_RESOLUTION_UNKNOWN) || (resolution >= SCMIRRORING_RESOLUTION_MAX)) {
+ scmirroring_error("Invalid resolution : %d", resolution);
+ return SCMIRRORING_ERROR_INVALID_PARAMETER;
+ }
+
+ scmirroring_debug("resolution(%d)", resolution);
+ ret = mm_wfd_sink_set_resolution(handle->mm_handle, resolution);
+ if (ret != MM_ERROR_NONE) {
+ scmirroring_error("Fail to Set resolution");
+ return __scmirroring_primary_sink_error_convert(__func__, ret);
+ }
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_pause(scmirroring_primary_sink_h scmirroring_primary_sink)
+ {
+ 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");
+
+ ret = mm_wfd_sink_pause(handle->mm_handle);
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_resume(scmirroring_primary_sink_h scmirroring_primary_sink)
+ {
+ 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");
+
+ ret = mm_wfd_sink_resume(handle->mm_handle);
+
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
- scmirroring_primary_sink_s *handle = NULL;
++int scmirroring_primary_sink_get_negotiated_video_codec(scmirroring_primary_sink_h scmirroring_primary_sink, scmirroring_video_codec_e *codec)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ int mm_codec = MM_WFD_SINK_VIDEO_CODEC_NONE;
+
- scmirroring_retvm_if(scmirroring_primary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink* is NULL");
- scmirroring_retvm_if(codec == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "codec is NULL");
-
- handle = (scmirroring_primary_sink_s *)(*scmirroring_primary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
++ scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)scmirroring_primary_sink;
+ scmirroring_debug_fenter();
+
-int scmirroring_primary_sink_get_negotiated_video_resolution(scmirroring_primary_sink_h *scmirroring_primary_sink, int *width, int *height)
++ 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");
++ scmirroring_retvm_if(codec == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "codec is NULL");
+
+ *codec = SCMIRRORING_VIDEO_CODEC_NONE;
+
+ ret = mm_wfd_sink_get_negotiated_video_codec(handle->mm_handle, &mm_codec);
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ switch (mm_codec) {
+ case MM_WFD_SINK_VIDEO_CODEC_H264:
+ *codec = SCMIRRORING_VIDEO_CODEC_H264;
+ break;
+ default:
+ *codec = SCMIRRORING_VIDEO_CODEC_NONE;
+ break;
+ }
+
+ scmirroring_debug("codec: %d", *codec);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
- scmirroring_primary_sink_s *handle = NULL;
++int scmirroring_primary_sink_get_negotiated_video_resolution(scmirroring_primary_sink_h scmirroring_primary_sink, int *width, int *height)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
- 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 *)scmirroring_primary_sink;
+ scmirroring_debug_fenter();
+
- handle = (scmirroring_primary_sink_s *)(*scmirroring_primary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
- scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink is invalid handle");
-
++ 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");
+ scmirroring_retvm_if(width == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "width is NULL");
+ scmirroring_retvm_if(height == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "height is NULL");
+
-int scmirroring_primary_sink_get_negotiated_video_frame_rate(scmirroring_primary_sink_h *scmirroring_primary_sink, int *frame_rate)
+ *width = 0;
+ *height = 0;
+
+ ret = mm_wfd_sink_get_negotiated_video_resolution(handle->mm_handle, width, height);
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ scmirroring_debug("width: %d, height: %d", *width, *height);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
- scmirroring_primary_sink_s *handle = NULL;
++int scmirroring_primary_sink_get_negotiated_video_frame_rate(scmirroring_primary_sink_h scmirroring_primary_sink, int *frame_rate)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
- scmirroring_retvm_if(scmirroring_primary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink* is NULL");
- scmirroring_retvm_if(frame_rate == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "frame_rate is NULL");
-
- handle = (scmirroring_primary_sink_s *)(*scmirroring_primary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
++ scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)scmirroring_primary_sink;
+ scmirroring_debug_fenter();
+
-int scmirroring_primary_sink_get_negotiated_audio_codec(scmirroring_primary_sink_h *scmirroring_primary_sink, scmirroring_audio_codec_e *codec)
++ 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");
++ scmirroring_retvm_if(frame_rate == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "frame_rate is NULL");
+
+ *frame_rate = 0;
+
+ ret = mm_wfd_sink_get_negotiated_video_frame_rate(handle->mm_handle, frame_rate);
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ scmirroring_debug("frame rate: %d", *frame_rate);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
- scmirroring_primary_sink_s *handle = NULL;
++int scmirroring_primary_sink_get_negotiated_audio_codec(scmirroring_primary_sink_h scmirroring_primary_sink, scmirroring_audio_codec_e *codec)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ int mm_codec = MM_WFD_SINK_AUDIO_CODEC_NONE;
+
- scmirroring_retvm_if(scmirroring_primary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink* is NULL");
- scmirroring_retvm_if(codec == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "codec is NULL");
-
- handle = (scmirroring_primary_sink_s *)(*scmirroring_primary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
++ scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)scmirroring_primary_sink;
+ scmirroring_debug_fenter();
+
-int scmirroring_primary_sink_get_negotiated_audio_channel(scmirroring_primary_sink_h *scmirroring_primary_sink, int *channel)
++ 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");
++ scmirroring_retvm_if(codec == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "codec is NULL");
+
+ *codec = SCMIRRORING_AUDIO_CODEC_NONE;
+
+ ret = mm_wfd_sink_get_negotiated_audio_codec(handle->mm_handle, &mm_codec);
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ switch (mm_codec) {
+ case MM_WFD_SINK_AUDIO_CODEC_AAC:
+ *codec = SCMIRRORING_AUDIO_CODEC_AAC;
+ break;
+ case MM_WFD_SINK_AUDIO_CODEC_AC3:
+ *codec = SCMIRRORING_AUDIO_CODEC_AC3;
+ break;
+ case MM_WFD_SINK_AUDIO_CODEC_LPCM:
+ *codec = SCMIRRORING_AUDIO_CODEC_LPCM;
+ break;
+ default:
+ *codec = SCMIRRORING_AUDIO_CODEC_NONE;
+ break;
+ }
+
+ scmirroring_debug("codec: %d", *codec);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
- scmirroring_primary_sink_s *handle = NULL;
++int scmirroring_primary_sink_get_negotiated_audio_channel(scmirroring_primary_sink_h scmirroring_primary_sink, int *channel)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
- scmirroring_retvm_if(scmirroring_primary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink* is NULL");
- scmirroring_retvm_if(channel == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "channel is NULL");
-
- handle = (scmirroring_primary_sink_s *)(*scmirroring_primary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
++ scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)scmirroring_primary_sink;
+ scmirroring_debug_fenter();
+
-int scmirroring_primary_sink_get_negotiated_audio_sample_rate(scmirroring_primary_sink_h *scmirroring_primary_sink, int *sample_rate)
++ 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");
++ scmirroring_retvm_if(channel == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "channel is NULL");
+
+ *channel = 0;
+
+ ret = mm_wfd_sink_get_negotiated_audio_channel(handle->mm_handle, channel);
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ scmirroring_debug("channel: %d", *channel);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
- scmirroring_primary_sink_s *handle = NULL;
++int scmirroring_primary_sink_get_negotiated_audio_sample_rate(scmirroring_primary_sink_h scmirroring_primary_sink, int *sample_rate)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
- scmirroring_retvm_if(scmirroring_primary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink* is NULL");
- scmirroring_retvm_if(sample_rate == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "sample_rate is NULL");
-
- handle = (scmirroring_primary_sink_s *)(*scmirroring_primary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
++ scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)scmirroring_primary_sink;
+ scmirroring_debug_fenter();
+
-int scmirroring_primary_sink_get_negotiated_audio_bitwidth(scmirroring_primary_sink_h *scmirroring_primary_sink, int *bitwidth)
++ 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");
++ scmirroring_retvm_if(sample_rate == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "sample_rate is NULL");
+
+ *sample_rate = 0;
+
+ ret = mm_wfd_sink_get_negotiated_audio_sample_rate(handle->mm_handle, sample_rate);
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ scmirroring_debug("sample rate: %d", *sample_rate);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
- scmirroring_primary_sink_s *handle = NULL;
++int scmirroring_primary_sink_get_negotiated_audio_bitwidth(scmirroring_primary_sink_h scmirroring_primary_sink, int *bitwidth)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
- scmirroring_retvm_if(scmirroring_primary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink* is NULL");
- scmirroring_retvm_if(bitwidth == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "bitwidth is NULL");
-
- handle = (scmirroring_primary_sink_s *)(*scmirroring_primary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
++ scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)scmirroring_primary_sink;
+ scmirroring_debug_fenter();
+
- scmirroring_retvm_if(scmirroring_primary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_primary_sink* is NULL");
- scmirroring_retvm_if(state == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "state is NULL");
++ 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");
++ scmirroring_retvm_if(bitwidth == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "bitwidth is NULL");
+
+ *bitwidth = 0;
+
+ ret = mm_wfd_sink_get_negotiated_audio_bitwidth(handle->mm_handle, bitwidth);
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ scmirroring_debug("bitwidth: %d", *bitwidth);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_sink_get_current_state(scmirroring_primary_sink_h scmirroring_primary_sink, scmirroring_sink_state_e *state)
+ {
+ int result = MM_ERROR_NONE;
+ int mm_state = MM_WFD_SINK_STATE_NONE;
+ scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)(scmirroring_primary_sink);
+
+ scmirroring_debug_fenter();
- scmirroring_debug("message key : %s , value : %s", response[1], response[2]);
++ 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");
++ scmirroring_retvm_if(state == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "state is NULL");
++
+
+ result = mm_wfd_sink_get_current_state(handle->mm_handle, &mm_state);
+ if (result == MM_ERROR_NONE) {
+ *state = __scmirroring_primary_sink_state_convert(mm_state);
+ scmirroring_debug("ScreenMirroring current state is [%d]", *state);
+ }
+ scmirroring_debug_fleave();
+ return __scmirroring_primary_sink_error_convert(__func__, result);
+ }
+
+ int scmirroring_primary_sink_set_coupled_sink(scmirroring_primary_sink_h scmirroring_primary_sink, gchar* address)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ scmirroring_debug_fenter();
+ scmirroring_primary_sink_s *handle = (scmirroring_primary_sink_s *)scmirroring_primary_sink;
+
+ 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");
+ scmirroring_retvm_if(address == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "MAC address is invalid");
+
+ scmirroring_debug("address [%s]", address);
+
+ ret = mm_wfd_sink_set_coupled_sink(handle->mm_handle, address);
+ if (ret != MM_ERROR_NONE) {
+ scmirroring_error("Fail to Set Coupled IP");
+ return __scmirroring_primary_sink_error_convert(__func__, ret);
+ }
+ ret = __scmirroring_primary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ 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;
+
+ if (scmirroring == NULL) {
+ scmirroring_error("SCMIRRORING is NULL");
+ return FALSE;
+ }
+
+ scmirroring_state_cb_s *cb_info = scmirroring->scmirroring_state_cb;
+
+ if ((cb_info != NULL) && (cb_info->state_cb != NULL)) {
+ scmirroring_debug("Calling user callback(error: %d, status: %d)", cb_info->error_code, cb_info->src_state);
+ cb_info->state_cb(cb_info->error_code, cb_info->src_state, cb_info->user_data);
+ }
+
+ if (cb_info != NULL && cb_info->src_state == SCMIRRORING_STATE_NULL) {
+ SCMIRRORING_SAFE_FREE(scmirroring->ip);
+ SCMIRRORING_SAFE_FREE(scmirroring->port);
+ SCMIRRORING_SAFE_FREE(scmirroring->scmirroring_state_cb);
+
+ g_io_channel_shutdown(scmirroring->channel, FALSE, NULL);
+ g_io_channel_unref(scmirroring->channel);
+
+ SCMIRRORING_SAFE_G_FREE(scmirroring->sock_path);
+ SCMIRRORING_SAFE_FREE(scmirroring);
+ }
+
+ return FALSE;
+ }
+
+ static int __scmirroring_primary_src_send_cmd_to_server(scmirroring_primary_sink_s *scmirroring, const char *cmd)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ char *_cmd = NULL;
+ int _cmdLen = 0;
+
+ scmirroring_retvm_if(scmirroring == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring is NULL");
+ scmirroring_retvm_if(cmd == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "cmd is NULL");
+
+ _cmd = g_strdup(cmd);
+ if (_cmd == NULL) {
+ scmirroring_error("Out of memory for command buffer");
+ return SCMIRRORING_ERROR_OUT_OF_MEMORY;
+ }
+
+ _cmdLen = strlen(_cmd) + 1;
+ if (write(scmirroring->sock, _cmd, _cmdLen) != _cmdLen) {
+ char buf[255] = {0, };
+ strerror_r(errno, buf, sizeof(buf));
+ scmirroring_error("sendto failed [%s]", buf);
+ ret = SCMIRRORING_ERROR_INVALID_OPERATION;
+ } else {
+ scmirroring_debug("Sent message [%s] successfully", _cmd);
+ }
+
+ SCMIRRORING_SAFE_G_FREE(_cmd);
+
+ return ret;
+ }
+
+ static int __miracast_server_launch(scmirroring_primary_sink_s *scmirroring)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ GDBusProxy *proxy = NULL;
+ GVariant *reg = NULL;
+ GDBusConnection *conn = NULL;
+ GError *error = NULL;
+
+ #if !GLIB_CHECK_VERSION(2, 35, 0)
+ g_type_init();
+ #endif
+
+ scmirroring_debug("-----------socket connect failed it means server is not yet started------------");
+ scmirroring_debug("going to start miracast server");
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (error) {
+ scmirroring_error("Failed to get dbus connection: %s", error->message);
+ g_error_free(error);
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+ }
+
+ gchar *name = NULL;
+ gchar *if_name = NULL;
+ gchar *obj_path = NULL;
+
+ if (scmirroring->server_name) {
+ name = g_strdup_printf("org.tizen.%s.server", scmirroring->server_name);
+ if_name = g_strdup_printf("org.tizen.%s.server", scmirroring->server_name);
+ obj_path = g_strdup_printf("/org/tizen/%s/server", scmirroring->server_name);
+ } else {
+ name = g_strdup("org.tizen.scmirroring.server");
+ if_name = g_strdup("org.tizen.scmirroring.server");
+ obj_path = g_strdup("/org/tizen/scmirroring/server");
+ }
+
+ scmirroring_debug("Server Name : %s", name);
+
+ proxy = g_dbus_proxy_new_sync(conn,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ NULL,
+ name,
+ obj_path,
+ if_name,
+ NULL,
+ &error);
+ g_free(name);
+ g_free(if_name);
+ g_free(obj_path);
+ g_object_unref(conn);
+ if (proxy == NULL) {
+ scmirroring_error("g_dbus_proxy_new_sync failed : %s", error->message);
+ g_error_free(error);
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+ }
+
+ reg = g_dbus_proxy_call_sync(proxy, "launch_method", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ g_object_unref(proxy);
+
+ if (reg) {
+ g_variant_unref(reg);
+ reg = NULL;
+ }
+ if (error) {
+ scmirroring_error("g_dbus_proxy_call_sync failed : %s", error->message);
+ g_error_free(error);
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+ }
+
+ scmirroring_debug("Miracast server is launched successfully");
+
+ return ret;
+ }
+
+ /*
+ * Application - miracast server message
+ * 1. Response Message from miracast server
+ * [Error:Status]
+ * - OK:LISTENING
+ * - OK:CONNECTED
+ * - OK:STOP
+ * - OK:DESTROY
+ *
+ * 2. Request Message from application to miracast server
+ * - START [ip addr:port]
+ * - SET [sth]
+ */
+
+ static int __scmirroring_primary_src_get_error(gchar *str)
+ {
+ if (g_strrstr(str, "OK"))
+ return SCMIRRORING_ERROR_NONE;
+ else if (g_strrstr(str, "FAIL"))
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+
+ return SCMIRRORING_ERROR_NONE;
+ }
+
+ static int __scmirroring_primary_src_get_status(gchar *str)
+ {
+ if (g_strrstr(str, "LISTENING"))
+ return SCMIRRORING_STATE_CONNECTION_WAIT;
+ else if (g_strrstr(str, "CONNECTED"))
+ return SCMIRRORING_STATE_CONNECTED;
+ else if (g_strrstr(str, "PLAYING"))
+ return SCMIRRORING_STATE_PLAYING;
+ else if (g_strrstr(str, "SET"))
+ return SCMIRRORING_STATE_READY;
+ else if (g_strrstr(str, SCMIRRORING_STATE_CMD_PAUSE))
+ return SCMIRRORING_STATE_PAUSED;
+ else if (g_strrstr(str, SCMIRRORING_STATE_CMD_RESUME))
+ return SCMIRRORING_STATE_PLAYING;
+ else if (g_strrstr(str, SCMIRRORING_STATE_CMD_STOP))
+ return SCMIRRORING_STATE_TEARDOWN;
+ else if (g_strrstr(str, SCMIRRORING_STATE_CMD_DESTROY))
+ return SCMIRRORING_STATE_NULL;
+
+ 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;
+ if (cb_info) {
+ cb_info->error_code = error_code;
+ cb_info->src_state = state;
+
+ GSource *src_user_cb = NULL;
+ src_user_cb = g_idle_source_new();
+ g_source_set_callback(src_user_cb, (GSourceFunc)__scmirroring_primary_src_callback_call, scmirroring, NULL);
+ g_source_attach(src_user_cb, g_main_context_get_thread_default());
+ } else {
+ scmirroring_error("There is no callback");
+ }
+
+ return;
+ }
+
+ static void __scmirroring_primary_src_interpret(scmirroring_primary_sink_s *scmirroring, char *buf)
+ {
+ scmirroring_debug("Received : %s", buf);
+
+ int error_code = SCMIRRORING_ERROR_INVALID_OPERATION;
+ int src_state = SCMIRRORING_STATE_CREATED;
+ gchar **response;
+ response = g_strsplit(buf, ":", 0);
+
+ scmirroring_debug("error: %s, status: %s", response[0], response[1]);
+
+ /* 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]);
+
+ 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);
+ }
+ /* 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]);
- g_print("yes , coupled_sink_address");
++ 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])) {
- scmirroring_error("scmirroring_primary_src_set_coupling_mode1");
++ scmirroring_primary_sink_set_coupled_sink(scmirroring, response[2]);
+ scmirroring_primary_sink_set_coupled_sink_status(scmirroring, 1);
+ }
+ }
+ g_strfreev(response);
+
+ return;
+ }
+
+ gboolean __scmirroring_primary_src_read_cb(GIOChannel *src, GIOCondition condition, gpointer data)
+ {
+ char buf[MAX_MSG_LEN + 1];
+ gsize read;
+
+ scmirroring_primary_sink_s *_scmirroring = (scmirroring_primary_sink_s *)data;
+
+ if (condition & G_IO_IN) {
+ g_io_channel_read_chars(_scmirroring->channel, buf, MAX_MSG_LEN, &read, NULL);
+ if (read == 0) {
+ scmirroring_error("Read 0 bytes");
+ return FALSE;
+ } else {
+ scmirroring_debug("Read %" G_GSIZE_FORMAT " bytes", read);
+ }
+
+ gsize i = 0;
+ gsize 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_primary_src_interpret(_scmirroring, str);
+ if (idx >= read) break;
+ }
+ } else if (condition & G_IO_ERR) {
+ scmirroring_error("got G_IO_ERR");
+ return FALSE;
+ } else if (condition & G_IO_HUP) {
+ scmirroring_error("got G_IO_HUP");
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ static int __scmirroring_primary_src_send_set_cm(scmirroring_primary_sink_h scmirroring)
+ {
+ /* Set connection 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 CM %d", _scmirroring->connect_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_set_ip(scmirroring_primary_sink_h scmirroring)
+ {
+ /* Set IP and Port to server */
+ char *cmd = NULL;
+ int ret = SCMIRRORING_ERROR_NONE;
+ scmirroring_primary_sink_s *_scmirroring = (scmirroring_primary_sink_s *)scmirroring;
+
+ cmd = g_strdup_printf("SET IP %s:%s", _scmirroring->ip, _scmirroring->port);
+ 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_set_reso(scmirroring_primary_sink_h scmirroring)
+ {
+ /* Set resolution 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 RESO %d", _scmirroring->resolution);
+ 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_set_multisink(scmirroring_primary_sink_h scmirroring)
+ {
+ /* Set resolution 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 MULTISINK %d", _scmirroring->multisink);
+ 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_set_direct_streaming(scmirroring_primary_sink_h scmirroring)
+ {
+ /* Set resolution to miracast server */
+ char *cmd = NULL;
+ int ret = SCMIRRORING_ERROR_NONE;
+ scmirroring_primary_sink_s *_scmirroring = (scmirroring_primary_sink_s *)scmirroring;
+
+ scmirroring_retvm_if(_scmirroring == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ cmd = g_strdup_printf("SET STREAMING %d %s", _scmirroring->direct_streaming, _scmirroring->filesrc);
+ ret = __scmirroring_primary_src_send_cmd_to_server(_scmirroring, cmd);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ SCMIRRORING_SAFE_FREE(cmd);
+ scmirroring_error("Failed to enable direct streaming [%d]", ret);
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+ }
+
+ SCMIRRORING_SAFE_FREE(cmd);
+
+ 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 */
+ char *cmd = NULL;
+ int ret = SCMIRRORING_ERROR_NONE;
+ scmirroring_primary_sink_s *_scmirroring = (scmirroring_primary_sink_s *)scmirroring;
+ const char *tr = _scmirroring->av_transport == SCMIRRORING_AV_TRANSPORT_UDP ? "UDP" : "TCP";
+
+ cmd = g_strdup_printf("SWITCH %s", tr);
+ 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;
+ }
+
+ int scmirroring_primary_src_create(scmirroring_primary_sink_h *scmirroring)
+ {
+ CHECK_FEATURE_SUPPORTED(WIFIDIRECT_DISPLAY_FEATURE);
+
+ int ret = SCMIRRORING_ERROR_NONE;
+ scmirroring_primary_sink_s *_scmirroring = NULL;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(scmirroring == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ _scmirroring = (scmirroring_primary_sink_s *)calloc(1, sizeof(scmirroring_primary_sink_s));
+ scmirroring_retvm_if(_scmirroring == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
+
+ _scmirroring->magic_num = SCMIRRORING_MAGIC_NUMBER;
+ _scmirroring->ip = NULL;
+ _scmirroring->port = NULL;
+ _scmirroring->filesrc = NULL;
+ _scmirroring->connected = NOT_CONNECTED_TO_SERVER;
+ _scmirroring->use_hdcp = TRUE;
+ _scmirroring->resolution = 0;
+ _scmirroring->connect_mode = SCMIRRORING_CONNECTION_WIFI_DIRECT;
+ _scmirroring->scmirroring_state_cb = NULL;
+ _scmirroring->sock = -1;
+ _scmirroring->channel = NULL;
+ _scmirroring->sock_path = NULL;
+ _scmirroring->current_state = SCMIRRORING_STATE_CREATED;
+ _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;
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_set_connection_mode(scmirroring_primary_sink_h scmirroring, scmirroring_connection_mode_e connect_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");
+
+ if ((connect_mode < SCMIRRORING_CONNECTION_WIFI_DIRECT) || (connect_mode >= SCMIRRORING_CONNECTION_MAX)) {
+ scmirroring_error("INVALID Connection mode : %d", connect_mode);
+ return SCMIRRORING_ERROR_INVALID_PARAMETER;
+ }
+
+ _scmirroring->connect_mode = connect_mode;
+
+ if (_scmirroring->connected)
+ ret = __scmirroring_primary_src_send_set_cm(_scmirroring);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_set_state_changed_cb(scmirroring_primary_sink_h scmirroring, scmirroring_state_cb callback, void *user_data)
+ {
+ 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_retvm_if(callback == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ 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;
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_unset_state_changed_cb(scmirroring_primary_sink_h scmirroring)
+ {
+ 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");
+
+ 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_primary_src_set_ip_and_port(scmirroring_primary_sink_h scmirroring, const char *ip, const char *port)
+ {
+ 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_retvm_if(!STRING_VALID(ip), SCMIRRORING_ERROR_INVALID_PARAMETER, "INVALID IP");
+ scmirroring_retvm_if(!STRING_VALID(port), SCMIRRORING_ERROR_INVALID_PARAMETER, "INVALID PORT");
+
+ SCMIRRORING_SAFE_FREE(_scmirroring->ip);
+ _scmirroring->ip = strdup(ip);
+ scmirroring_retvm_if(_scmirroring->ip == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Out of memory for IP");
+
+ SCMIRRORING_SAFE_FREE(_scmirroring->port);
+ _scmirroring->port = strdup(port);
+ scmirroring_retvm_if(_scmirroring->port == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Out of memory for PORT");
+
+ if (_scmirroring->connected)
+ ret = __scmirroring_primary_src_send_set_ip(_scmirroring);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_set_resolution(scmirroring_primary_sink_h scmirroring, scmirroring_resolution_e resolution)
+ {
+ 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");
+
+ if ((resolution < SCMIRRORING_RESOLUTION_1920x1080_P30) || (resolution >= SCMIRRORING_RESOLUTION_MAX)) {
+ scmirroring_error("INVALID resolution : %d", resolution);
+ return SCMIRRORING_ERROR_INVALID_PARAMETER;
+ }
+
+ _scmirroring->resolution = resolution;
+
+ if (_scmirroring->connected)
+ ret = __scmirroring_primary_src_send_set_reso(_scmirroring);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_set_server_name(scmirroring_primary_sink_h scmirroring, const char *name)
+ {
+ 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_SAFE_G_FREE(_scmirroring->server_name);
+ _scmirroring->server_name = g_strdup(name);
+ scmirroring_retvm_if(_scmirroring->server_name == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Out of memory for server name");
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_set_multisink_ability(scmirroring_primary_sink_h scmirroring, scmirroring_multisink_e multisink)
+ {
+ 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");
+
+ if ((multisink < SCMIRRORING_MULTISINK_DISABLE) || (multisink > SCMIRRORING_MULTISINK_ENABLE)) {
+ scmirroring_error("INVALID multisink ability : %d", multisink);
+ return SCMIRRORING_ERROR_INVALID_PARAMETER;
+ }
+
+ _scmirroring->multisink = multisink;
+
+ if (_scmirroring->connected)
+ ret = __scmirroring_primary_src_send_set_multisink(_scmirroring);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_connect(scmirroring_primary_sink_h scmirroring)
+ {
+ CHECK_FEATURE_SUPPORTED(WIFIDIRECT_DISPLAY_FEATURE);
+
+ 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 };
+ char buf[255] = {0, };
+
+ 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_retvm_if(_scmirroring->connected == CONNECTED_TO_SERVER, SCMIRRORING_ERROR_NONE, "already connected to server.");
+
+ /*Create TCP Socket*/
+ if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ scmirroring_error("socket failed: %s", buf);
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+ }
+
+ if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
+ strerror_r(errno, buf, sizeof(buf));
+ scmirroring_error("setsockopt failed: %s", buf);
+ close(sock);
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+ }
+
+ channel = g_io_channel_unix_new(sock);
+ if (channel == NULL) {
+ strerror_r(errno, buf, sizeof(buf));
+ scmirroring_error("g_io_channel_unix_new failed: %s", buf);
+ }
+
+ g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
+
+ _scmirroring->sock = sock;
+ _scmirroring->channel = channel;
+ SCMIRRORING_SAFE_G_FREE(_scmirroring->sock_path);
+ _scmirroring->sock_path = g_strdup("/tmp/.miracast_ipc_rtspserver");
+
+ /* Connecting to the miracast server */
+ memset(&serv_addr, 0, sizeof(struct sockaddr_un));
+ serv_addr.sun_family = AF_UNIX;
+ strncpy(serv_addr.sun_path, _scmirroring->sock_path, sizeof(serv_addr.sun_path));
+ serv_addr.sun_path[sizeof(serv_addr.sun_path) - 1] = '\0';
+
+ try:
+ scmirroring_debug("Trying to connect to the miracast server");
+ if (connect(_scmirroring->sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+ /* Once failed to connect, try to launch miracast server */
+ if (retry == 0) {
+ ret = __miracast_server_launch(_scmirroring);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ SCMIRRORING_SAFE_G_FREE(_scmirroring->sock_path);
+ scmirroring_error("__miracast_server_launch error : %d", ret);
+ return ret;
+ }
+ retry++;
+ goto try;
+ } else {
+ scmirroring_debug("Trying to connect failed");
+ if (retry < 5) {
+ scmirroring_debug("Trying to connect again..");
+ retry++;
+ usleep(10000);
+ goto try;
+ }
+
+ strerror_r(errno, buf, sizeof(buf));
+ scmirroring_error("Connect error : %s", buf);
+ close(_scmirroring->sock);
+ _scmirroring->sock = -1;
+ SCMIRRORING_SAFE_G_FREE(_scmirroring->sock_path);
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+ }
+ } else {
+ scmirroring_debug("Connected successfully");
+ }
+
+ /* Create new channel to watch tcp socket */
+ GSource *source = NULL;
+ source = g_io_create_watch(_scmirroring->channel, G_IO_IN | G_IO_HUP | G_IO_ERR);
+ int source_id = -1;
+
+ /* Set callback to be called when socket is readable */
+ g_source_set_callback(source, (GSourceFunc)__scmirroring_primary_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_primary_src_set_callback_info(_scmirroring, SCMIRRORING_ERROR_NONE, SCMIRRORING_STATE_READY);
+
+ if ((_scmirroring->ip != NULL) || (_scmirroring->port != NULL)) {
+ ret = __scmirroring_primary_src_send_set_ip(_scmirroring);
+ ret = __scmirroring_primary_src_send_set_cm(_scmirroring);
+ ret = __scmirroring_primary_src_send_set_reso(_scmirroring);
+ }
+
+ if (_scmirroring->multisink == SCMIRRORING_MULTISINK_ENABLE)
+ ret = __scmirroring_primary_src_send_set_multisink(_scmirroring);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_disconnect(scmirroring_primary_sink_h scmirroring)
+ {
+ 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_retvm_if(_scmirroring->connected == NOT_CONNECTED_TO_SERVER, SCMIRRORING_ERROR_NONE, "Already disconnected");
+
+ ret = __scmirroring_primary_src_send_cmd_to_server(_scmirroring, SCMIRRORING_STATE_CMD_DESTROY);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ scmirroring_error("Failed to destroy miracast server [%d]", ret);
+
+ 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_G_FREE(_scmirroring->sock_path);
+ _scmirroring->connected = NOT_CONNECTED_TO_SERVER;
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_start(scmirroring_primary_sink_h scmirroring)
+ {
+ 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");
+
+ ret = __scmirroring_primary_src_send_cmd_to_server(_scmirroring, SCMIRRORING_STATE_CMD_START);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ scmirroring_error("Failed to start [%d]", ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_pause(scmirroring_primary_sink_h scmirroring)
+ {
+ 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");
+
+ ret = __scmirroring_primary_src_send_cmd_to_server(_scmirroring, SCMIRRORING_STATE_CMD_PAUSE);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ scmirroring_error("Failed to pause [%d]", ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_resume(scmirroring_primary_sink_h scmirroring)
+ {
+ 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");
+
+ ret = __scmirroring_primary_src_send_cmd_to_server(_scmirroring, SCMIRRORING_STATE_CMD_RESUME);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ scmirroring_error("Failed to resume [%d]", ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_set_direct_streaming(scmirroring_primary_sink_h scmirroring_primary_src,
+ scmirroring_direct_streaming_e enable, const char* uri_srcname)
+ {
+ CHECK_FEATURE_SUPPORTED(WIFIDIRECT_DISPLAY_FEATURE);
+
+ int ret = SCMIRRORING_ERROR_NONE;
+ int len = 0;
+ scmirroring_primary_sink_s *_scmirroring = (scmirroring_primary_sink_s *)scmirroring_primary_src;
+
+ 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_retvm_if(!STRING_VALID(uri_srcname), SCMIRRORING_ERROR_INVALID_PARAMETER, "INVALID URI_SRCNAME");
+ _scmirroring->direct_streaming = enable;
+
+ len = strlen(uri_srcname);
+ if (_scmirroring->filesrc != NULL) {
+ g_free(_scmirroring->filesrc);
+ _scmirroring->filesrc = NULL;
+ }
+ _scmirroring->filesrc = g_strndup(uri_srcname, len);
+
+ if ((_scmirroring->filesrc == NULL)) {
+ scmirroring_error("OUT_OF_MEMORY");
+ return SCMIRRORING_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = __scmirroring_primary_src_send_set_direct_streaming(_scmirroring);
+
+ scmirroring_debug_fleave();
+
+ 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_mode2");
-
+
+ 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;
- scmirroring_error("scmirroring_primary_src_set_coupling_mode3");
+
- ret = __scmirroring_primary_src_send_set_coupling_mode(_scmirroring);
- scmirroring_error("scmirroring_primary_src_set_coupling_mode4");
++ _scmirroring->coupling_mode = coupling_mode;
+
+ if (_scmirroring->connected)
++ ret = __scmirroring_primary_src_send_set_coupling_mode(_scmirroring);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_AV_transport_switch(scmirroring_primary_sink_h scmirroring,
+ scmirroring_av_transport_e transport)
+ {
+ 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");
+
+ if (transport < SCMIRRORING_AV_TRANSPORT_UDP || transport > SCMIRRORING_AV_TRANSPORT_TCP) {
+ scmirroring_error("Invalid transport");
+ return SCMIRRORING_ERROR_INVALID_PARAMETER;
+ }
+
+ _scmirroring->av_transport = transport;
+
+ ret = __scmirroring_primary_src_send_switch_transport(_scmirroring);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_stop(scmirroring_primary_sink_h scmirroring)
+ {
+ 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");
+
+ ret = __scmirroring_primary_src_send_cmd_to_server(_scmirroring, SCMIRRORING_STATE_CMD_STOP);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ scmirroring_error("Failed to be stop [%d]", ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_primary_src_destroy(scmirroring_primary_sink_h scmirroring)
+ {
+ 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");
+
+ if (_scmirroring->connected == CONNECTED_TO_SERVER) {
+ ret = scmirroring_primary_src_disconnect(scmirroring);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ scmirroring_error("Failed to disconnect server [%d]", ret);
+ }
+
+ SCMIRRORING_SAFE_FREE(_scmirroring->scmirroring_state_cb);
+ SCMIRRORING_SAFE_G_FREE(_scmirroring->server_name);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
--- /dev/null
-* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ /*
-int scmirroring_secondary_sink_get_negotiated_audio_codec(scmirroring_secondary_sink_h *scmirroring_secondary_sink, scmirroring_audio_codec_e *codec)
++* Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ #include <stdio.h>
+ #include <mmf/mm_wfd_sink.h>
+ #include <scmirroring_secondary_sink.h>
+ #include <scmirroring_private.h>
+
+ static scmirroring_error_e __scmirroring_secondary_sink_error_convert(const char *func, int error)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ const char *errorstr = NULL;
+
+ switch (error) {
+ case MM_ERROR_NONE:
+ ret = SCMIRRORING_ERROR_NONE;
+ errorstr = "ERROR_NONE";
+ break;
+
+ case MM_ERROR_WFD_NO_FREE_SPACE:
+ ret = SCMIRRORING_ERROR_OUT_OF_MEMORY;
+ errorstr = "OUT_OF_MEMORY";
+ break;
+
+ case MM_ERROR_WFD_NOT_INITIALIZED:
+ case MM_ERROR_COMMON_INVALID_ATTRTYPE:
+ case MM_ERROR_COMMON_INVALID_PERMISSION:
+ case MM_ERROR_COMMON_OUT_OF_ARRAY:
+ case MM_ERROR_COMMON_OUT_OF_RANGE:
+ case MM_ERROR_COMMON_ATTR_NOT_EXIST:
+ ret = SCMIRRORING_ERROR_INVALID_PARAMETER;
+ errorstr = "INVALID_PARAMETER";
+ break;
+
+ default:
+ ret = SCMIRRORING_ERROR_INVALID_OPERATION;
+ errorstr = "INVALID_OPERATION";
+ }
+
+ if (ret != SCMIRRORING_ERROR_NONE)
+ scmirroring_error("[%s] %s (0x%08x) : core frameworks error code(0x%08x)", func, errorstr, ret, error);
+ else
+ scmirroring_debug("[%s] %s", func, errorstr);
+
+ return ret;
+ }
+
+ static scmirroring_sink_state_e __scmirroring_secondary_sink_state_convert(MMWFDSinkStateType mm_state)
+ {
+ scmirroring_sink_state_e state = SCMIRRORING_SINK_STATE_NONE;
+
+ switch (mm_state) {
+ case MM_WFD_SINK_STATE_NONE:
+ state = SCMIRRORING_SINK_STATE_NONE;
+ break;
+ case MM_WFD_SINK_STATE_NULL:
+ state = SCMIRRORING_SINK_STATE_NULL;
+ break;
+ case MM_WFD_SINK_STATE_PREPARED:
+ state = SCMIRRORING_SINK_STATE_PREPARED;
+ break;
+ case MM_WFD_SINK_STATE_CONNECTED:
+ state = SCMIRRORING_SINK_STATE_CONNECTED;
+ break;
+ case MM_WFD_SINK_STATE_PLAYING:
+ state = SCMIRRORING_SINK_STATE_PLAYING;
+ break;
+ case MM_WFD_SINK_STATE_PAUSED:
+ state = SCMIRRORING_SINK_STATE_PAUSED;
+ break;
+ case MM_WFD_SINK_STATE_DISCONNECTED:
+ state = SCMIRRORING_SINK_STATE_DISCONNECTED;
+ break;
+ default:
+ state = SCMIRRORING_SINK_STATE_NONE;
+ break;
+ }
+
+ return state;
+ }
+
+ void __mm_scmirroring_secondary_sink_set_message_cb(int error_type, MMWFDSinkStateType state_type, void *uData)
+ {
+ scmirroring_error_e error = __scmirroring_secondary_sink_error_convert(__func__, error_type);
+ scmirroring_sink_state_e state = __scmirroring_secondary_sink_state_convert(state_type);
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)uData;
+
+ /* call application callback */
+ if (handle && handle->scmirroring_sink_state_cb && handle->scmirroring_sink_state_cb->state_cb)
+ handle->scmirroring_sink_state_cb->state_cb(error, state, handle->scmirroring_sink_state_cb->user_data);
+
+ return;
+ }
+
+ int scmirroring_secondary_sink_create(scmirroring_secondary_sink_h *scmirroring_secondary_sink)
+ {
+ CHECK_FEATURE_SUPPORTED(WIFIDIRECT_DISPLAY_FEATURE);
+
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)calloc(1, sizeof(scmirroring_secondary_sink_s));
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Fail to allocate memory for handle");
+
+ handle->mm_handle = 0;
+ handle->ip = NULL;
+ handle->port = NULL;
+ handle->use_hdcp = TRUE;
+ handle->scmirroring_sink_state_cb = NULL;
+ handle->magic_num = SCMIRRORING_MAGIC_NUMBER;
+
+ ret = mm_wfd_sink_create_r2(&handle->mm_handle);
+ if (ret != MM_ERROR_NONE) {
+ SCMIRRORING_SAFE_FREE(handle);
+ scmirroring_error("Fail to Create");
+ return __scmirroring_secondary_sink_error_convert(__func__, ret);
+ }
+
+ *scmirroring_secondary_sink = (scmirroring_secondary_sink_h)handle;
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_secondary_sink_set_ip_and_port(scmirroring_secondary_sink_h scmirroring_secondary_sink, const char *ip, const char *port)
+ {
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+ scmirroring_retvm_if(ip == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "ip is NULL");
+ scmirroring_retvm_if(port == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "port is NULL");
+
+ scmirroring_debug("ip[%s] port[%s]", ip, port);
+
+ SCMIRRORING_SAFE_FREE(handle->ip);
+ handle->ip = strdup(ip);
+ scmirroring_retvm_if(handle->ip == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Out of memory for ip");
+
+ SCMIRRORING_SAFE_FREE(handle->port);
+ handle->port = strdup(port);
+ scmirroring_retvm_if(handle->port == NULL, SCMIRRORING_ERROR_OUT_OF_MEMORY, "Out of memory for port");
+
+ scmirroring_debug_fleave();
+
+ return SCMIRRORING_ERROR_NONE;
+ }
+
+ int scmirroring_secondary_sink_prepare(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+ ret = mm_wfd_sink_prepare(handle->mm_handle);
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_secondary_sink_connect(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ char server_uri[255] = {0, };
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+ if (handle->ip == NULL) {
+ scmirroring_error("INVALID_IP(NULL) (0x%08x)", SCMIRRORING_ERROR_INVALID_PARAMETER);
+ return SCMIRRORING_ERROR_INVALID_PARAMETER;
+ }
+
+ if (handle->port == NULL) {
+ scmirroring_error("INVALID_PORT(NULL) (0x%08x)", SCMIRRORING_ERROR_INVALID_PARAMETER);
+ return SCMIRRORING_ERROR_INVALID_PARAMETER;
+ }
+
+ memset(server_uri, 0x00, sizeof(server_uri));
+ snprintf(server_uri, sizeof(server_uri), "rtsp://%s:%s/wfd1.0/streamid=0", handle->ip, handle->port);
+
+ scmirroring_error("server_uri[%s]", server_uri);
+ printf("server_uri[%s]", server_uri);
+
+ ret = mm_wfd_sink_connect(handle->mm_handle, server_uri);
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_secondary_sink_unprepare(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+ ret = mm_wfd_sink_unprepare(handle->mm_handle);
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_secondary_sink_destroy(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+ ret = mm_wfd_sink_destroy(handle->mm_handle);
+
+ handle->mm_handle = 0;
+ handle->magic_num = 0;
+ SCMIRRORING_SAFE_FREE(handle->ip);
+ SCMIRRORING_SAFE_FREE(handle->port);
+ SCMIRRORING_SAFE_FREE(handle->scmirroring_sink_state_cb);
+ SCMIRRORING_SAFE_FREE(handle);
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_secondary_sink_start(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+ ret = mm_wfd_sink_start(handle->mm_handle);
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_secondary_sink_disconnect(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+ ret = mm_wfd_sink_disconnect(handle->mm_handle);
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_secondary_sink_set_state_changed_cb(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_sink_state_cb callback, void *user_data)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+ scmirroring_retvm_if(callback == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ if (handle->scmirroring_sink_state_cb == NULL) {
+ handle->scmirroring_sink_state_cb = (scmirroring_sink_state_cb_s *)calloc(1, sizeof(scmirroring_sink_state_cb_s));
+ if (handle->scmirroring_sink_state_cb == NULL) {
+ scmirroring_error("Error Set CB");
+ return SCMIRRORING_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ memset(handle->scmirroring_sink_state_cb, 0, sizeof(scmirroring_sink_state_cb_s));
+ }
+
+ handle->scmirroring_sink_state_cb->user_data = user_data;
+ handle->scmirroring_sink_state_cb->state_cb = callback;
+
+ ret = mm_wfd_sink_set_message_callback(handle->mm_handle, __mm_scmirroring_secondary_sink_set_message_cb, handle);
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_secondary_sink_unset_state_changed_cb(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+ ret = mm_wfd_sink_set_message_callback(handle->mm_handle, NULL, NULL);
+
+ SCMIRRORING_SAFE_FREE(handle->scmirroring_sink_state_cb);
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+
+ int scmirroring_secondary_sink_pause(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+ ret = mm_wfd_sink_pause(handle->mm_handle);
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_secondary_sink_resume(scmirroring_secondary_sink_h scmirroring_secondary_sink)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_debug_fenter();
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+ ret = mm_wfd_sink_resume(handle->mm_handle);
+
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+
- scmirroring_secondary_sink_s *handle = NULL;
++int scmirroring_secondary_sink_get_negotiated_audio_codec(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_audio_codec_e *codec)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ int mm_codec = MM_WFD_SINK_AUDIO_CODEC_NONE;
+
- scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
- scmirroring_retvm_if(codec == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "codec is NULL");
-
- handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
++ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s*)scmirroring_secondary_sink;
+ scmirroring_debug_fenter();
+
-int scmirroring_secondary_sink_get_negotiated_audio_channel(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *channel)
++ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
++ scmirroring_retvm_if(codec == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "codec is NULL");
+
+ *codec = SCMIRRORING_AUDIO_CODEC_NONE;
+
+ ret = mm_wfd_sink_get_negotiated_audio_codec(handle->mm_handle, &mm_codec);
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ switch (mm_codec) {
+ case MM_WFD_SINK_AUDIO_CODEC_AAC:
+ *codec = SCMIRRORING_AUDIO_CODEC_AAC;
+ break;
+ case MM_WFD_SINK_AUDIO_CODEC_AC3:
+ *codec = SCMIRRORING_AUDIO_CODEC_AC3;
+ break;
+ case MM_WFD_SINK_AUDIO_CODEC_LPCM:
+ *codec = SCMIRRORING_AUDIO_CODEC_LPCM;
+ break;
+ default:
+ *codec = SCMIRRORING_AUDIO_CODEC_NONE;
+ break;
+ }
+
+ scmirroring_debug("codec: %d", *codec);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
- scmirroring_secondary_sink_s *handle = NULL;
++int scmirroring_secondary_sink_get_negotiated_audio_channel(scmirroring_secondary_sink_h scmirroring_secondary_sink, int *channel)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
- scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
- scmirroring_retvm_if(channel == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "channel is NULL");
-
- handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
++ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s*)scmirroring_secondary_sink;
+ scmirroring_debug_fenter();
+
-int scmirroring_secondary_sink_get_negotiated_audio_sample_rate(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *sample_rate)
++ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
++ scmirroring_retvm_if(channel == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "channel is NULL");
+
+ *channel = 0;
+
+ ret = mm_wfd_sink_get_negotiated_audio_channel(handle->mm_handle, channel);
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ scmirroring_debug("channel: %d", *channel);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
- scmirroring_secondary_sink_s *handle = NULL;
++int scmirroring_secondary_sink_get_negotiated_audio_sample_rate(scmirroring_secondary_sink_h scmirroring_secondary_sink, int *sample_rate)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
- scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
- scmirroring_retvm_if(sample_rate == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "sample_rate is NULL");
-
- handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
++ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s*)scmirroring_secondary_sink;
+ scmirroring_debug_fenter();
+
-int scmirroring_secondary_sink_get_negotiated_audio_bitwidth(scmirroring_secondary_sink_h *scmirroring_secondary_sink, int *bitwidth)
++ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
++ scmirroring_retvm_if(sample_rate == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "sample_rate is NULL");
+
+ *sample_rate = 0;
+
+ ret = mm_wfd_sink_get_negotiated_audio_sample_rate(handle->mm_handle, sample_rate);
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ scmirroring_debug("sample rate: %d", *sample_rate);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
- scmirroring_secondary_sink_s *handle = NULL;
++int scmirroring_secondary_sink_get_negotiated_audio_bitwidth(scmirroring_secondary_sink_h scmirroring_secondary_sink, int *bitwidth)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
- scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
- scmirroring_retvm_if(bitwidth == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "bitwidth is NULL");
-
- handle = (scmirroring_secondary_sink_s *)(*scmirroring_secondary_sink);
- scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "handle is NULL");
++ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s*)scmirroring_secondary_sink;
+ scmirroring_debug_fenter();
+
++ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
++ scmirroring_retvm_if(bitwidth == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "bitwidth is NULL");
+
+ *bitwidth = 0;
+
+ ret = mm_wfd_sink_get_negotiated_audio_bitwidth(handle->mm_handle, bitwidth);
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ return ret;
+
+ scmirroring_debug("bitwidth: %d", *bitwidth);
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
+
+ int scmirroring_secondary_sink_get_current_state(scmirroring_secondary_sink_h scmirroring_secondary_sink, scmirroring_sink_state_e *state)
+ {
+ int result = MM_ERROR_NONE;
+ int mm_state = MM_WFD_SINK_STATE_NONE;
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)(scmirroring_secondary_sink);
+
+ scmirroring_debug_fenter();
+ scmirroring_retvm_if(scmirroring_secondary_sink == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink* is NULL");
+ scmirroring_retvm_if(state == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "state is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+
+ result = mm_wfd_sink_get_current_state(handle->mm_handle, &mm_state);
+ if (result == MM_ERROR_NONE) {
+ *state = __scmirroring_secondary_sink_state_convert(mm_state);
+ scmirroring_debug("ScreenMirroring current state is [%d]", *state);
+ }
+ scmirroring_debug_fleave();
+ return __scmirroring_secondary_sink_error_convert(__func__, result);
+ }
+
+ int scmirroring_secondary_sink_set_coupled_sink(scmirroring_secondary_sink_h scmirroring_secondary_sink, gchar* address)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ scmirroring_debug_fenter();
+ scmirroring_secondary_sink_s *handle = (scmirroring_secondary_sink_s *)scmirroring_secondary_sink;
+
+ scmirroring_retvm_if(handle == NULL, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is NULL");
+ scmirroring_retvm_if(handle->magic_num != SCMIRRORING_MAGIC_NUMBER, SCMIRRORING_ERROR_INVALID_PARAMETER, "scmirroring_secondary_sink is invalid handle");
+ scmirroring_retvm_if(address, SCMIRRORING_ERROR_INVALID_PARAMETER, "MAC address is invalid");
+
+ scmirroring_debug("address[%s]", address);
+
+ ret = mm_wfd_sink_set_coupled_sink(handle->mm_handle, address);
+
+ if (ret != MM_ERROR_NONE) {
+ scmirroring_error("Fail to Set Coupled sink");
+ return __scmirroring_secondary_sink_error_convert(__func__, ret);
+ }
+ ret = __scmirroring_secondary_sink_error_convert(__func__, ret);
+
+ scmirroring_debug_fleave();
+
+ return ret;
+ }
scmirroring_debug("error: %s, status: %s", response[0], response[1]);
- error_code = __scmirroring_src_get_error(response[0]);
- src_state = __scmirroring_src_get_status(response[1]);;
- g_strfreev(response);
-
- if (scmirroring->current_state != src_state) {
- scmirroring->current_state = src_state;
+ /* 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]);
+ if(response[2] != NULL){
+ scmirroring_debug("response2 : %s", response[2]);
- }
- g_strfreev(response);
++ }
+ 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);
+ }
+ } else if (g_strcmp0("SECONDARY_SINK",response[0]) == 0 ) {
+ /* for coupled sink */
+ error_code = SCMIRRORING_ERROR_NONE;
+ src_state = SCMIRRORING_STATE_TEARDOWN;
__scmirroring_src_set_callback_info(scmirroring, error_code, src_state);
- } else {
- scmirroring_debug("Current state is already %d", src_state);
}
++ g_strfreev(response);
return;
+
}
gboolean __scmirroring_src_read_cb(GIOChannel *src, GIOCondition condition, gpointer data)
return ret;
}
- scmirroring_error("scmirroring_primary_src_set_coupling_mode1");
+ 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->coupling_mode = coupling_mode;
+
+ 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;
+ }
- ret = __scmirroring_src_send_set_coupling_mode(_scmirroring);
++ _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);
--- /dev/null
-#define COUPLED_SINK_ADDRESS "192.168.0.50"
+ /*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ #include <gio/gio.h>
+ #include <scmirroring_private.h>
+ #include <scmirroring_internal.h>
+
+ #include <stdlib.h>
+ #include <string.h>
+ #include <glib/gprintf.h>
+ #include <scmirroring_primary_sink.h>
+ #include <wifi-direct.h>
+ #include <wifi-direct-internal.h>
+
+ #include <Elementary.h>
+ #include <appcore-efl.h>
+
+ #define MAX_STRING_LEN 2048
+ #define SINKTEST_EXECUTE_DELAY 5000
+ #define MAIN_MENU 0
+ #define SUBMENU_RESOLUTION 1
+ #define SUBMENU_GETTING_STREAM_INFO 2
+ #define SUBMENU_SETTING_SINK 3
+ #define SUBMENU_SETTING_WINDOW_SIZE 4
+ //#define TEST_WITH_WIFI_DIRECT
+ #define TEST_PRIMARY_SINK
- g_loop = g_main_loop_new(NULL, FALSE);
- g_main_loop_run(g_loop);
-
+ #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);
+ static Evas_Object *create_evas_image_object(Evas_Object *eo_parent);
+ static void _win_del(void *data, Evas_Object *obj, void *event);
+ static gboolean _scmirroring_start_jobs(gpointer data);
+
+ struct appcore_ops ops = {
+ .create = app_create,
+ .terminate = app_terminate,
+ };
+ static Evas_Object* g_evas;
+ static Evas_Object* g_eo = NULL;
+
+ scmirroring_primary_sink_h scmirroring_primary_sink = NULL;
+ gint g_resolution = 0;
+ gint g_sinktype = SCMIRRORING_DISPLAY_TYPE_OVERLAY;
+
+ gint g_menu = MAIN_MENU;
+ GMainLoop *g_loop;
+
+ #ifdef TEST_WITH_WIFI_DIRECT
+ static int g_peer_cnt = 0;
+ static char g_peer_ip[32];
+ static char g_peer_port[32];
+ static char g_src_mac_addr[18] = {0, };
+ #define DEFAULT_SCREEN_MIRRORING_PORT 2022
+ #endif
+
+ gboolean __scmirroring_primary_sink_start(gpointer data);
+
+ #ifndef TEST_WITH_WIFI_DIRECT
+ static int __scmirroring_primary_sink_create(gpointer data);
+ #endif
+ #ifdef TEST_WITH_WIFI_DIRECT
+ static gboolean __start_wifi_display_connection();
+ static gboolean __start_p2p_connection(gpointer data);
+ static gboolean __disconnect_p2p_connection(void);
+ #endif
+ static void __quit_program_sink(void);
+ gboolean __timeout_menu_display(void *data);
+
+ /* for source*/
+ int _scmirroring_primary_src_create(void);
+ /* Submenu for setting resolution */
+ static void __display_resolution_submenu(void);
+ gboolean __timeout_resolution_submenu_display(void *data);
+ static void __interpret_resolution_submenu(char *cmd);
+
+ /* Submenu for getting negotiated audio and video information */
+ static void __display_stream_info_submenu(void);
+ gboolean __timeout_stream_info_submenu_display(void *data);
+ static void __interpret_stream_info_submenu(char *cmd);
+
+ /* Submenu for setting sink type */
+ gboolean __timeout_sink_submenu_display(void *data);
+ static void __display_sink_submenu(void);
+ static void __interpret_sink_submenu(char *cmd);
+ static void create_render_rect_and_bg(Evas_Object *win);
+
+ /* Submenu for setting window size */
+ gboolean __timeout_window_size_submenu_display(void *data);
+ static void __display_window_size_submenu(void);
+ static void __interpret_window_size_submenu(char *cmd);
+
+ static void create_render_rect_and_bg(Evas_Object *win);
+ void create_render_rect_and_bg(Evas_Object *win)
+ {
+ if (!win) {
+ g_print("no win");
+ return;
+ }
+ Evas_Object *bg, *rect;
+
+ bg = elm_bg_add(win);
+ elm_win_resize_object_add(win, bg);
+ evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_show(bg);
+
+ rect = evas_object_rectangle_add(evas_object_evas_get(win));
+ if (!rect) {
+ g_print("no rect");
+ return;
+ }
+ evas_object_color_set(rect, 0, 0, 0, 0);
+ evas_object_render_op_set(rect, EVAS_RENDER_COPY);
+
+ elm_win_resize_object_add(win, rect);
+ evas_object_size_hint_weight_set(rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_show(rect);
+ evas_object_show(win);
+ }
+
+ static void _win_del(void *data, Evas_Object *obj, void *event)
+ {
+ elm_exit();
+ }
+
+
+ static Evas_Object* _create_win(const char *name)
+ {
+ Evas_Object *eo = NULL;
+ int w = 0;
+ int h = 0;
+
+ g_printf("[%s][%d] name=%s\n", __func__, __LINE__, name);
+
+ eo = elm_win_add(NULL, name, ELM_WIN_BASIC);
+ if (eo) {
+ elm_win_title_set(eo, name);
+ elm_win_borderless_set(eo, EINA_TRUE);
+ evas_object_smart_callback_add(eo, "delete,request", _win_del, NULL);
+ elm_win_autodel_set(eo, EINA_TRUE);
+ elm_win_screen_size_get(eo, NULL, NULL, &w, &h);
+ g_print("window size :%d,%d\n", w, h);
+ elm_win_alpha_set(eo, EINA_TRUE);
+ }
+ return eo;
+ }
+
+ static Evas_Object *create_evas_image_object(Evas_Object *eo_parent)
+ {
+ if (!eo_parent)
+ return NULL;
+
+ Evas *evas = evas_object_evas_get(eo_parent);
+ Evas_Object *eo = NULL;
+
+ eo = evas_object_image_add(evas);
+
+ return eo;
+ }
+
+ static int app_create(void *data)
+ {
+
+ gboolean result = FALSE;
+
+ g_print("app_create enter");
+
+ Evas_Object *win = NULL;
+ /* create window */
+ win = _create_win(PACKAGE);
+ if (win == NULL)
+ return -1;
+ g_evas = win;
+ create_render_rect_and_bg(g_evas);
+
+ elm_win_activate(win);
+ evas_object_show(win);
+
+ result = _scmirroring_start_jobs((void *)NULL);
+ if (result != TRUE)
+ g_print("failed _scmirroring_start_jobs ");
+
+ g_print("app_create leave");
+
+ return result;
+
+ }
+ static int app_terminate(void *data)
+ {
+
+ if (g_evas) {
+ evas_object_del(g_evas);
+ g_evas = NULL;
+ }
+ return 0;
+ }
+
+ gboolean __timeout_sink_submenu_display(void *data)
+ {
+ __display_sink_submenu();
+ return FALSE;
+ }
+
+ static void __display_sink_submenu(void)
+ {
+ g_print("\n");
+ g_print("**********************************************************************\n");
+ g_print(" Setting sink \n");
+ g_print("**********************************************************************\n");
+ g_print("1 : SCMIRRORING_DISPLAY_TYPE_OVERLAY with No Surface(DEFAULT)\n");
+ g_print("2 : SCMIRRORING_DISPLAY_TYPE_OVERLAY with Surface\n");
+ g_print("3 : SCMIRRORING_DISPLAY_TYPE_EVAS\n");
+ g_print("g : Go back to main menu \n");
+ g_print("**********************************************************************\n");
+
+ }
+
+ static void __interpret_sink_submenu(char *cmd)
+ {
+ if (strncmp(cmd, "1", 1) == 0) {
+ g_print("SCMIRRORING_DISPLAY_TYPE_OVERLAY with No Surface\n");
+ g_sinktype = -1;
+ } else if (strncmp(cmd, "2", 1) == 0) {
+ g_print("SCMIRRORING_DISPLAY_TYPE_OVERLAY with Surface\n");
+ g_sinktype = SCMIRRORING_DISPLAY_TYPE_OVERLAY;
+ } else if (strncmp(cmd, "3", 1) == 0) {
+ g_print("SCMIRRORING_DISPLAY_TYPE_EVAS\n");
+ g_sinktype = SCMIRRORING_DISPLAY_TYPE_EVAS;
+ } else if (strncmp(cmd, "g", 1) == 0) {
+ g_print("go back to main menu\n");
+ g_menu = MAIN_MENU;
+ g_timeout_add(100, __timeout_menu_display, 0);
+ return;
+ }
+
+ g_print("sink type : %d\n", g_sinktype);
+ g_timeout_add(100, __timeout_sink_submenu_display, 0);
+ return;
+ }
+
+ gboolean __timeout_resolution_submenu_display(void *data)
+ {
+ __display_resolution_submenu();
+ return FALSE;
+ }
+
+ static void __display_resolution_submenu(void)
+ {
+ g_print("\n");
+ g_print("**********************************************************************\n");
+ g_print(" Setting resolution \n");
+ g_print("**********************************************************************\n");
+ g_print("1 : SCMIRRORING_RESOLUTION_1920x1080_P30 [%d]\n", SCMIRRORING_RESOLUTION_1920x1080_P30);
+ g_print("2 : SCMIRRORING_RESOLUTION_1280x720_P30 [%d]\n", SCMIRRORING_RESOLUTION_1280x720_P30);
+ g_print("3 : SCMIRRORING_RESOLUTION_960x540_P30 [%d]\n", SCMIRRORING_RESOLUTION_960x540_P30);
+ g_print("4 : SCMIRRORING_RESOLUTION_864x480_P30 [%d]\n", SCMIRRORING_RESOLUTION_864x480_P30);
+ g_print("5 : SCMIRRORING_RESOLUTION_720x480_P60 [%d]\n", SCMIRRORING_RESOLUTION_720x480_P60);
+ g_print("6 : SCMIRRORING_RESOLUTION_640x480_P60 [%d]\n", SCMIRRORING_RESOLUTION_640x480_P60);
+ g_print("7 : SCMIRRORING_RESOLUTION_640x360_P30 [%d]\n", SCMIRRORING_RESOLUTION_640x360_P30);
+ g_print("r : Reset resolution \n");
+ g_print("g : Go back to main menu \n");
+ g_print("**********************************************************************\n");
+
+ }
+
+ static void __interpret_resolution_submenu(char *cmd)
+ {
+ if (strncmp(cmd, "1", 1) == 0) {
+ g_print("resolution |= SCMIRRORING_RESOLUTION_1920x1080_P30[%d]\n", SCMIRRORING_RESOLUTION_1920x1080_P30);
+ g_resolution |= SCMIRRORING_RESOLUTION_1920x1080_P30;
+ } else if (strncmp(cmd, "2", 1) == 0) {
+ g_print("resolution |= SCMIRRORING_RESOLUTION_1280x720_P30[%d]\n", SCMIRRORING_RESOLUTION_1280x720_P30);
+ g_resolution |= SCMIRRORING_RESOLUTION_1280x720_P30;
+ } else if (strncmp(cmd, "3", 1) == 0) {
+ g_print("resolution |= SCMIRRORING_RESOLUTION_960x540_P30[%d]\n", SCMIRRORING_RESOLUTION_960x540_P30);
+ g_resolution |= SCMIRRORING_RESOLUTION_960x540_P30;
+ } else if (strncmp(cmd, "4", 1) == 0) {
+ g_print("resolution |= SCMIRRORING_RESOLUTION_864x480_P30[%d]\n", SCMIRRORING_RESOLUTION_864x480_P30);
+ g_resolution |= SCMIRRORING_RESOLUTION_864x480_P30;
+ } else if (strncmp(cmd, "5", 1) == 0) {
+ g_print("resolution |= SCMIRRORING_RESOLUTION_720x480_P60[%d]\n", SCMIRRORING_RESOLUTION_720x480_P60);
+ g_resolution |= SCMIRRORING_RESOLUTION_720x480_P60;
+ } else if (strncmp(cmd, "6", 1) == 0) {
+ g_print("resolution |= SCMIRRORING_RESOLUTION_640x480_P60[%d]\n", SCMIRRORING_RESOLUTION_640x480_P60);
+ g_resolution |= SCMIRRORING_RESOLUTION_640x480_P60;
+ } else if (strncmp(cmd, "7", 1) == 0) {
+ g_print("resolution |= SCMIRRORING_RESOLUTION_640x360_P30[%d]\n", SCMIRRORING_RESOLUTION_640x360_P30);
+ g_resolution |= SCMIRRORING_RESOLUTION_640x360_P30;
+ } else if (strncmp(cmd, "r", 1) == 0) {
+ g_resolution = 0;
+ } else if (strncmp(cmd, "g", 1) == 0) {
+ g_print("go back to main menu\n");
+ g_menu = MAIN_MENU;
+ g_timeout_add(100, __timeout_menu_display, 0);
+ return;
+ }
+
+ g_print("resolution : %d\n", g_resolution);
+
+ g_timeout_add(100, __timeout_resolution_submenu_display, 0);
+
+ return;
+ }
+
+ gboolean __timeout_stream_info_submenu_display(void *data)
+ {
+ __display_stream_info_submenu();
+ return FALSE;
+ }
+
+ static void __display_stream_info_submenu(void)
+ {
+ g_print("\n");
+ g_print("**********************************************************************\n");
+ g_print(" Getting negotiated audio and video information \n");
+ g_print("**********************************************************************\n");
+ g_print("1 : video codec\n");
+ g_print("2 : video resolution\n");
+ g_print("3 : video frame rate\n");
+ g_print("4 : audio codec\n");
+ g_print("5 : audio channel\n");
+ g_print("6 : audio sample rate\n");
+ g_print("7 : audio bitwidth\n");
+ g_print("g : Go back to main menu \n");
+ g_print("**********************************************************************\n");
+
+ }
+
+ static void __interpret_stream_info_submenu(char *cmd)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ if (strncmp(cmd, "1", 1) == 0) {
+
+ scmirroring_video_codec_e codec;
+ ret = scmirroring_primary_sink_get_negotiated_video_codec(&scmirroring_primary_sink, &codec);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("Error : scmirroring_primary_sink_get_negotiated_video_codec fail[%d]\n", ret);
+ } else {
+ switch (codec) {
+ case SCMIRRORING_VIDEO_CODEC_H264:
+ g_print("video codec : H264[%d]\n", codec);
+ break;
+ default:
+ g_print("video codec : NONE[%d]\n", codec);
+ break;
+ }
+ }
+
+ } else if (strncmp(cmd, "2", 1) == 0) {
+
+ int width, height;
+ ret = scmirroring_primary_sink_get_negotiated_video_resolution(&scmirroring_primary_sink, &width, &height);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ g_print("Error : scmirroring_primary_sink_get_negotiated_video_resolution fail[%d]\n", ret);
+ else
+ g_print("video resoltuion : width[%d], height[%d]\n", width, height);
+
+ } else if (strncmp(cmd, "3", 1) == 0) {
+
+ int frame_rate;
+ ret = scmirroring_primary_sink_get_negotiated_video_frame_rate(&scmirroring_primary_sink, &frame_rate);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ g_print("Error : scmirroring_primary_sink_get_negotiated_video_frame_rate fail[%d]\n", ret);
+ else
+ g_print("video frame rate[%d]\n", frame_rate);
+
+ } else if (strncmp(cmd, "4", 1) == 0) {
+ scmirroring_audio_codec_e codec;
+ ret = scmirroring_primary_sink_get_negotiated_audio_codec(&scmirroring_primary_sink, &codec);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("Error : scmirroring_primary_sink_get_negotiated_audio_codec fail[%d]\n", ret);
+ } else {
+ switch (codec) {
+ case SCMIRRORING_AUDIO_CODEC_AAC:
+ g_print("audio codec : AAC[%d]\n", codec);
+ break;
+ case SCMIRRORING_AUDIO_CODEC_AC3:
+ g_print("audio codec : AC3[%d]\n", codec);
+ break;
+ case SCMIRRORING_AUDIO_CODEC_LPCM:
+ g_print("audio codec : LPCM[%d]\n", codec);
+ break;
+ default:
+ g_print("audio codec : NONE[%d]\n", codec);
+ break;
+ }
+ }
+
+ } else if (strncmp(cmd, "5", 1) == 0) {
+ int channel;
+ ret = scmirroring_primary_sink_get_negotiated_audio_channel(&scmirroring_primary_sink, &channel);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ g_print("Error : scmirroring_primary_sink_get_negotiated_audio_channel fail[%d]\n", ret);
+ else
+ g_print("audio channel[%d]\n", channel);
+
+ } else if (strncmp(cmd, "6", 1) == 0) {
+ int sample_rate;
+ ret = scmirroring_primary_sink_get_negotiated_audio_sample_rate(&scmirroring_primary_sink, &sample_rate);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ g_print("Error : scmirroring_primary_sink_get_negotiated_audio_sample_rate fail[%d]\n", ret);
+ else
+ g_print("audio sample rate[%d]\n", sample_rate);
+
+ } else if (strncmp(cmd, "7", 1) == 0) {
+ int bitwidth;
+ ret = scmirroring_primary_sink_get_negotiated_audio_bitwidth(&scmirroring_primary_sink, &bitwidth);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ g_print("Error : scmirroring_primary_sink_get_negotiated_audio_bitwidth fail[%d]\n", ret);
+ else
+ g_print("audio bitwidth[%d]\n", bitwidth);
+
+ } else if (strncmp(cmd, "g", 1) == 0) {
+ g_print("go back to main menu\n");
+ g_menu = MAIN_MENU;
+ g_timeout_add(100, __timeout_menu_display, 0);
+ return;
+ }
+
+ g_timeout_add(100, __timeout_stream_info_submenu_display, 0);
+
+ return;
+ }
+
+ gboolean __timeout_window_size_submenu_display(void *data)
+ {
+ __display_window_size_submenu();
+ return FALSE;
+
+ }
+
+ static void __display_window_size_submenu(void)
+ {
+ g_print("\n");
+ g_print("**********************************************************************\n");
+ g_print(" Setting window size \n");
+ g_print("**********************************************************************\n");
+ g_print("1 : UHD [width:3840, height:2160] \n");
+ g_print("2 : FHD [width:1920, height:1080] \n");
+ g_print("3 : HD [width:1280, height:720] \n");
+ g_print("g : Go back to main menu \n");
+ g_print("**********************************************************************\n");
+
+ }
+
+ static void __interpret_window_size_submenu(char *cmd)
+ {
+ int w = 0;
+ int h = 0;
+ if (strncmp(cmd, "1", 1) == 0) {
+ w = 3840;
+ h = 2160;
+ elm_win_aux_hint_add(g_evas, "wm.policy.win.user.geometry", "1");
+ evas_object_resize(g_evas, w, h);
+ g_print("Window size is changed.[width:%d, height:%d]", w, h);
+ } else if (strncmp(cmd, "2", 1) == 0) {
+ w = 1920;
+ h = 1080;
+ elm_win_aux_hint_add(g_evas, "wm.policy.win.user.geometry", "1");
+ evas_object_resize(g_evas, w, h);
+ g_print("Window size is changed.[width:%d, height:%d]", w, h);
+ } else if (strncmp(cmd, "3", 1) == 0) {
+ w = 1280;
+ h = 720;
+ elm_win_aux_hint_add(g_evas, "wm.policy.win.user.geometry", "1");
+ evas_object_resize(g_evas, w, h);
+ g_print("Window size is changed.[width:%d, height:%d]", w, h);
+ } else if (strncmp(cmd, "g", 1) == 0) {
+ g_print("go back to main menu\n");
+ g_menu = MAIN_MENU;
+ g_timeout_add(100, __timeout_menu_display, 0);
+ return;
+ }
+
+ g_timeout_add(100, __timeout_window_size_submenu_display, 0);
+ return;
+ }
+
+ //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);
+ 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);
+
+ if (state == SCMIRRORING_SINK_STATE_NONE)
+ g_print(" state[%d] SCMIRRORING_SINK_STATE_NONE\n", state);
+ else if (state == SCMIRRORING_SINK_STATE_NULL)
+ g_print(" state[%d] SCMIRRORING_SINK_STATE_NULL\n", state);
+ else if (state == SCMIRRORING_SINK_STATE_PREPARED)
+ g_print(" state[%d] SCMIRRORING_SINK_STATE_PREPARED\n", state);
+ else if (state == SCMIRRORING_SINK_STATE_CONNECTED) {
+ g_print(" state[%d] SCMIRRORING_SINK_STATE_CONNECTED\n", state);
+ if (scmirroring_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)
+ g_print(" state[%d] SCMIRRORING_SINK_STATE_PAUSED\n", state);
+ else if (state == SCMIRRORING_SINK_STATE_DISCONNECTED) {
+ g_print(" state[%d] SCMIRRORING_SINK_STATE_DISCONNECTED\n", state);
+ if (scmirroring_primary_sink_unprepare(scmirroring_primary_sink) != SCMIRRORING_ERROR_NONE)
+ 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");
+ } else
+ g_print(" state[%d] Invalid State", state);
+
+ return;
+ }
+
+ static void __quit_program_sink(void)
+ {
+ g_print("Quit sink\n");
+
+ #ifdef TEST_WITH_WIFI_DIRECT
+ __disconnect_p2p_connection();
+ #endif
+ scmirroring_primary_sink = 0;
+ elm_exit();
+ }
+
+ static void __displaymenu(void)
+ {
+ g_print("\n");
+ g_print("=====================================================================\n");
+ g_print(" SCMIRRORING Primary Sink Testsuite(press q to quit) \n");
+ g_print("=====================================================================\n");
+ #ifdef TEST_PRIMARY_SINK
+ g_print("=====================================================================\n");
+ g_print(" Source function \n");
+ 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("---------------------------------------------------------------------\n");
+ #endif
+
+ g_print("=====================================================================\n");
+ g_print(" Sink function \n");
+ g_print("=====================================================================\n");
+ #ifndef TEST_WITH_WIFI_DIRECT
+ g_print("a : a ip port(ex. a 192.168.49.1 2022)\n");
+ g_print("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");
+ #endif
+ g_print("p : Pause\n");
+ g_print("r : Resume\n");
+ g_print("d : Disconnect\n");
+ g_print("t : desTroy\n");
+ g_print("L : Setting resolution\n");
+ g_print("G : Getting negotiated audio and video information\n");
+ g_print("I : Setting Sink\n");
+ g_print("K : Setting window size\n");
+ g_print("q : quit\n");
+ g_print("-----------------------------------------------------------------------------------------\n");
+ }
+
+ gboolean __timeout_menu_display(void *data)
+ {
+ __displaymenu();
+
+ return FALSE;
+ }
+
+ #ifdef TEST_WITH_WIFI_DIRECT
+ bool _connected_peer_cb(wifi_direct_connected_peer_info_s *peer, void *user_data)
+ {
+ int peer_port = 0;
+ if (wifi_direct_get_peer_display_port(peer->mac_address, &peer_port) != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Can not get port info\n Use default(2022)\n");
+ peer_port = DEFAULT_SCREEN_MIRRORING_PORT;
+ }
+ if (peer_port == 0) {
+ g_print("Can not get port info\n Use default(2022)\n");
+ peer_port = DEFAULT_SCREEN_MIRRORING_PORT;
+ }
+
+ g_print("[_connected_peer_cb] Connected to IP [%s]\n", peer->ip_address);
+ g_print("[_connected_peer_cb] Connected to Port [%d]\n", peer_port);
+ g_print("[_connected_peer_cb] Connected device_name [%s]\n", peer->device_name);
+ g_print("[_connected_peer_cb] Connected to mac_address [%s]\n", peer->mac_address);
+ g_print("[_connected_peer_cb] Connected to interface_address [%s]\n", peer->interface_address);
+
+ memset(g_peer_ip, 0x00, sizeof(g_peer_ip));
+ memset(g_peer_port, 0x00, sizeof(g_peer_port));
+
+ snprintf(g_peer_ip, sizeof(g_peer_port), "%s", peer->ip_address);
+ snprintf(g_peer_port, sizeof(g_peer_port), "%d", peer_port);
+
+ g_timeout_add(SINKTEST_EXECUTE_DELAY, __scmirroring_primary_sink_start, NULL);
+
+ return TRUE;
+ }
+
+ void _activation_cb(int error_code, wifi_direct_device_state_e device_state, void *user_data)
+ {
+ gint ret = FALSE;
+ switch (device_state) {
+ case WIFI_DIRECT_DEVICE_STATE_ACTIVATED:
+ g_print("device_state : WIFI_DIRECT_DEVICE_STATE_ACTIVATED\n");
+ ret = __start_wifi_display_connection();
+ if (ret == TRUE) {
+ g_print("__start_wifi_display_connection success\n");
+ } else {
+ g_print("__start_wifi_display_connection fail\n");
+ g_print("Quit Program\n");
+ ret = wifi_direct_deinitialize();
+ if (ret != WIFI_DIRECT_ERROR_NONE)
+ g_print("wifi_direct_deinitialize is failed\n");
+
+ scmirroring_primary_sink = 0;
+ elm_exit();
+ }
+ break;
+ case WIFI_DIRECT_DEVICE_STATE_DEACTIVATED:
+ g_print("device_state : WIFI_DIRECT_DEVICE_STATE_DEACTIVATED\n");
+ break;
+ default:
+ g_print("device_state : ERROR\n");
+ break;
+ }
+
+ return;
+ }
+
+ bool _discovered_peer_cb(wifi_direct_discovered_peer_info_s *peer, void *user_data)
+ {
+ g_print("[%d] discovered device peer : %s, %s, %d\n", g_peer_cnt, peer->device_name, peer->mac_address, peer->is_connected);
+
+ g_peer_cnt++;
+
+ return TRUE;
+ }
+
+ void _discover_cb(int error_code, wifi_direct_discovery_state_e discovery_state, void *user_data)
+ {
+ int ret = WIFI_DIRECT_ERROR_NONE;
+ /*g_print("Discovered [ error : %d discovery state : %d ]\n", error_code, discovery_state); */
+
+ switch (discovery_state) {
+ case WIFI_DIRECT_ONLY_LISTEN_STARTED:
+ g_print("discovery_state : WIFI_DIRECT_ONLY_LISTEN_STARTED \n");
+ break;
+ case WIFI_DIRECT_DISCOVERY_STARTED:
+ g_print("discovery_state : WIFI_DIRECT_DISCOVERY_STARTED \n");
+ break;
+ case WIFI_DIRECT_DISCOVERY_FOUND:
+ g_print("discovery_state : WIFI_DIRECT_DISCOVERY_FOUND \n");
+ ret = wifi_direct_foreach_discovered_peers(_discovered_peer_cb, (void *)NULL);
+ if (ret != WIFI_DIRECT_ERROR_NONE)
+ g_print("Error : wifi_direct_foreach_discovered_peers failed : %d\n", ret);
+ break;
+ case WIFI_DIRECT_DISCOVERY_FINISHED:
+ g_print("discovery_state : WIFI_DIRECT_DISCOVERY_FINISHED \n");
+ break;
+ default:
+ g_print("discovery_state : ERROR\n");
+ break;
+ }
+
+ return;
+ }
+
+ void _ip_assigned_cb(const char *mac_address, const char *ip_address, const char *interface_address, void *user_data)
+ {
+ g_print("[_ip_assigned_cb] IP assigned [ ip addr : %s if addr : %s mac_addr:%s ]\n", ip_address, interface_address, mac_address);
+
+ int peer_port = 0;
+ wifi_direct_discovered_peer_info_s *peer_info = NULL;
+
+ if (wifi_direct_get_peer_display_port((char *)mac_address, &peer_port) != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Can not get port info\n Use default(2022)\n");
+ peer_port = DEFAULT_SCREEN_MIRRORING_PORT;
+ }
+ if (peer_port == 0) {
+ g_print("Can not get port info\n Use default(2022)\n");
+ peer_port = DEFAULT_SCREEN_MIRRORING_PORT;
+ }
+ if (wifi_direct_get_peer_info((char *)mac_address, &peer_info) != WIFI_DIRECT_ERROR_NONE)
+ g_print("Can not get peer info and device name\n");
+
+ if (peer_info != NULL && peer_info->device_name != NULL)
+ g_print("[_ip_assigned_cb] Connected to device_name [%s]\n", peer_info->device_name);
+
+ g_print("[_ip_assigned_cb] Connected to IP [%s]\n", ip_address);
+ g_print("[_ip_assigned_cb] Connected to Port [%d]\n", peer_port);
+ g_print("[_ip_assigned_cb] Connected to mac_address [%s]\n", mac_address);
+ g_print("[_ip_assigned_cb] Connected to interface_address [%s]\n", interface_address);
+
+ memset(g_peer_ip, 0x00, sizeof(g_peer_ip));
+ memset(g_peer_port, 0x00, sizeof(g_peer_port));
+
+ snprintf(g_peer_ip, sizeof(g_peer_port), "%s", ip_address);
+ snprintf(g_peer_port, sizeof(g_peer_port), "%d", peer_port);
+
+ g_timeout_add(SINKTEST_EXECUTE_DELAY, __scmirroring_primary_sink_start, NULL);
+ }
+
+ void _connection_cb(int error_code, wifi_direct_connection_state_e connection_state, const char *mac_address, void *user_data)
+ {
+ int ret = WIFI_DIRECT_ERROR_NONE;
+
+ g_print("Connected [ error : %d connection state : %d mac_addr:%s ]\n", error_code, connection_state, mac_address);
+
+ switch (connection_state) {
+ case WIFI_DIRECT_CONNECTION_REQ:
+ g_print("WIFI_DIRECT_CONNECTION_REQ : Connection is requested\n");
+ ret = wifi_direct_accept_connection((char *)mac_address);
+ if (ret != WIFI_DIRECT_ERROR_NONE)
+ g_print("Error : wifi_direct_accept_connection failed : %d\n", ret);
+ break;
+ case WIFI_DIRECT_CONNECTION_WPS_REQ:
+ g_print("WIFI_DIRECT_CONNECTION_WPS_REQ : WPS is requested\n");
+ break;
+ case WIFI_DIRECT_CONNECTION_IN_PROGRESS:
+ g_print("WIFI_DIRECT_CONNECTION_IN_PROGRESS : Connection in progress\n");
+ break;
+ case WIFI_DIRECT_CONNECTION_RSP:
+ {
+ bool is_go = FALSE;
+ g_print("WIFI_DIRECT_CONNECTION_RSP : Connected\n");
+ ret = wifi_direct_is_group_owner(&is_go);
+ if (ret != WIFI_DIRECT_ERROR_NONE)
+ g_print("Error : wifi_direct_is_group_owner failed : %d\n", ret);
+
+ if (is_go) {
+ g_print("Connected as Group Owner\n");
+ } else {
+ ret = wifi_direct_foreach_connected_peers(_connected_peer_cb, (void *)NULL);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_foreach_connected_peers failed : %d\n", ret);
+ return;
+ }
+ g_print("Connected as Group Client\n");
+ }
+ break;
+ }
+ case WIFI_DIRECT_DISASSOCIATION_IND:
+ g_print("WIFI_DIRECT_DISASSOCIATION_IND : Disconnected by remote Group Client\n");
+ break;
+ case WIFI_DIRECT_DISCONNECTION_RSP:
+ g_print("WIFI_DIRECT_DISCONNECTION_RSP : Disconnected by local device\n");
+ break;
+ case WIFI_DIRECT_DISCONNECTION_IND:
+ g_print("WIFI_DIRECT_DISCONNECTION_IND : Disconnected by remote Group Owner\n");
+ break;
+ case WIFI_DIRECT_GROUP_CREATED:
+ g_print("WIFI_DIRECT_GROUP_CREATED : Group is created\n");
+ break;
+ case WIFI_DIRECT_GROUP_DESTROYED:
+ g_print("WIFI_DIRECT_GROUP_DESTROYED : Group is destroyed\n");
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+
+
+ static int __wifi_direct_device_connect()
+ {
+ if (strlen(g_src_mac_addr) > 17 || strlen(g_src_mac_addr) <= 0) {
+ g_print("\nWrong Mac_address");
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+ }
+
+ int err = wifi_direct_connect(g_src_mac_addr);
+ if (err != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Failed to connect [%d]\n", err);
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+ }
+ return SCMIRRORING_ERROR_NONE;
+ }
+
+ #endif
+
+ static void __interpret(char *cmd)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ gchar **value;
+ value = g_strsplit(cmd, " ", 0);
+
+ //Source Side
+
+ if (strncmp(cmd, "M", 1) == 0) {
+ ret = _scmirroring_primary_src_create();
+ } 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("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");
+ ret = scmirroring_primary_src_start(scmirroring_primary_sink);
+ } else if (strncmp(cmd, "T", 1) == 0) {
+ g_print("Stop\n");
+ ret = scmirroring_primary_src_stop(scmirroring_primary_sink);
+ } else if (strncmp(cmd, "D", 1) == 0) {
+ g_print("Destroy\n");
+ ret = scmirroring_primary_src_destroy(scmirroring_primary_sink);
+ }
+
+ //Sink side
+ 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) {
+ g_print("Pause\n");
+ ret = scmirroring_primary_sink_pause(scmirroring_primary_sink);
+ } else if (strncmp(cmd, "r", 1) == 0) {
+ g_print("Resume\n");
+ ret = scmirroring_primary_sink_resume(scmirroring_primary_sink);
+ } else if (strncmp(cmd, "t", 1) == 0) {
+ g_print("Destroy\n");
+ ret = scmirroring_primary_sink_unprepare(scmirroring_primary_sink);
+ ret = scmirroring_primary_sink_destroy(scmirroring_primary_sink);
+ } else if (strncmp(cmd, "q", 1) == 0) {
+ __quit_program_sink();
+ } else if (strncmp(cmd, "I", 1) == 0) {
+ g_menu = SUBMENU_SETTING_SINK;
+ g_timeout_add(100, __timeout_sink_submenu_display, 0);
+ return;
+ } else if (strncmp(cmd, "L", 1) == 0) {
+ g_menu = SUBMENU_RESOLUTION;
+ g_timeout_add(100, __timeout_resolution_submenu_display, 0);
+ return;
+ } else if (strncmp(cmd, "G", 1) == 0) {
+ g_menu = SUBMENU_GETTING_STREAM_INFO;
+ g_timeout_add(100, __timeout_stream_info_submenu_display, 0);
+ return;
+ } else if (strncmp(cmd, "K", 1) == 0) {
+ g_menu = SUBMENU_SETTING_WINDOW_SIZE;
+ g_timeout_add(100, __timeout_window_size_submenu_display, 0);
+ return;
+ }
+ #ifndef TEST_WITH_WIFI_DIRECT
+ else if (strncmp(cmd, "a", 1) == 0) {
+ ret = __scmirroring_primary_sink_create(NULL);
+ if (ret == SCMIRRORING_ERROR_NONE) {
+ ret = scmirroring_primary_sink_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, "s", 1) == 0) {
+ g_print("Start\n");
+ ret = __scmirroring_primary_sink_start(NULL);
+ }
+ #else
+ else if (strncmp(cmd, "b", 1) == 0) {
+ strncpy(g_src_mac_addr, value[1], sizeof(g_src_mac_addr));
+ g_src_mac_addr[17] = '\0';
+ g_print("Src mac address : %s\n", g_src_mac_addr);
+ ret = __wifi_direct_device_connect();
+ }
+ #endif
+ else
+ g_print("unknown menu \n");
+
+ if (ret != SCMIRRORING_ERROR_NONE)
+ g_print("Error Occured [%d]", ret);
+
+ g_timeout_add(100, __timeout_menu_display, 0);
+
+ return;
+ }
+
+ gboolean __input(GIOChannel *channel)
+ {
+ char buf[MAX_STRING_LEN + 3];
+ gsize read;
+ GError *error = NULL;
+
+ g_io_channel_read_chars(channel, buf, MAX_STRING_LEN, &read, &error);
+ buf[read] = '\0';
+ g_strstrip(buf);
+
+ if (g_menu == MAIN_MENU)
+ __interpret(buf);
+ else if (g_menu == SUBMENU_RESOLUTION)
+ __interpret_resolution_submenu(buf);
+ else if (g_menu == SUBMENU_GETTING_STREAM_INFO)
+ __interpret_stream_info_submenu(buf);
+ else if (g_menu == SUBMENU_SETTING_SINK)
+ __interpret_sink_submenu(buf);
+ else if (g_menu == SUBMENU_SETTING_WINDOW_SIZE)
+ __interpret_window_size_submenu(buf);
+
+ return TRUE;
+ }
+
+ #ifdef TEST_WITH_WIFI_DIRECT
+ static gboolean __start_wifi_display_connection()
+ {
+ int go_intent = 0;
+ static int is_initialized = FALSE;
+ wifi_direct_state_e direct_state = WIFI_DIRECT_STATE_DEACTIVATED;
+ gint ret = FALSE;
+
+ if (is_initialized == TRUE)
+ return TRUE;
+ is_initialized = TRUE;
+
+ /*Enable Screen Mirroring*/
+ ret = wifi_direct_init_display();
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_display_init failed : %d\n", ret);
+ return FALSE;
+ }
+
+ /*Enable Wifi Direct - You can set this as true if you want to see it from wifi-direct list*/
+ ret = wifi_direct_set_display_availability(TRUE);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_display_init failed : %d\n", ret);
+ return FALSE;
+ }
+
+ ret = wifi_direct_set_display(WIFI_DISPLAY_TYPE_SINK, 2022, 0);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_display_set_device failed : %d\n", ret);
+ return FALSE;
+ }
+
+ ret = wifi_direct_get_group_owner_intent(&go_intent);
+ g_print("go_intent = [%d]\n", go_intent);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_get_group_owner_intent failed : %d\n", ret);
+ return FALSE;
+ }
+
+ go_intent = 1;
+ ret = wifi_direct_set_group_owner_intent(go_intent);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_get_group_owner_intent failed : %d\n", ret);
+ return FALSE;
+ }
+ g_print("wifi_direct_set_group_owner_intent() result=[%d] go_intent[%d]\n", ret, go_intent);
+
+ ret = wifi_direct_set_max_clients(1);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_set_max_clients failed : %d\n", ret);
+ return FALSE;
+ }
+
+ ret = wifi_direct_get_state(&direct_state);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_get_state failed : %d\n", ret);
+ return FALSE;
+ }
+
+ if (direct_state > WIFI_DIRECT_STATE_ACTIVATING) {
+ char *device_name = NULL;
+
+ ret = wifi_direct_start_discovery(0, 20);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_start_discovery failed : %d\n", ret);
+ return FALSE;
+ }
+
+ ret = wifi_direct_get_device_name(&device_name);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_get_device_name failed : %d\n", ret);
+ return FALSE;
+ }
+
+ g_print("Device Name : [%s]\n", device_name);
+ if (device_name)
+ free(device_name);
+
+ } else {
+ g_print("Error : Direct not activated yet\n");
+ }
+
+ g_print("====== p2p connection established ======\n");
+
+ return TRUE;
+ }
+
+
+ static gboolean __start_p2p_connection(gpointer data)
+ {
+ int ret = WIFI_DIRECT_ERROR_NONE;
+ wifi_direct_state_e direct_state = WIFI_DIRECT_STATE_DEACTIVATED;
+
+ g_print("====== Start p2p connection ======\n");
+
+ ret = wifi_direct_initialize();
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_initialize failed : %d\n", ret);
+ return FALSE;
+ }
+
+ struct ug_data *ugd = (struct ug_data *)data;
+
+ /* Activation / Deactivation state Callback */
+ ret = wifi_direct_set_device_state_changed_cb(_activation_cb, (void *)ugd);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_set_device_state_changed_cb failed : %d\n", ret);
+ goto error;
+ }
+
+ /* Discovery state Callback */
+ ret = wifi_direct_set_discovery_state_changed_cb(_discover_cb, (void *)ugd);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_set_discovery_state_changed_cb failed : %d\n", ret);
+ goto error;
+ }
+
+ /* Connection state Callback */
+ ret = wifi_direct_set_connection_state_changed_cb(_connection_cb, (void *)ugd);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_set_connection_state_changed_cb failed : %d\n", ret);
+ goto error;
+ }
+
+ /* IP address assigning state callback */
+ ret = wifi_direct_set_client_ip_address_assigned_cb(_ip_assigned_cb, (void *)ugd);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_set_client_ip_address_assigned_cb failed : %d\n", ret);
+ goto error;
+ }
+
+ ret = wifi_direct_get_state(&direct_state);
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_get_state failed : %d\n", ret);
+ goto error;
+ }
+
+ if (direct_state < WIFI_DIRECT_STATE_ACTIVATED) {
+ g_print("wifi direct status < WIFI_DIRECT_STATE_ACTIVATED\n");
+ g_print("\n------Starting to activate scmirroring------\n");
+ ret = wifi_direct_activate();
+ if (ret < WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_activate failed : %d\n", ret);
+ return FALSE;
+ }
+ } else {
+ g_print("wifi direct status >= WIFI_DIRECT_STATE_ACTIVATED.. Disconnect all first\n");
+ ret = wifi_direct_disconnect_all();
+ if (!ret)
+ g_print("wifi_direct_disconnect_all success\n");
+ else
+ g_print("wifi_direct_disconnect_all fail\n");
+
+ ret = __start_wifi_display_connection();
+ if (ret == TRUE) {
+ g_print("__start_wifi_display_connection success\n");
+ } else {
+ g_print("__start_wifi_display_connection fail\n");
+ goto error;
+ }
+ }
+
+ return TRUE;
+
+ error:
+ ret = wifi_direct_deinitialize();
+
+ return FALSE;
+ }
+
+ static gboolean __disconnect_p2p_connection(void)
+ {
+ int ret = WIFI_DIRECT_ERROR_NONE;
+
+ ret = wifi_direct_deactivate();
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_deactivate failed : %d\n", ret);
+ return FALSE;
+ }
+
+ ret = wifi_direct_deinitialize();
+ if (ret != WIFI_DIRECT_ERROR_NONE) {
+ g_print("Error : wifi_direct_deinitialize failed : %d\n", ret);
+ return FALSE;
+ }
+
+ g_print("------p2p connection disconnected------\n");
+
+ return TRUE;
+ }
+ #endif
+
+ #ifndef TEST_WITH_WIFI_DIRECT
+ static int __scmirroring_primary_sink_create(gpointer data)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ ret = scmirroring_primary_sink_create(&scmirroring_primary_sink);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("scmirroring_primary_sink_create fail [%d]", ret);
+ return SCMIRRORING_ERROR_INVALID_OPERATION;
+ }
+
+ if (g_sinktype != -1) {
+ if (g_sinktype == SCMIRRORING_DISPLAY_TYPE_OVERLAY) {
+ evas_object_show(g_evas);
+ ret = scmirroring_primary_sink_set_display(scmirroring_primary_sink, SCMIRRORING_DISPLAY_TYPE_OVERLAY, (void *)g_evas);
+ } else if (g_sinktype == SCMIRRORING_DISPLAY_TYPE_EVAS) {
+ g_eo = create_evas_image_object(g_evas);
+ evas_object_image_size_set(g_eo, 800, 1200);
+ evas_object_image_fill_set(g_eo, 0, 0, 800, 1200);
+ evas_object_resize(g_eo, 800, 1200);
+ evas_object_show(g_evas);
+ ret = scmirroring_primary_sink_set_display(scmirroring_primary_sink, SCMIRRORING_DISPLAY_TYPE_EVAS, (void *)g_eo);
+ }
+
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("scmirroring_primary_sink_set_display fail [%d]", ret);
+ return FALSE;
+ }
+ }
+
+ return ret;
+ }
+ #endif
+
+ gboolean __scmirroring_primary_sink_start(gpointer data)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+ g_print("__scmirroring_primary_sink_start <enter>\n");
+
+ #ifdef TEST_WITH_WIFI_DIRECT
+ ret = scmirroring_primary_sink_create(&scmirroring_primary_sink);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("scmirroring_primary_sink_create fail [%d]", ret);
+ return FALSE;
+ }
+
+ if (g_resolution != 0) {
+ ret = scmirroring_primary_sink_set_resolution(scmirroring_primary_sink, g_resolution);
+ if (ret != SCMIRRORING_ERROR_NONE)
+ g_print("Failed to set resolution, error[%d]\n", ret);
+ }
+
+ if (g_sinktype != -1) {
+
+ if (g_sinktype == SCMIRRORING_DISPLAY_TYPE_OVERLAY) {
+ evas_object_show(g_evas);
+ ret = scmirroring_primary_sink_set_display(scmirroring_primary_sink, SCMIRRORING_DISPLAY_TYPE_OVERLAY, (void *)g_evas);
+ } else if (g_sinktype == SCMIRRORING_DISPLAY_TYPE_EVAS) {
+ g_eo = create_evas_image_object(g_evas);
+ evas_object_image_size_set(g_eo, 800, 1200);
+ evas_object_image_fill_set(g_eo, 0, 0, 800, 1200);
+ evas_object_resize(g_eo, 800, 1200);
+ evas_object_show(g_evas);
+ ret = scmirroring_primary_sink_set_display(scmirroring_primary_sink, SCMIRRORING_DISPLAY_TYPE_EVAS, (void *)g_eo);
+ }
+
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("scmirroring_primary_sink_set_display fail [%d]", ret);
+ return FALSE;
+ }
+ }
+
+ ret = scmirroring_primary_sink_prepare(scmirroring_primary_sink);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("scmirroring_primary_sink_prepare fail [%d]", ret);
+ return FALSE;
+ }
+
+ ret = scmirroring_primary_sink_set_ip_and_port(scmirroring_primary_sink, g_peer_ip, g_peer_port);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("scmirroring_primary_sink_set_ip_and_port fail [%d]", ret);
+ return FALSE;
+ }
+
+ g_print("Input server IP and port number IP[%s] Port[%s]\n", g_peer_ip, g_peer_port);
+ #endif
+
+ ret = scmirroring_primary_sink_set_state_changed_cb(scmirroring_primary_sink, scmirroring_sink_state_callback, NULL);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("scmirroring_primary_sink_set_state_changed_cb fail [%d]", ret);
+ return FALSE;
+ }
+
+ ret = scmirroring_primary_sink_connect(scmirroring_primary_sink);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("scmirroring_primary_sink_connect fail [%d]", ret);
+ return FALSE;
+ }
+
+ g_print("__scmirroring_primary_sink_start <leave>\n");
+ return FALSE;
+ }
+
+ gboolean _scmirroring_start_jobs(gpointer data)
+ {
+ #ifdef TEST_WITH_WIFI_DIRECT
+ int ret = WIFI_DIRECT_ERROR_NONE;
+
+ ret = __start_p2p_connection(data);
+ if (ret == FALSE)
+ return FALSE;
+ #endif
+
+ return TRUE;
+ }
+
+ int _scmirroring_primary_src_create(void)
+ {
+ int ret = SCMIRRORING_ERROR_NONE;
+
+ g_print("Create source handle\n");
+ ret = scmirroring_primary_src_create(&scmirroring_primary_sink);
+ if (ret != SCMIRRORING_ERROR_NONE) {
+ g_print("Failed to create source handle\n");
+ return ret;
+ }
+
+ g_print("Set state Changed callback function\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");
+
+ return ret;
+ }
+
+ int main(int argc, char *argv[])
+ {
+ GIOChannel *stdin_channel;
+
+ stdin_channel = g_io_channel_unix_new(0);
+ g_io_channel_set_flags(stdin_channel, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)__input, NULL);
+
+ __displaymenu();
+
+ ops.data = NULL;
+ appcore_efl_main(PACKAGE, &argc, &argv, &ops);
+
+ return 0;
+ }