[ACR-1252] Add to send event, reply and received callbacks 89/183489/1
authorJiyong Min <jiyong.min@samsung.com>
Tue, 26 Jun 2018 01:18:21 +0000 (10:18 +0900)
committerhj kim <backto.kim@samsung.com>
Fri, 6 Jul 2018 04:29:34 +0000 (04:29 +0000)
Change-Id: I22a3f81785f38c77213e854cc47ab8dd152cb282
(cherry picked from commit beeeff22972d6a79c28f905364f028eb52e9486c)

include/media_controller_client.h
include/media_controller_db.h
include/media_controller_private.h
include/media_controller_server.h
src/media_controller_client.c
src/media_controller_db.c
src/media_controller_ipc.c
src/media_controller_server.c
svc/media_controller_db_util.c
test/client_test/media_controller_client_test.c
test/server_test/media_controller_server_test.c

index ba080a5..0403f9e 100755 (executable)
@@ -164,14 +164,14 @@ typedef void (*mc_shuffle_mode_updated_cb)(const char *server_name, mc_shuffle_m
 typedef void (*mc_repeat_mode_updated_cb)(const char *server_name, mc_repeat_mode_e mode, void *user_data);
 
 /**
- * @brief Called when requesting the list of activated servers.
+ * @brief Called when requesting the list of created servers.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
- * @remarks The callback is called in the dbus event loop.
+ * @remarks The callback is called in the main loop.
  *               The @a server_name should not be released by the application. \n
  *               The @a server_name can be used only in the callback. To use outside, make a copy.
  *
- * @param[in] server_name The app_id of the activated media controller server.
+ * @param[in] server_name The app_id of the created media controller server.
  * @param[in] user_data        The user data passed from the mc_client_foreach_server() function
  *
  * @return @c true to continue with the next iteration of the loop,
@@ -213,10 +213,10 @@ typedef void (*mc_command_reply_received_cb)(const char *server_name, int result
  * @param[in] request_id     The id of the command request
  * @param[in] result_code    The result code of the action
  * @param[in] data The extra data
- * @param[in] user_data        The user data passed from the mc_client_send_custom_cmd() function
+ * @param[in] user_data        The user data passed from the mc_client_set_cmd_reply_received_cb() function
  *
  * @pre mc_client_send_custom_cmd()
- * @pre mc_client_set_cmd_reply_cb()
+ * @pre mc_client_set_cmd_reply_received_cb()
  *
  * @see mc_client_send_custom_cmd()
  */
@@ -265,6 +265,30 @@ typedef bool (*mc_subscribed_server_cb)(const char *server_name, void *user_data
 typedef void (*mc_playlist_updated_cb)(const char *server_name, mc_playlist_update_mode_e mode, const char *playlist_name, mc_playlist_h playlist, void *user_data);
 
 /**
+ * @brief Called when receiving custom event of media controller servers.
+ * @since_tizen 4.0
+ *
+ * @remarks The callback is called in the dbus event loop. The @a data should be released using bundle_free(). \n
+ *          The @a server_name, @a request_id and @a event should not be released by the application. \n
+ *          The @a server_name, @a request_id and @a event can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] server_name The app_id of the subscribed media controller server.
+ * @param[in] request_id     The id of the custom event request
+ * @param[in] event          The name of the custom event
+ * @param[in] data           The data can include other information associated with the event
+ * @param[in] user_data        The user data passed from the mc_client_set_custom_event_received_cb() function
+ *
+ * @return @c true to continue with the next iteration of the loop,
+ *         otherwise @c false to break out of the loop
+ *
+ * @pre mc_client_set_custom_event_received_cb()
+ *
+ * @see mc_client_set_custom_event_received_cb()
+ * @see mc_client_unset_custom_event_received_cb()
+ */
+typedef void (*mc_client_custom_event_received_cb)(const char *server_name, const char *request_id, const char *event, bundle *data, void *user_data);
+
+/**
  * @brief Creates a media controller client.
  * @details The media controller client binds the latest media controller server when handlers are created.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
@@ -795,6 +819,82 @@ int mc_client_set_playlist_updated_cb(mc_client_h client, mc_playlist_updated_cb
 int mc_client_unset_playlist_updated_cb(mc_client_h client);
 
 /**
+ * @brief Sets the callback for receiving the custom event from a media controller server.
+ * @since_tizen 4.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param[in] client    The handle to media controller client
+ * @param[in] callback      The callback to be invoked when the media controller client receives custom event from a media controller server.
+ * @param[in] user_data   The user data to be passed to the callback function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_client_create()
+ * @see mc_client_custom_event_received_cb()
+ * @see mc_client_unset_custom_event_received_cb()
+ * @see mc_client_send_event_reply()
+ * @see mc_client_destroy()
+ */
+int mc_client_set_custom_event_received_cb(mc_client_h client, mc_client_custom_event_received_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for receiving the custom event from a media controller server.
+ * @since_tizen 4.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param[in] client    The handle to the media controller client
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_client_create()
+ * @see mc_client_custom_event_received_cb()
+ * @see mc_client_set_custom_event_received_cb()
+ * @see mc_client_destroy()
+ */
+int mc_client_unset_custom_event_received_cb(mc_client_h client);
+
+/**
+ * @brief Replies with the result of the requested event to the media controller server.
+ * @since_tizen 4.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @remarks The media controller client get the @a server_name and @a request_id through the mc_client_custom_event_received_cb().
+ *          If @a request_id is not null there, the media controller client should send the reply to the media controller server with the @a request_id. \n
+ *          If @a request_id is null, this function will return #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER.
+ *
+ * @param[in] client    The handle to the media controller client
+ * @param[in] server_name    The app_id of the media controller server
+ * @param[in] request_id    The id of the event request, received in the mc_client_set_custom_event_received_cb() function.
+ * @param[in] result_code    The result code of custom event
+ * @param[in] data                The extra data
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_client_create()
+ * @see mc_client_set_custom_event_received_cb()
+ * @see mc_client_unset_custom_event_received_cb()
+ * @see mc_client_destroy()
+ */
+int mc_client_send_event_reply(mc_client_h client, const char *server_name, const char *request_id, int result_code, bundle *data);
+
+/**
  * @brief Subscribes media controller server for monitoring status.
  * @details If media controller client subscribe media controller server, \n
  *              the media controller client receive callback from subscribed media controller server. \n
@@ -997,6 +1097,9 @@ int mc_client_destroy_metadata(mc_metadata_h metadata) TIZEN_DEPRECATED_API;
  *
  * @remarks The @a server_name should be released using free(). \n
  *               If there is no activated media controller server, return value of the server name is NULL. \n
+ *               Before a media controller server sets the playback state to #MC_PLAYBACK_STATE_PLAYING, the @a server_state is #MC_SERVER_STATE_NONE.
+ *               After a media controller server sets the playback state to #MC_PLAYBACK_STATE_PLAYING, the @a server_state is #MC_SERVER_STATE_ACTIVATE.
+ *               After a media controller server is destroyed, @a server_state is #MC_SERVER_STATE_DEACTIVATE.
  *
  * @param[in] client    The handle to the media controller client
  * @param[out] server_name    The app_id of the latest media controller server
@@ -1096,14 +1199,17 @@ int mc_client_get_server_shuffle_mode(mc_client_h client, const char *server_nam
 int mc_client_get_server_repeat_mode(mc_client_h client, const char *server_name, mc_repeat_mode_e *mode);
 
 /**
- * @brief Retrieves all activated Server.
+ * @brief Retrieves all created servers.
+ * @details This function gets all created media controller servers.
+ *          The callback function will be invoked for every created media controller server.
+ *          If there are no media controller servers, the callback will not be invoked.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
  * @privlevel public
  * @privilege %http://tizen.org/privilege/mediacontroller.client
  *
  * @param[in] client    The handle to the media controller client
- * @param[in] callback      The callback to be invoked when the list of the registered media controller server created completely.
+ * @param[in] callback      The callback function to be invoked, will be called for each server
  * @param[in] user_data   The user data to be passed to the callback function
  * @return @c 0 on success,
  *         otherwise a negative error value
index 7863fa2..f791ed1 100755 (executable)
@@ -24,6 +24,7 @@ int mc_db_disconnect(void *db_handle);
 int mc_db_create_server_table(void *handle, const char *server_name);
 int mc_db_delete_server_table(void *handle, const char *server_name);
 int mc_db_check_server_table_exist(void *handle, const char *server_name, bool *exist);
+int mc_db_check_client_table_exist(void *handle, const char *client_name, bool *exist);
 
 int mc_db_update_playback_info(void *handle, const char *table_name, int playback_state, unsigned long long playback_position, const char *index);
 int mc_db_update_whole_metadata(void *handle, const char *server_name,
@@ -31,6 +32,7 @@ int mc_db_update_whole_metadata(void *handle, const char *server_name,
                                                const char *copyright, const char *description, const char *track_num, const char *picture);
 int mc_db_update_shuffle_mode(void *handle, const char *table_name, int shuffle_mode);
 int mc_db_update_repeat_mode(void *handle, const char *table_name, int repeat_mode);
+int mc_db_update_extra_info(void *handle, const char *server_name, const char *event_name, const char *extras);
 
 int mc_db_get_latest_server_name(void *handle, char **latest_server_name);
 int mc_db_get_server_state(void *handle, const char *server_name, mc_server_state_e *state);
@@ -42,8 +44,11 @@ int mc_db_get_foreach_playlist(void *handle, const char *server_name, mc_playlis
 int mc_db_get_playlist_item(void *handle, const char *server_name, char *playlist_name, mc_playlist_item_cb callback, void *user_data);
 int mc_db_insert_server_address_into_server_list(void *db_handle, const char *address);
 int mc_db_delete_server_address_from_server_list(void *db_handle, const char *address);
+int mc_db_insert_client_address_into_client_list(void *db_handle, const char *address);
+int mc_db_delete_client_address_from_client_list(void *db_handle, const char *address);
 
 int mc_db_foreach_server_list(void *handle, mc_activated_server_cb callback, void *user_data);
+int mc_db_foreach_client_list(void *handle, mc_activated_client_cb callback, void *user_data);
 int mc_db_update_server_and_playback_state(void *handle, const char *server_name, mc_server_state_e server_state, mc_playback_states_e playback_state);
 int mc_db_update_latest_server_table(void *handle, const char *server_name);
 int mc_db_remove_playlist(void *handle, const char *server_name, const char *playlist_name);
index 2066a36..4d0e630 100755 (executable)
@@ -119,6 +119,7 @@ extern "C" {
 #define MC_DB_TABLE_SERVER_LIST                "server_list"
 #define MC_DB_TABLE_LATEST_SERVER              "latest_server"
 #define MC_DB_TABLE_PLAYLIST                   "server_playlist"
+#define MC_DB_TABLE_CLIENT_LIST                "client_list"
 
 #define SQLITE3_SAFE_FREE(sql_string)  {if (sql_string) { sqlite3_free(sql_string); sql_string = NULL; } }
 #define SQLITE3_FINALIZE(x)    {if (x != NULL) sqlite3_finalize(x); }
@@ -168,6 +169,8 @@ extern "C" {
 #define MC_DBUS_SIGNAL_NAME_PLAYBACK_PLAYLIST          "pb_playlist"
 #define MC_DBUS_SIGNAL_NAME_CUSTOM_COMMAND                     "custom_command"
 #define MC_DBUS_SIGNAL_NAME_CUSTOM_COMMAND_REPLY       "custom_command_reply"
+#define MC_DBUS_SIGNAL_NAME_CUSTOM_EVENT                       "custom_event"
+#define MC_DBUS_SIGNAL_NAME_EVENT_REPLY                                "event_reply"
 
 
 #define MC_COMMAND_PLAYBACKSTATE               "_pb_state_cmd_"
@@ -180,8 +183,13 @@ extern "C" {
 #define MC_COMMAND_CUSTOMACTION                        "_custom_action_"
 #define MC_COMMAND_CMDREPLY                            "_cmd_reply_"
 
+#define MC_EVENT_CUSTOM                                        "_custom_event_"
+#define MC_EVENT_REPLY                                 "_event_reply_"
+
+
 #define MC_DB_CMD_CREATE_SERVER                "DB_CMD_CREATE_SERVER"                  /* Create New Server Table*/
 #define MC_DB_CMD_UPDATE_SERVER_LIST   "DB_CMD_UPDATE_SERVER_LIST"                     /* Update Server Name*/
+#define MC_DB_CMD_UPDATE_CLIENT_LIST   "DB_CMD_UPDATE_CLIENT_LIST"                     /* Update Client Name*/
 #define MC_DB_CMD_UPDATE_PLAYBACK      "DB_CMD_UPDATE_PLAYBACK"                /* Update Server Playback info*/
 #define MC_DB_CMD_UPDATE_STATE_PLAYBACK        "DB_CMD_UPDATE_STATE_PLAYBACK"  /* Update Server State and Playback state*/
 #define MC_DB_CMD_UPDATE_META          "DB_CMD_UPDATE_META"                    /* Update Server Meta info*/
@@ -192,6 +200,7 @@ extern "C" {
 #define MC_DB_CMD_REMOVE_SERVER                "DB_CMD_REMOVE_SERVER"          /* Remove Server info*/
 #define MC_DB_CMD_REMOVE_PLAYLIST      "DB_CMD_REMOVE_PLAYLIST"                /* Remove Server State*/
 #define MC_DB_CMD_REMOVE_SERVER_LIST   "DB_CMD_REMOVE_SERVER_LIST"     /* Remove Server from Server List*/
+#define MC_DB_CMD_REMOVE_CLIENT_LIST   "DB_CMD_REMOVE_CLIENT_LIST"     /* Remove Client from Client List*/
 
 
 #define DEFAULT_USER_UID 5001  /* owner */
@@ -258,6 +267,7 @@ typedef struct {
        media_controller_receiver_s custom_cmd_reciever;
        media_controller_receiver_s play_playlist_reciever;
        media_controller_receiver_s custom_command_reciever;
+       media_controller_receiver_s event_reply_receiver;
 } media_controller_server_s;
 
 typedef struct {
@@ -277,6 +287,7 @@ typedef struct {
        media_controller_receiver_s reply_cb;
        media_controller_receiver_s playlist_cb;
        media_controller_receiver_s cmd_reply_cb;
+       media_controller_receiver_s custom_event_cb;
 } media_controller_client_s;
 
 typedef struct {
index be8d52a..d3cbf8c 100755 (executable)
@@ -212,6 +212,49 @@ typedef void (*mc_server_playlist_cmd_received_cb)(const char* client_name, cons
 typedef void (*mc_server_custom_cmd_received_cb)(const char* client_name, const char *request_id, const char *command, bundle *data, void *user_data);
 
 /**
+ * @brief Called when requesting the list of created clients.
+ * @since_tizen 4.0
+ *
+ * @remarks The callback is called in the main loop. \n
+ *          The @a client_name should not be released by the application. \n
+ *          The @a client_name can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] client_name The app_id of the created media controller client.
+ * @param[in] user_data        The user data passed from the mc_client_foreach_server() function
+ *
+ * @return @c true to continue with the next iteration of the loop,
+ *         otherwise @c false to break out of the loop
+ *
+ * @pre mc_server_foreach_client()
+ *
+ * @see mc_server_foreach_client()
+ */
+typedef bool (*mc_activated_client_cb)(const char *client_name, void *user_data);
+
+/**
+ * @brief Called when the result of the event from the client is received.
+ * @since_tizen 4.0
+ *
+ * @remarks The callback is called in the dbus event loop. @a data should be released using bundle_free(). \n
+ *          The @a client_name and @a request_id should not be released by the application. \n
+ *          The @a client_name and @a request_id can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] client_name    The app_id of the media controller client which sent the reply. It can be used only in the callback. To use outside, make a copy.
+ * @param[in] request_id     The id of the event request
+ * @param[in] result_code    The result code of the event
+ * @param[in] data The extra data
+ * @param[in] user_data        The user data passed from the mc_server_set_event_reply_received_cb() function
+ *
+ * @pre mc_server_send_custom_event()
+ * @pre mc_server_set_event_reply_received_cb()
+ *
+ * @see mc_server_send_custom_event()
+ * @see mc_server_set_event_reply_received_cb()
+ * @see mc_server_unset_event_reply_received_cb()
+ */
+typedef void (*mc_server_event_reply_received_cb)(const char *client_name, const char *request_id, int result_code, bundle *data, void *user_data);
+
+/**
  * @brief Creates a media controller server.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
@@ -799,6 +842,107 @@ int mc_server_unset_custom_cmd_received_cb(mc_server_h server);
 int mc_server_send_cmd_reply(mc_server_h server, const char *client_name, const char *request_id, int result_code, bundle *data);
 
 /**
+ * @brief Retrieves all created clients.
+ * @details This function gets all created media controller clients.
+ *          The callback function will be invoked for every created media controller client.
+ *          If there are no media controller clients, the callback will not be invoked.
+ * @since_tizen 4.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param[in] server    The handle to media controller server
+ * @param[in] callback      The callback function to be invoked, will be called for each client
+ * @param[in] user_data   The user data to be passed to the callback function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_activated_client_cb()
+ * @see mc_server_destroy()
+ */
+int mc_server_foreach_client(mc_server_h server, mc_activated_client_cb callback, void *user_data);
+
+/**
+ * @brief Sends the customized event with the bundle data.
+ * @details If the event is needed in the client, this function should be called. @a data is a bundle.
+ * @since_tizen 4.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @remarks The @a request_id should be released using free().\n
+ *          If the @a request_id is null, the client will not send the reply of the custom event.
+ *
+ * @param[in] server The handle to media controller server
+ * @param[in] client_name The name of the client which receive the event
+ * @param[in] event The name of the event
+ * @param[in] data The data can include other information associated with the event
+ * @param[out] request_id   The id of the event request, it will be passed to the mc_server_event_reply_received_cb() function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_event_reply_received_cb()
+ * @see mc_server_set_event_reply_received_cb()
+ * @see mc_server_destroy()
+ */
+int mc_server_send_custom_event(mc_server_h server, const char *client_name, const char *event, bundle *data, char **request_id);
+
+/**
+ * @brief Sets the callback for receiving the result of the event from the media controller client.
+ * @details The media controller server which calls this function will receive the result of the event from all media controller clients.
+ * @since_tizen 4.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param[in] server         The handle to the media controller server
+ * @param[in] callback      The callback to be invoked when the reply is received
+ * @param[in] user_data   The user data to be passed to the callback function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_unset_event_reply_received_cb()
+ * @see mc_server_destroy()
+ */
+int mc_server_set_event_reply_received_cb(mc_server_h server, mc_server_event_reply_received_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for receiving event reply of the media controller client.
+ * @since_tizen 4.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param[in] server         The handle to the media controller server
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_server_create()
+ * @see mc_server_set_event_reply_received_cb()
+ * @see mc_server_destroy()
+ */
+int mc_server_unset_event_reply_received_cb(mc_server_h server);
+
+/**
  * @brief Destroys media controller server.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  * @param[in] server The handle to media controller server
index fb6791b..92f8626 100755 (executable)
@@ -229,6 +229,48 @@ static void __client_cmd_reply_received_cb(const char *interface_name, const cha
        g_strfreev(params);
 }
 
+static void __client_custom_event_received_cb(const char *interface_name, const char *signal_name, const char *message, const char *request_id, void *user_data)
+{
+       gchar **params = NULL;
+       int enc_size = 0;
+       char *sender = NULL;
+       char *command = NULL;
+       bundle *bundle_data = NULL;
+
+       media_controller_receiver_s *receiver = (media_controller_receiver_s *)user_data;
+       mc_retm_if(receiver == NULL, "reciever is NULL");
+
+       mc_client_custom_event_received_cb callback = receiver->callback;
+       mc_retm_if(receiver->callback == NULL, "custom_event_received_cb is NULL");
+
+       mc_debug("__client_custom_event_received_cb(%s, %s, %s, %llu, %p)", interface_name, signal_name, message, request_id, user_data);
+
+       params = g_strsplit(message, MC_STRING_DELIMITER, 0);
+       mc_retm_if(params == NULL, "invalid custom data");
+
+       if (params[0])
+               sender = strdup(params[0]);
+
+       if (mc_util_get_command_available(MC_PRIV_TYPE_CLIENT, sender, MC_EVENT_CUSTOM, params[1]) != MEDIA_CONTROLLER_ERROR_NONE) {
+               mc_error("Error permission denied");
+               MC_SAFE_FREE(sender);
+               g_strfreev(params);
+               return;
+       }
+
+       command = strdup(params[1]);
+       enc_size = atoi(params[2]);
+       if (enc_size > 0)
+               bundle_data = bundle_decode((bundle_raw *)params[3], enc_size);
+
+       callback(sender, request_id, command, bundle_data, receiver->user_data);
+
+       MC_SAFE_FREE(sender);
+       MC_SAFE_FREE(command);
+
+       g_strfreev(params);
+}
+
 static int __mc_client_create(media_controller_client_s **mc_client)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -454,6 +496,13 @@ int mc_client_create(mc_client_h *client)
                return ret;
        }
 
+       ret = mc_db_insert_client_address_into_client_list(mc_client->db_handle, mc_client->client_name);
+       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+               mc_error("fail mc_db_insert_server_address_into_table [%d]", ret);
+               __mc_client_destroy(mc_client);
+               return ret;
+       }
+
        *client = (mc_client_h)mc_client;
 
        mc_debug_fleave();
@@ -1549,6 +1598,73 @@ int mc_client_send_custom_cmd(mc_client_h client, const char *server_name, const
        return ret;
 }
 
+int mc_client_set_custom_event_received_cb(mc_client_h client, mc_client_custom_event_received_cb callback, void *user_data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+       mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+       mc_client->custom_event_cb.callback = callback;
+       mc_client->custom_event_cb.user_data = user_data;
+
+       char *interface_name = mc_util_get_interface_name(MC_CLIENT, mc_client->client_name);
+       ret = mc_ipc_register_listener(&mc_client->listeners, mc_client->dconn, interface_name, MC_DBUS_SIGNAL_NAME_CUSTOM_EVENT,
+               __client_custom_event_received_cb, (void *)&(mc_client->custom_event_cb));
+
+       MC_SAFE_FREE(interface_name);
+
+       return ret;
+}
+
+int mc_client_unset_custom_event_received_cb(mc_client_h client)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+       mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       char *interface_name = mc_util_get_interface_name(MC_CLIENT, mc_client->client_name);
+       ret = mc_ipc_unregister_listener(&mc_client->listeners, mc_client->dconn, interface_name, MC_DBUS_SIGNAL_NAME_CUSTOM_EVENT);
+
+       mc_client->custom_event_cb.callback = NULL;
+       mc_client->custom_event_cb.user_data = NULL;
+
+       MC_SAFE_FREE(interface_name);
+
+       return ret;
+}
+
+int mc_client_send_event_reply(mc_client_h client, const char *server_name, const char *request_id, int result_code, bundle *data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       char *message = NULL;
+       char *bundle_str = NULL;
+       media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+       mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       mc_retvm_if(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+       mc_retvm_if(!MC_STRING_VALID(request_id), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "request_id is NULL");
+
+       ret = mc_util_bundle_to_string(data, &bundle_str);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Error when make string from bundle");
+
+       message = g_strdup_printf("%s%s%d%s%s", mc_client->client_name, MC_STRING_DELIMITER, result_code, MC_STRING_DELIMITER, bundle_str);
+       MC_SAFE_G_FREE(bundle_str);
+       mc_retvm_if(message == NULL, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "Error when making message");
+
+       char *interface_name = mc_util_get_interface_name(MC_SERVER, server_name);
+       ret = mc_ipc_send_reply(mc_client->dconn, NULL, interface_name, MC_DBUS_SIGNAL_NAME_EVENT_REPLY, message, request_id);
+       if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+               mc_error("Error mc_ipc_send_message [%d]", ret);
+
+       MC_SAFE_G_FREE(message);
+       MC_SAFE_G_FREE(interface_name);
+
+       return ret;
+}
+
 int mc_client_destroy(mc_client_h client)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -1571,6 +1687,10 @@ int mc_client_destroy(mc_client_h client)
        if (ret != MEDIA_CONTROLLER_ERROR_NONE)
                mc_error("Error mc_ipc_unregister_all_listener [%d]", ret);
 
+       ret = mc_db_delete_client_address_from_client_list(mc_client->db_handle, mc_client->client_name);
+       if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+               mc_error("fail mc_db_delete_client_address_from_client_list [%d]", ret);
+
        /*Send Disconnection Msg to Server*/
        ret = mc_ipc_send_message_to_server(MC_MSG_SERVER_DISCONNECTION, MC_PRIV_TYPE_CLIENT, MC_SERVER_DISCONNECTION_MSG);
        if (ret != MEDIA_CONTROLLER_ERROR_NONE)
index 416e4eb..42b2670 100755 (executable)
@@ -644,6 +644,40 @@ int mc_db_delete_server_address_from_server_list(void *handle, const char *addre
        return ret;
 }
 
+int mc_db_insert_client_address_into_client_list(void *handle, const char *address)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       char *sql_str = NULL;
+
+       mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       mc_retvm_if(!MC_STRING_VALID(address), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "invalid address");
+
+       sql_str = g_strdup_printf("%s%s%s", MC_DB_CMD_UPDATE_CLIENT_LIST, MC_STRING_DELIMITER, address);
+
+       ret = __mc_db_update_db(handle, MC_PRIV_TYPE_CLIENT, sql_str);
+
+       MC_SAFE_FREE(sql_str);
+
+       return ret;
+}
+
+int mc_db_delete_client_address_from_client_list(void *handle, const char *address)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       char *sql_str = NULL;
+
+       mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       mc_retvm_if(!MC_STRING_VALID(address), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "invalid address");
+
+       sql_str = g_strdup_printf("%s%s%s", MC_DB_CMD_REMOVE_CLIENT_LIST, MC_STRING_DELIMITER, address);
+
+       ret = __mc_db_update_db(handle, MC_PRIV_TYPE_CLIENT, sql_str);
+
+       MC_SAFE_FREE(sql_str);
+
+       return ret;
+}
+
 int mc_db_disconnect(void *handle)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -740,6 +774,49 @@ int mc_db_check_server_table_exist(void *handle, const char *server_name, bool *
        return MEDIA_CONTROLLER_ERROR_NONE;
 }
 
+int mc_db_check_client_table_exist(void *handle, const char *client_name, bool *exist)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       char *sql_str = NULL;
+       sqlite3_stmt *stmt = NULL;
+       int count = 0;
+
+       mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       mc_retvm_if(client_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+       sql_str = sqlite3_mprintf("SELECT COUNT(*) FROM '%q' WHERE client_name='%q'", MC_DB_TABLE_CLIENT_LIST, client_name);
+       mc_retvm_if(!MC_STRING_VALID(sql_str), MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "SQL string is null");
+
+       ret = sqlite3_prepare_v2(handle, sql_str, strlen(sql_str), &stmt, NULL);
+       if (SQLITE_OK != ret) {
+               mc_error("prepare error [%s]", sqlite3_errmsg(handle));
+               SQLITE3_SAFE_FREE(sql_str);
+               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+       }
+
+       ret = sqlite3_step(stmt);
+       if (SQLITE_ROW != ret) {
+               mc_error("end of row [%s]", sqlite3_errmsg(handle));
+               SQLITE3_FINALIZE(stmt);
+               SQLITE3_SAFE_FREE(sql_str);
+               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+       }
+
+       count = sqlite3_column_int(stmt, 0);
+
+       mc_debug("table count [%d]", count);
+
+       if (count > 0)
+               *exist = TRUE;
+       else
+               *exist = FALSE;
+
+       SQLITE3_FINALIZE(stmt);
+       SQLITE3_SAFE_FREE(sql_str);
+
+       return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
 int mc_db_foreach_server_list(void *handle, mc_activated_server_cb callback, void *user_data)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -784,6 +861,50 @@ int mc_db_foreach_server_list(void *handle, mc_activated_server_cb callback, voi
        return MEDIA_CONTROLLER_ERROR_NONE;
 }
 
+int mc_db_foreach_client_list(void *handle, mc_activated_client_cb callback, void *user_data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       sqlite3 *db_handle = (sqlite3 *)handle;
+       char *sql_str = NULL;
+       sqlite3_stmt *stmt = NULL;
+
+       mc_retvm_if(db_handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       sql_str = sqlite3_mprintf("SELECT client_name FROM '%q';", MC_DB_TABLE_CLIENT_LIST);
+       mc_retvm_if(!MC_STRING_VALID(sql_str), MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "SQL string is null");
+       ret = sqlite3_prepare_v2(db_handle, sql_str, strlen(sql_str), &stmt, NULL);
+       if (SQLITE_OK != ret) {
+               mc_error("prepare error [%s]", sqlite3_errmsg(db_handle));
+               SQLITE3_SAFE_FREE(sql_str);
+               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+       }
+
+       ret = sqlite3_step(stmt);
+       if (SQLITE_ROW != ret) {
+               mc_error("[No-Error] There is no client list [%s]", sqlite3_errmsg(db_handle));
+               SQLITE3_FINALIZE(stmt);
+               SQLITE3_SAFE_FREE(sql_str);
+               return MEDIA_CONTROLLER_ERROR_NONE;
+       }
+
+       while (SQLITE_ROW == ret) {
+               char *client_name = NULL;
+               client_name = strdup((char *)sqlite3_column_text(stmt, 0));
+               if (callback(client_name, user_data) == false) {
+                       MC_SAFE_FREE(client_name);
+                       break;
+               }
+               MC_SAFE_FREE(client_name);
+
+               ret = sqlite3_step(stmt);
+       }
+
+       SQLITE3_FINALIZE(stmt);
+       SQLITE3_SAFE_FREE(sql_str);
+
+       return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
 int mc_db_update_server_and_playback_state(void *handle, const char *server_name, mc_server_state_e server_state, mc_playback_states_e playback_state)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
index c044539..6bb43f4 100755 (executable)
@@ -53,17 +53,16 @@ static void __mc_ipc_signal_cb(GDBusConnection *connection,
        mc_debug("__mc_ipc_signal_cb Received :");
 
        gchar *message = NULL;
-       gchar * request_id = NULL;
+       gchar *request_id = NULL;
 
-       g_variant_get(parameters, "(s&s)", &request_id, &message);
+       g_variant_get(parameters, "(&s&s)", &request_id, &message);
        if (!message) {
                mc_error("g_variant_get() fail");
                return;
        }
 
-       if ((request_id != NULL) && (!g_strcmp0(request_id, DEFAULT_REQ_ID))) {
+       if ((request_id != NULL) && (!g_strcmp0(request_id, DEFAULT_REQ_ID)))
                request_id = NULL;
-       }
 
        char *key = __make_key_for_map(interface_name, signal_name);
        if (key == NULL) {
@@ -80,6 +79,7 @@ static void __mc_ipc_signal_cb(GDBusConnection *connection,
                        break;
                }
        }
+
        MC_SAFE_FREE(key);
 }
 
index 9dfe97e..3493748 100755 (executable)
@@ -400,6 +400,38 @@ static void __server_custom_cmd_cb(const char *interface_name, const char *signa
        g_strfreev(params);
 }
 
+static void __server_event_reply_received_cb(const char *interface_name, const char *signal_name, const char *message, const char *request_id, void *user_data)
+{
+       gchar **params = NULL;
+       int result_code = 0;
+       int enc_size = 0;
+       bundle *bundle_data = NULL;
+
+       media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data;
+       mc_retm_if(reciever == NULL, "reciever is NULL");
+
+       mc_cmd_reply_received_cb callback = (mc_cmd_reply_received_cb)reciever->callback;
+       mc_retm_if(reciever->callback == NULL, "reply_cb is NULL");
+
+       mc_debug("__server_event_reply_received_cb(%s, %s, %s, %s, %p)", interface_name, signal_name, message, request_id, user_data);
+
+       params = g_strsplit(message, MC_STRING_DELIMITER, 0);
+       mc_retm_if(params == NULL, "invalid custom data");
+
+       if (params[1] != NULL)
+               mc_retm_if(MEDIA_CONTROLLER_ERROR_NONE != mc_safe_strtoi(params[1], &result_code), "getting result_code is failed");
+
+       if (params[2] != NULL)
+               mc_retm_if(MEDIA_CONTROLLER_ERROR_NONE != mc_safe_strtoi(params[2], &enc_size), "getting message is failed");
+
+       if (enc_size > 0)
+               bundle_data = bundle_decode((bundle_raw *)params[3], enc_size);
+
+       callback(params[0], request_id, result_code, bundle_data, reciever->user_data);
+
+       g_strfreev(params);
+}
+
 static int __mc_server_current_is_latest(media_controller_server_s *mc_server, bool *is_latest)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -468,6 +500,37 @@ static int __mc_server_send_message(media_controller_server_s *mc_server, const
        return ret;
 }
 
+static int __mc_server_send_event(mc_server_h server, const char *client_name, const char *command_type, const char *event, const char *signal_name, const char *message, char **request_id)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_server_s *mc_server = (media_controller_server_s *)server;
+       bool exist_server = FALSE;
+       char *interface_name = NULL;
+
+       mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       mc_retvm_if(!MC_STRING_VALID(client_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name");
+       mc_retvm_if(!MC_STRING_VALID(command_type), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid command_type");
+       mc_retvm_if(!MC_STRING_VALID(signal_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid signal_name");
+       mc_retvm_if(!MC_STRING_VALID(message), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid message");
+
+       ret = mc_db_check_client_table_exist(mc_server->db_handle, client_name, &exist_server);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Error mc_db_check_client_table_exist [%d]", ret);
+       mc_retvm_if(exist_server == FALSE, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Error Invalid client_name");
+
+       ret = mc_util_set_command_available(MC_PRIV_TYPE_SERVER, mc_server->server_name, command_type, event);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Error mc_util_set_command_available [%d]", ret);
+
+       interface_name = mc_util_get_interface_name(MC_CLIENT, client_name);
+
+       ret = mc_ipc_send_message(mc_server->dconn, NULL, interface_name, signal_name, message, request_id);
+       if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+               mc_error("Error mc_ipc_send_message [%d]", ret);
+
+       MC_SAFE_G_FREE(interface_name);
+
+       return ret;
+}
+
 int mc_server_set_playback_state(mc_server_h server, mc_playback_states_e state)
 {
        media_controller_server_s *mc_server = (media_controller_server_s *)server;
@@ -1305,6 +1368,83 @@ int mc_server_send_cmd_reply(mc_server_h server, const char *client_name, const
        return ret;
 }
 
+int mc_server_foreach_client(mc_server_h server, mc_activated_client_cb callback, void *user_data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+       mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+       ret = mc_db_foreach_client_list(mc_server->db_handle, callback, user_data);
+
+       return ret;
+}
+
+int mc_server_send_custom_event(mc_server_h server, const char *client_name, const char *event, bundle *data, char **request_id)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       char *message = NULL;
+       char *bundle_str = NULL;
+       media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+       mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       mc_retvm_if(!MC_STRING_VALID(client_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid client_name");
+       mc_retvm_if(event == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "event is NULL");
+
+       ret = mc_util_bundle_to_string(data, &bundle_str);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Error when make string from bundle");
+
+       message = g_strdup_printf("%s%s%s%s%s", mc_server->server_name, MC_STRING_DELIMITER, event, MC_STRING_DELIMITER, bundle_str);
+       MC_SAFE_G_FREE(bundle_str);
+       mc_retvm_if(message == NULL, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "Error when making message");
+
+       ret = __mc_server_send_event(server, client_name, MC_EVENT_CUSTOM, event, MC_DBUS_SIGNAL_NAME_CUSTOM_EVENT, message, request_id);
+
+       MC_SAFE_G_FREE(message);
+
+       return ret;
+}
+
+int mc_server_set_event_reply_received_cb(mc_server_h server, mc_server_event_reply_received_cb callback, void *user_data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+       mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+       mc_retvm_if(mc_server->event_reply_receiver.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set");
+
+       mc_server->event_reply_receiver.callback = callback;
+       mc_server->event_reply_receiver.user_data = user_data;
+
+       char *interface_name = mc_util_get_interface_name(MC_SERVER, mc_server->server_name);
+       ret = mc_ipc_register_listener(&mc_server->listeners, mc_server->dconn, interface_name, MC_DBUS_SIGNAL_NAME_EVENT_REPLY,
+                                               __server_event_reply_received_cb, (void *)&(mc_server->event_reply_receiver));
+
+       MC_SAFE_FREE(interface_name);
+
+       return ret;
+}
+
+int mc_server_unset_event_reply_received_cb(mc_server_h server)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+       mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       char *interface_name = mc_util_get_interface_name(MC_SERVER, mc_server->server_name);
+       ret = mc_ipc_unregister_listener(&mc_server->listeners, mc_server->dconn, interface_name, MC_DBUS_SIGNAL_NAME_EVENT_REPLY);
+
+       mc_server->event_reply_receiver.callback = NULL;
+       mc_server->event_reply_receiver.user_data = NULL;
+
+       MC_SAFE_FREE(interface_name);
+
+       return ret;
+}
+
 int mc_server_create(mc_server_h *server)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
index 773fc32..ddcaf50 100755 (executable)
@@ -124,6 +124,19 @@ static int __mc_create_server_list_table(sqlite3 *handle)
        return ret;
 }
 
+static int __mc_create_client_list_table(sqlite3 *handle)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       char *sql_str = NULL;
+
+       sql_str = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (client_name TEXT PRIMARY KEY);", MC_DB_TABLE_CLIENT_LIST);
+
+       ret = mc_db_util_update_db(handle, sql_str);
+
+       SQLITE3_SAFE_FREE(sql_str);
+       return ret;
+}
+
 static int __mc_create_playlist_table(sqlite3 *handle)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -331,6 +344,9 @@ int mc_db_util_create_tables(void *handle)
        ret = __mc_create_server_list_table(db_handle);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "create server_list table failed!err= [%d]", ret);
 
+       ret = __mc_create_client_list_table(db_handle);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "create client_list table failed!err= [%d]", ret);
+
        ret = __mc_create_playlist_table(db_handle);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "create playlist table failed!err= [%d]", ret);
 
@@ -494,6 +510,9 @@ int mc_db_parse_and_update_db(uid_t uid, const char *data, int data_size)
        } else if (strncmp(MC_DB_CMD_UPDATE_SERVER_LIST, params[0], strlen(MC_DB_CMD_UPDATE_SERVER_LIST)) == 0) {
                sql_str = sqlite3_mprintf("INSERT INTO '%q' (server_name) VALUES ('%q');", MC_DB_TABLE_SERVER_LIST, params[1]);
 
+       } else if (strncmp(MC_DB_CMD_UPDATE_CLIENT_LIST, params[0], strlen(MC_DB_CMD_UPDATE_CLIENT_LIST)) == 0) {
+               sql_str = sqlite3_mprintf("INSERT INTO '%q' (client_name) VALUES ('%q');", MC_DB_TABLE_CLIENT_LIST, params[1]);
+
        } else if (strncmp(MC_DB_CMD_UPDATE_STATE_PLAYBACK, params[0], strlen(MC_DB_CMD_UPDATE_STATE_PLAYBACK)) == 0) {
                if (params[2] == NULL || params[3] == NULL) {
                        mc_error("wrong query");
@@ -556,6 +575,9 @@ int mc_db_parse_and_update_db(uid_t uid, const char *data, int data_size)
        } else if (strncmp(MC_DB_CMD_REMOVE_SERVER_LIST, params[0], strlen(MC_DB_CMD_REMOVE_SERVER_LIST)) == 0) {
                sql_str = sqlite3_mprintf("DELETE FROM %q WHERE server_name = '%q';", MC_DB_TABLE_SERVER_LIST, params[1]);
 
+       } else if (strncmp(MC_DB_CMD_REMOVE_CLIENT_LIST, params[0], strlen(MC_DB_CMD_REMOVE_CLIENT_LIST)) == 0) {
+               sql_str = sqlite3_mprintf("DELETE FROM %q WHERE client_name = '%q';", MC_DB_TABLE_CLIENT_LIST, params[1]);
+
        } else if (strncmp(MC_DB_CMD_REMOVE_SERVER, params[0], strlen(MC_DB_CMD_REMOVE_SERVER)) == 0) {
                sql_str = sqlite3_mprintf("DROP TABLE IF EXISTS '%q'", params[1]);
 
index f086a84..1c3f89f 100755 (executable)
@@ -204,6 +204,29 @@ void _mc_cmd_reply_received_cb(const char *server_name, const char *request_id,
        }
 }
 
+void _mc_custom_event_received_cb(const char *server_name, const char *request_id, const char *event, bundle *data, void *user_data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+       const char *bundle_key = "key1";
+       char *bundle_value = NULL;
+
+       if (data)
+               bundle_get_str(data, bundle_key, &bundle_value);
+
+       g_print("recieved request_id:[%s] event:[%s] bundle:[%s, %s] from [%s]\n",
+                       request_id, event, bundle_key, bundle_value, server_name);
+
+       bundle *bundle_reply = bundle_create();
+       bundle_add_str(bundle_reply, "key1", "result1");
+
+       ret = mc_client_send_event_reply(g_mc_client, server_name, request_id, 0, bundle_reply);
+       if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+               g_print("Fail to mc_client_send_event_reply\n");
+
+       bundle_free(bundle_reply);
+}
+
 static gboolean _create()
 {
        g_print("== create \n");
@@ -261,6 +284,9 @@ static gboolean _set_callback()
        ret = mc_client_set_cmd_reply_received_cb(g_mc_client, _mc_cmd_reply_received_cb, NULL);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_set_reply_received_cb [%d]", ret);
 
+       ret = mc_client_set_custom_event_received_cb(g_mc_client, _mc_custom_event_received_cb, NULL);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_set_custom_event_received_cb [%d]", ret);
+
        mc_debug_fleave();
 
        return ret;
@@ -293,6 +319,9 @@ static gboolean _unset_callback()
        ret = mc_client_unset_cmd_reply_received_cb(g_mc_client);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_unset_reply_received_cb [%d]", ret);
 
+       ret = mc_client_unset_custom_event_received_cb(g_mc_client);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_unset_custom_event_received_cb [%d]", ret);
+
        mc_debug_fleave();
 
        return TRUE;
index 9f29425..1ff5af2 100755 (executable)
@@ -40,6 +40,11 @@ static mc_shuffle_mode_e g_shuffle_mode;
 static mc_repeat_mode_e g_repeat_mode;
 static mc_playlist_update_mode_e g_playlist_mode;
 
+/* for sending event */
+static char *g_event_name = NULL;
+static char *g_client_name = NULL;
+static char *g_request_id = NULL;
+
 GMainLoop *mainloop = NULL;
 
 #define MAX_STRING_LEN    2048
@@ -53,6 +58,7 @@ enum {
        CURRENT_STATE_MAIN_MENU,
        CURRENT_STATE_INFORMATION_SET_MENU,
        CURRENT_STATE_INFORMATION_UPDATE_MENU,
+       CURRENT_STATE_SEND_EVENT_MENU,
 };
 
 enum {
@@ -69,6 +75,7 @@ enum {
 ---------------------------------------------------------------------------*/
 int g_menu_state = CURRENT_STATE_MAIN_MENU;
 int g_menu_set_state = CURRENT_STATE_SET_MODE_NONE;
+int g_menu_send_event = 0;
 
 /*---------------------------------------------------------------------------
 |    LOCAL FUNCTION PROTOTYPES:                       |
@@ -346,6 +353,32 @@ void __custom_cmd_received_cb(const char *client_name, const char *request_id, c
                g_free(bundle_data);
 }
 
+void __event_reply_received_cb(const char *client_name, const char *request_id, const int result_code, bundle *data, void *user_data)
+{
+       const char *bundle_key = "key1";
+       char *bundle_value = NULL;
+
+       if (data) {
+               bundle_get_str(data, bundle_key, &bundle_value);
+       }
+
+       if (g_strcmp0(g_request_id, request_id) != 0) {
+               g_printf("[recieved event reply] wrong request_id: %s \n", request_id);
+       }
+
+       g_print("[recieved event reply] request_id:[%s] result:[%d] bundle:[%s, %s] from [%s] \n",
+               request_id, result_code, bundle_key, bundle_value, client_name);
+}
+
+bool _mc_activated_client_cb(const char *client_name, void *user_data)
+{
+       char **_client = (char **)user_data;
+       if (_client == NULL) return FALSE;
+       *_client = g_strdup(client_name);
+       g_print("== success activated client_name: %s \n", client_name);
+       return FALSE;
+}
+
 static gboolean _create()
 {
        g_print("== create \n");
@@ -414,6 +447,12 @@ static gboolean _set_cb()
                return FALSE;
        }
 
+       ret = mc_server_set_event_reply_received_cb(g_mc_server, __event_reply_received_cb, NULL);
+       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+               g_print("Fail to set mc_server_set_custom_cmd_received_cb");
+               return FALSE;
+       }
+
        g_print("== success set default callback \n");
 
        return TRUE;
@@ -550,6 +589,65 @@ static gboolean _update_info(int type)
        return TRUE;
 }
 
+static gboolean _send_event(int type, char *cmd)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       bundle *bundle_data = NULL;
+
+       g_print("== send event menu [%d] \n", type);
+
+       switch (type) {
+       case 1:
+               if (g_client_name != NULL) {
+                       g_free(g_client_name);
+                       g_client_name = NULL;
+               }
+               ret = mc_server_foreach_client(g_mc_server, _mc_activated_client_cb, &g_client_name);
+               break;
+
+       case 2:
+               if (g_event_name != NULL) {
+                       g_free(g_event_name);
+                       g_event_name = NULL;
+               }
+               g_event_name = g_strdup(cmd);
+               if (g_event_name == NULL) {
+                       g_print("Fail to set event_name \n");
+                       return FALSE;
+               }
+               g_print("set event_name: %s \n", g_event_name);
+               break;
+
+       case 3:
+               if (g_request_id != NULL) {
+                       g_free(g_request_id);
+                       g_request_id = NULL;
+               }
+
+               bundle_data = bundle_create();
+               if (bundle_data == NULL) {
+                       g_print("Fail to create bundle \n");
+                       return FALSE;
+               }
+               bundle_add_str(bundle_data, "key1", "ev_val1");
+
+               ret = mc_server_send_custom_event(g_mc_server, g_client_name, g_event_name, bundle_data, &g_request_id);
+               if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+                       g_print("Fail to mc_server_send_custom_event\n");
+
+               bundle_free(bundle_data);
+               g_print(" == success send event(req_id:%s) \n", g_request_id);
+               break;
+       default:
+               g_print(" == unknown type!\n");
+               return TRUE;
+       }
+
+       g_print(" == success event menu \n");
+
+       return TRUE;
+}
+
 static gboolean _destroy()
 {
        g_print("== destroy \n");
@@ -578,6 +676,12 @@ void quit(void)
        g_main_loop_quit(mainloop);
 }
 
+void reset_current_send_menu_state()
+{
+       g_menu_send_event = 0;
+       return;
+}
+
 void reset_current_set_menu_state()
 {
        g_menu_set_state = CURRENT_STATE_SET_MODE_NONE;
@@ -624,6 +728,21 @@ static void display_set_info_menu(void)
 
 }
 
+static void display_send_menu(void)
+{
+       g_print("\n");
+       g_print("====================================================\n");
+       g_print("    media controller test(server): Send event menu\n");
+       g_print("----------------------------------------------------\n");
+       g_print("1. foreach activated client \n");
+       g_print("2. enter event name \n");
+       g_print("3. send event \n");
+       g_print("0. back \n");
+       g_print("----------------------------------------------------\n");
+       g_print("====================================================\n");
+
+}
+
 static void display_main_menu(void)
 {
        g_print("\n");
@@ -634,6 +753,7 @@ static void display_main_menu(void)
        g_print("2. set default command callback \n");
        g_print("3. set information to client \n");
        g_print("4. update information to client \n");
+       g_print("6. send event to client \n");
        g_print("9. destroy media controller server \n");
        g_print("0. quit \n");
        g_print("----------------------------------------------------\n");
@@ -649,6 +769,8 @@ static void display_menu(void)
                display_set_info_menu();
        else if (g_menu_state == CURRENT_STATE_INFORMATION_UPDATE_MENU)
                display_update_info_menu();
+       else if (g_menu_state == CURRENT_STATE_SEND_EVENT_MENU)
+               display_send_menu();
        else
                g_print("*** Unknown status.\n");
 
@@ -700,6 +822,30 @@ void _interpret_set_info_menu(char *cmd)
        }
 }
 
+void _interpret_send_menu(char *cmd)
+{
+       int len = strlen(cmd);
+
+       if (len == 1) {
+               if (!strncmp(cmd, "1", len)) {
+                       _send_event(1, cmd);
+                       reset_current_send_menu_state();
+                       display_menu();
+               } else if (!strncmp(cmd, "2", len)) {
+                       g_menu_send_event = 2;
+               } else if (!strncmp(cmd, "3", len)) {
+                       _send_event(3, cmd);
+                       reset_current_send_menu_state();
+                       display_menu();
+               } else if (!strncmp(cmd, "0", len)) {
+                       reset_current_menu_state();
+                       display_menu();
+               }
+       } else {
+               g_print("wrong command\n");
+       }
+}
+
 void _interpret_main_menu(char *cmd)
 {
        int len = strlen(cmd);
@@ -713,6 +859,8 @@ void _interpret_main_menu(char *cmd)
                        g_menu_state = CURRENT_STATE_INFORMATION_SET_MENU;
                else if (!strncmp(cmd, "4", len))
                        g_menu_state = CURRENT_STATE_INFORMATION_UPDATE_MENU;
+               else if (!strncmp(cmd, "6", len))
+                       g_menu_state = CURRENT_STATE_SEND_EVENT_MENU;
                else if (!strncmp(cmd, "9", len))
                        _destroy();
                else if (!strncmp(cmd, "0", len))
@@ -752,6 +900,19 @@ static void interpret_cmd(char *cmd)
                _interpret_update_info_menu(cmd);
                display_menu();
                break;
+       case CURRENT_STATE_SEND_EVENT_MENU:
+               switch (g_menu_send_event) {
+               case 0:
+                       _interpret_send_menu(cmd);
+                       break;
+               case 2:
+                       _send_event(g_menu_send_event, cmd);
+                       reset_current_send_menu_state();
+                       display_menu();
+               default:
+                       break;
+               }
+               break;
        default:
                g_print("Invalid command\n");
        }