[ACR-1298] Add new APIs for Setting age rating and Searching. 44/188344/21 accepted/tizen/unified/20180914.143103 submit/tizen/20180914.043733
authorhj kim <backto.kim@samsung.com>
Tue, 4 Sep 2018 05:50:40 +0000 (14:50 +0900)
committerhj kim <backto.kim@samsung.com>
Fri, 14 Sep 2018 02:48:13 +0000 (11:48 +0900)
Change-Id: I9abb5c53668d0d05b7055d2cc476b1ced28642c4

15 files changed:
doc/media_controller_doc.h
include/media_controller_client.h
include/media_controller_metadata.h
include/media_controller_playlist.h
include/media_controller_private.h
include/media_controller_server.h
include/media_controller_type.h
packaging/capi-media-controller.spec
src/media_controller_client.c
src/media_controller_db.c
src/media_controller_metadata.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 cacc03f..88c3416 100755 (executable)
 /**
 * @ingroup CAPI_MEDIA_CONTROLLER_MODULE
 * @defgroup CAPI_MEDIA_CONTROLLER_ABILITY_MODULE Media Controller Playback ability
-* @brief The @ref CAPI_MEDIA_CONTROLLER_ABILITY_MODULE API provides functions for the playback ability fo the media controller server.
+* @brief The @ref CAPI_MEDIA_CONTROLLER_ABILITY_MODULE API provides functions for the playback ability for the media controller server.
 * @section CAPI_MEDIA_CONTROLLER_ABILITY_MODULE_HEADER Required Header
-*      \#include <media_controller_client.h>
+*      \#include <media_controller_metadata.h>
 *
 * @section CAPI_MEDIA_CONTROLLER_ABILITY_MODULE_OVERVIEW Overview
 * The @ref CAPI_MEDIA_CONTROLLER_ABILITY_MODULE API allows you to get playback action ability (#mc_playback_action_is_supported()). \n
 *
 */
 
+/**
+* @ingroup CAPI_MEDIA_CONTROLLER_MODULE
+* @defgroup CAPI_MEDIA_CONTROLLER_SEARCH_MODULE Media Controller Search
+* @brief The @ref CAPI_MEDIA_CONTROLLER_SEARCH_MODULE API provides functions for search for the media controller server.
+* @section CAPI_MEDIA_CONTROLLER_SEARCH_MODULE_HEADER Required Header
+*      \#include <media_controller_metadata.h>
+*
+* @section CAPI_MEDIA_CONTROLLER_SEARCH_MODULE_OVERVIEW Overview
+* The @ref CAPI_MEDIA_CONTROLLER_SEARCH_MODULE API allows you to create handle for searching (#mc_search_create()). \n
+* You can set and get search conditions (#mc_search_set_condition() and #mc_search_foreach_condition()). \n
+* And copy the search by using #mc_search_clone(). And if you don't use handle anymore, you have to destroy it(#mc_search_destroy()).
+*
+*/
+
 
 #endif /* __TIZEN_MEDIA_CONTROLLER_DOC_H__ */
 
index 3736d9e..d5c8268 100755 (executable)
@@ -73,7 +73,7 @@ typedef void (*mc_server_state_updated_cb)(const char *server_name, mc_server_st
  * @see mc_client_set_playback_updated_cb()
  * @see mc_client_get_playback_state()
  * @see mc_client_get_playback_position()
- * @see mc_client_get_playlist_item_index()
+ * @see mc_client_get_playlist_item_info()
  */
 typedef void (*mc_playback_updated_cb)(const char *server_name, mc_playback_h playback, void *user_data);
 
@@ -310,7 +310,7 @@ typedef bool (*mc_subscribed_server_cb)(const char *server_name, void *user_data
  *
  * @remarks The callback is called in the dbus event loop.
  *              The @a server_name, @a playlist_name and @a playlist should not be released by the application. \n
- *              The @a server_name and @ playlist_name can be used only in the callback. To use outside, make a copy.
+ *              The @a server_name and @a playlist_name can be used only in the callback. To use outside, make a copy.
  *              And @a playlist also can be used only in the callback. To use outside, make a copy using mc_playlist_clone(). \n
  *
  * @param[in] server_name The app_id of the media controller server which sent the notification.
@@ -1270,6 +1270,26 @@ int mc_client_get_playlist_item_info(mc_playback_h playback, char **playlist_nam
 int mc_client_get_playback_content_type(mc_playback_h playback, mc_content_type_e *content_type);
 
 /**
+ * @brief Gets the age rating of the content.
+ * @details Gets the age rating of the current playing media.
+ * @since_tizen 5.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param[in] playback    The handle to playback
+ * @param[out] age_rating    Age rating of the content
+ * @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 The playback update callback should be set with mc_client_set_playback_updated_cb().
+ * @see mc_client_set_playback_updated_cb()
+ */
+int mc_client_get_age_rating(mc_playback_h playback, mc_content_age_rating_e *age_rating);
+
+/**
  * @brief Destroys playback.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
@@ -1799,13 +1819,44 @@ int mc_client_send_playlist_cmd(mc_client_h client, const char *server_name, con
 int mc_client_send_custom_cmd(mc_client_h client, const char *server_name, const char *command, bundle *data, char **request_id);
 
 /**
+ * @brief Sends the search command to server.
+ * @details If the server sends the result of the command, the media controller client will get the result of the search command by mc_cmd_reply_received_cb() callback.
+ * @since_tizen 5.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @remarks The @a request_id should be released using free().\n
+ *          If the @a request_id is null, the server will not send the reply of the command.
+ *
+ * @param[in] client    The handle to the media controller client
+ * @param[in] server_name    The app_id of the media controller server
+ * @param[in] search      The search handle to be sent
+ * @param[out] request_id   The id of the command request, it will be passed to the mc_cmd_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_PERMISSION_DENIED Permission denied
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @pre Create search handle and set data by calling mc_search_create() and mc_search_set_condition().
+ * @see mc_client_create()
+ * @see mc_client_set_cmd_reply_received_cb()
+ * @see mc_search_create()
+ * @see mc_search_set_condition()
+ */
+int mc_client_send_search_cmd(mc_client_h client, const char *server_name, mc_search_h search, char **request_id);
+
+/**
  * @brief Destroys client.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  * @param[in] client The handle to the media controller client
  * @return @c 0 on success,
  *         otherwise a negative error value
- * @retval #METADATA_EXTRACTOR_ERROR_NONE Successful
- * @retval #METADATA_EXTRACTOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_OPERATION Invalid operation
  * @pre Create a media controller client handle by calling mc_client_create().
  * @see mc_client_create()
  */
index 888d9e6..bb6ba70 100755 (executable)
@@ -38,7 +38,7 @@ extern "C" {
 /**
  * @brief Clones a media controller metadata handle.
  * @details This function copies the media controller metadata handle from a source to
- *          destination. The mc_metadata_h is created internally and available through media controller metadata functions.
+ *          destination. The #mc_metadata_h is created internally and available through media controller metadata functions.
  *
  * @since_tizen @if MOBILE 4.0 @elseif WEARABLE 5.0 @endif
  *
@@ -116,7 +116,7 @@ int mc_metadata_get(mc_metadata_h metadata, mc_meta_e attribute, char **value);
 /**
  * @brief Clones a playback ability handle.
  * @details This function copies the playback ability handle from a source to
- *          destination. The mc_playback_ability_h is created internally and available through playback ability functions.
+ *          destination. The #mc_playback_ability_h is created internally and available through playback ability functions.
  *
  * @since_tizen 5.0
  *
@@ -184,6 +184,138 @@ int mc_playback_action_is_supported(mc_playback_ability_h ability, mc_playback_a
 * @}
 */
 
+/**
+ * @addtogroup CAPI_MEDIA_CONTROLLER_SEARCH_MODULE
+ * @{
+ */
+
+/**
+ * @brief Called for every search condition information in the obtained list of search.
+ * @details Iterates over a search list.
+ *
+ * @since_tizen 5.0
+ *
+ * @remarks The callback is called in the main loop.
+ *              The @a search_keyword and @a data should not be released by the application. \n
+ *              The @a search_keyword and @a data can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] content_type The content type to search
+ * @param[in] category The category to search
+ * @param[in] search_keyword The key word to search
+ * @param[in] data The extra data
+ * @param[in] user_data The user data passed from the foreach function
+ *
+ * @return @c true to continue with the next iteration of the loop,
+ *         otherwise @c false to break out of the loop
+ *
+ * @pre mc_search_foreach_condition() will invoke this function.
+ * @see mc_search_foreach_condition()
+ */
+typedef bool (*mc_search_condition_cb)(mc_content_type_e content_type, mc_search_category_e category, const char *search_keyword, bundle *data, void *user_data);
+
+/**
+ * @brief Creates a media controller search handle.
+ * @since_tizen 5.0
+ *
+ * @remarks The @a search should be released using @c mc_search_destroy().
+ *
+ * @param[out] search The handle to search
+ * @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
+ * @see mc_search_set_condition()
+ * @see mc_search_foreach_condition()
+ */
+int mc_search_create(mc_search_h *search);
+
+/**
+ * @brief Sets the information to search.
+ * @details Sets the information to search. You can set various search condition by calling this function for the same search handle. \n
+ *            But it's not allowed to set more than 20 conditions. If you try to set more than 20 conditions, this function will return #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER.
+ * @since_tizen 5.0
+ *
+ * @param[in] search The handle to search
+ * @param[in] content_type The content type to search
+ * @param[in] category The category to search
+ * @param[in] search_keyword The key word to search
+ * @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
+ * @pre mc_search_create()
+ * @see mc_search_foreach_condition()
+ */
+int mc_search_set_condition(mc_search_h search, mc_content_type_e content_type, mc_search_category_e category, const char *search_keyword, bundle *data);
+
+/**
+ * @brief Destroys search.
+ * @since_tizen 5.0
+ * @param[in] search The handle to search
+ * @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_INVALID_OPERATION Invalid operation
+ * @pre Create a media controller search handle by calling mc_search_create().
+ * @see mc_search_create()
+ */
+int mc_search_destroy(mc_search_h search);
+
+/**
+ * @brief Retrieves all search conditions.
+ * @details This function gets all search conditions set.
+ *            The callback function will be invoked for every retrieved search condition.
+ *            If there were no search conditions set with mc_search_set_condition(), this function will return #MEDIA_CONTROLLER_ERROR_NONE, and the callback will not be invoked.
+ * @since_tizen 5.0
+ *
+ * @param[in] search    The handle to search
+ * @param[in] callback      The callback function to be invoked.
+ * @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
+ *
+ * @pre Create a media controller search handle by calling mc_search_create().
+ * @pre Set the search conditions by calling mc_search_set_condition().
+ * @see mc_search_create()
+ * @see mc_search_set_condition()
+ */
+int mc_search_foreach_condition(mc_search_h search, mc_search_condition_cb callback, void *user_data);
+
+/**
+ * @brief Clones a media controller search handle.
+ * @details This function copies the media controller search handle from a source to
+ *          destination. The #mc_search_h is created internally and available through media controller search functions.
+ *
+ * @since_tizen 5.0
+ *
+ * @remarks The @a dst should be released using @c mc_search_destroy().
+ *
+ * @param[in] src The source handle to the media controller search
+ * @param[out] dst The destination handle to the media controller search
+ *
+ * @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
+ *
+ * @see mc_search_destroy()
+ */
+int mc_search_clone(mc_search_h src, mc_search_h *dst);
+
+/**
+* @}
+*/
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index b9d3aea..dea1a96 100755 (executable)
@@ -140,7 +140,7 @@ int mc_playlist_foreach_item(mc_playlist_h playlist, mc_playlist_item_cb callbac
 /**
  * @brief Clones a media controller playlist handle.
  * @details This function copies the media controller playlist handle from a source to
- *          destination. The mc_playlist_h is created internally and available through media controller playlist functions.
+ *          destination. The #mc_playlist_h is created internally and available through media controller playlist functions.
  *
  * @since_tizen @if MOBILE 4.0 @elseif WEARABLE 5.0 @endif
  *
index 2d7eed0..ac0f681 100755 (executable)
@@ -121,7 +121,8 @@ 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 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); }
@@ -176,6 +177,7 @@ extern "C" {
 #define MC_DBUS_SIGNAL_NAME_PLAYBACK_ABILITY                   "playback_ability"
 #define MC_DBUS_SIGNAL_NAME_SHUFFLE_ABILITY                    "shuffle_ability"
 #define MC_DBUS_SIGNAL_NAME_REPEAT_ABILITY                     "repeat_ability"
+#define MC_DBUS_SIGNAL_NAME_SEARCH_CMD                         "search_cmd"
 
 
 
@@ -189,6 +191,8 @@ extern "C" {
 #define MC_COMMAND_PLAY_PLAYLIST               "_playlist_cmd_"
 #define MC_COMMAND_CUSTOMACTION                        "_custom_action_"
 #define MC_COMMAND_CMDREPLY                            "_cmd_reply_"
+#define MC_COMMAND_SEARCH                              "_search_cmd_"
+
 
 #define MC_EVENT_CUSTOM                                        "_custom_event_"
 #define MC_EVENT_REPLY                                 "_event_reply_"
@@ -206,6 +210,7 @@ extern "C" {
 #define MC_DB_CMD_UPDATE_PLAYLIST      "DB_CMD_UPDATE_PLAYLIST"                /* Update Server Playlist*/
 #define MC_DB_CMD_UPDATE_ICON          "DB_CMD_UPDATE_ICON"                    /* Update Server Icon*/
 #define MC_DB_CMD_UPDATE_ABILITY               "DB_CMD_UPDATE_ABILITY"                 /* Update Server abilities*/
+
 #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*/
@@ -256,6 +261,7 @@ typedef struct {
        char *playlist_name;
        char *index;
        mc_content_type_e content_type;
+       mc_content_age_rating_e age_rating;
 } media_controller_playback_s;
 
 typedef struct {
@@ -303,6 +309,7 @@ typedef enum {
        MC_SERVER_EVENT_CLIENT_CUSTOM,          //received event from client
        MC_SERVER_EVENT_CLIENT_CUSTOM_OLD,      //received event from client, deprecated
        MC_SERVER_EVENT_REPLY_CUSTOM,           //received event reply from client
+       MC_SERVER_EVENT_SEARCH,
        MC_SERVER_EVENT_MAX,
 } mc_server_receive_event_e;
 
@@ -327,6 +334,10 @@ typedef struct {
 } media_controller_server_s;
 
 typedef struct {
+       GList *search_list;
+} media_controller_search_s;
+
+typedef struct {
        char            *client_name;
        void            *db_handle;
 
@@ -384,6 +395,12 @@ typedef struct {
        mc_signal_received_cb cb_func;
 } mc_cb_event_s;
 
+typedef struct {
+       mc_content_type_e content_type;
+       mc_search_category_e category;
+       char *search_keyword;
+       bundle *data;
+} mc_search_item_s;
 
 /* util */
 int mc_util_get_own_name(char **name);
index 680fa57..d0d4e23 100755 (executable)
@@ -255,6 +255,32 @@ typedef bool (*mc_activated_client_cb)(const char *client_name, void *user_data)
 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 Called when the Server receives search command from the client.
+ * @details This callback is called when server receives search command from client.
+ *                If you want to reply to the command, call mc_server_send_cmd_reply() function.
+ * @since_tizen 5.0
+ *
+ * @remarks The callback is called in the dbus event loop.\n
+ *          If @a request_id is not null, the server should send the reply to the client with the @a request_id.
+ *          The @a client_name, @a request_id and @a search 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.
+ *          @a search also can be used only in the callback. To use outside, make a copy using mc_search_clone(). \n
+ *
+ * @param[in] client_name    The app_id of the media controller client.
+ * @param[in] request_id     The id of the command request
+ * @param[in] search    The handle to search
+ * @param[in] user_data        The user data passed from the mc_server_set_search_cmd_received_cb() function
+ *
+ * @pre mc_server_set_search_cmd_received_cb()
+ * @see mc_server_set_search_cmd_received_cb()
+ * @see mc_server_unset_search_cmd_received_cb()
+ * @see mc_server_send_cmd_reply()
+ * @see mc_search_foreach_condition()
+ * @see mc_search_clone()
+ */
+typedef void (*mc_server_search_cmd_received_cb)(const char *client_name, const char *request_id, mc_search_h search, void *user_data);
+
+/**
  * @brief Creates a media controller server.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
@@ -360,7 +386,7 @@ int mc_server_set_playlist_item_index(mc_server_h server, const char *index)  TI
  * @privilege %http://tizen.org/privilege/mediacontroller.server
  *
  * @param[in] server The handle to media controller server
- * @param[in] playlist_name    The playlist name media included. The length of the playlist name should be less than 4096byte
+ * @param[in] playlist_name    The name of the playlist. The length of the playlist name should be less than 4096 bytes
  * @param[in] index    The index of the current playing media in the playlist
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -403,6 +429,30 @@ int mc_server_set_playlist_item_info(mc_server_h server, const char *playlist_na
 int mc_server_set_playback_content_type(mc_server_h server, mc_content_type_e content_type);
 
 /**
+ * @brief Sets the content age rating to update the latest playback info.
+ * @details If this function is called, the updated age rating information will be sent to all clients. Default value is #MC_CONTENT_RATING_ALL.
+ * @since_tizen 5.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param[in] server The handle to media controller server
+ * @param[in] age_rating Age rating of the content
+ * @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().
+ * @post Apply the updated age rating information by calling mc_server_update_playback_info().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ * @see mc_server_update_playback_info()
+ */
+int mc_server_set_content_age_rating(mc_server_h server, mc_content_age_rating_e age_rating);
+
+/**
  * @brief Updates the modified playback info.
  * @details If this function is called, the updated playback information will be sent to the controller.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
@@ -998,6 +1048,47 @@ int mc_server_set_event_reply_received_cb(mc_server_h server, mc_server_event_re
 int mc_server_unset_event_reply_received_cb(mc_server_h server);
 
 /**
+ * @brief Sets the callback for receiving search command from client.
+ * @since_tizen 5.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param[in] server    The handle to media controller server
+ * @param[in] callback      The callback to be invoked when media controller server receives search command from 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_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ */
+int mc_server_set_search_cmd_received_cb(mc_server_h server, mc_server_search_cmd_received_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for receiving search command from client.
+ * @since_tizen 5.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param[in] server    The handle to 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_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ * @see mc_server_set_search_cmd_received_cb()
+ */
+int mc_server_unset_search_cmd_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 d245cfd..ba9b41e 100755 (executable)
@@ -72,6 +72,12 @@ typedef void *mc_playlist_h;
 typedef void *mc_playback_ability_h;
 
 /**
+ * @brief The structure type for the media controller search handle.
+ * @since_tizen 5.0
+ */
+typedef void *mc_search_h;
+
+/**
  * @brief Enumeration for the media controller error.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  */
@@ -191,7 +197,7 @@ typedef enum {
 } mc_playlist_update_mode_e;
 
 /**
- * @brief Enumeration for the content type of the media controller server.
+ * @brief Enumeration for the content type of the content.
  * @since_tizen 5.0
  */
 typedef enum {
@@ -203,6 +209,33 @@ typedef enum {
 } mc_content_type_e;
 
 /**
+ * @brief Enumeration for the content age rating of the content.
+ * @since_tizen 5.0
+ */
+typedef enum {
+       MC_CONTENT_RATING_ALL = 0,              /**< Suitable for all ages */
+       MC_CONTENT_RATING_1_PLUS = 1,   /**< Suitable for ages 1 and up*/
+       MC_CONTENT_RATING_2_PLUS = 2,   /**< Suitable for ages 2 and up*/
+       MC_CONTENT_RATING_3_PLUS = 3,   /**< Suitable for ages 3 and up*/
+       MC_CONTENT_RATING_4_PLUS = 4,   /**< Suitable for ages 4 and up*/
+       MC_CONTENT_RATING_5_PLUS = 5,   /**< Suitable for ages 5 and up*/
+       MC_CONTENT_RATING_6_PLUS = 6,   /**< Suitable for ages 6 and up*/
+       MC_CONTENT_RATING_7_PLUS = 7,   /**< Suitable for ages 7 and up*/
+       MC_CONTENT_RATING_8_PLUS = 8,   /**< Suitable for ages 8 and up*/
+       MC_CONTENT_RATING_9_PLUS = 9,   /**< Suitable for ages 9 and up*/
+       MC_CONTENT_RATING_10_PLUS = 10,         /**< Suitable for ages 10 and up*/
+       MC_CONTENT_RATING_11_PLUS = 11,         /**< Suitable for ages 11 and up*/
+       MC_CONTENT_RATING_12_PLUS = 12,         /**< Suitable for ages 12 and up*/
+       MC_CONTENT_RATING_13_PLUS = 13,         /**< Suitable for ages 13 and up*/
+       MC_CONTENT_RATING_14_PLUS = 14,         /**< Suitable for ages 14 and up*/
+       MC_CONTENT_RATING_15_PLUS = 15,         /**< Suitable for ages 15 and up*/
+       MC_CONTENT_RATING_16_PLUS = 16,         /**< Suitable for ages 16 and up*/
+       MC_CONTENT_RATING_17_PLUS = 17,         /**< Suitable for ages 17 and up*/
+       MC_CONTENT_RATING_18_PLUS = 18,         /**< Suitable for ages 18 and up*/
+       MC_CONTENT_RATING_19_PLUS = 19,         /**< Suitable for ages 19 and up*/
+} mc_content_age_rating_e;
+
+/**
  * @brief Enumeration for the support of the ability.
  * @since_tizen 5.0
  */
@@ -213,6 +246,19 @@ typedef enum {
 } mc_ability_support_e;
 
 /**
+ * @brief Enumeration for the search category.
+ * @since_tizen 5.0
+ */
+typedef enum {
+       MC_SEARCH_NO_CATEGORY = 0,      /**< No search category */
+       MC_SEARCH_TITLE,                /**< Search by content title */
+       MC_SEARCH_ARTIST,               /**< Search by content artist */
+       MC_SEARCH_ALBUM,                /**< Search by content album */
+       MC_SEARCH_GENRE,                /**< Search by content genre */
+       MC_SEARCH_TPO,          /**< Search by Time Place Occasion */
+} mc_search_category_e;
+
+/**
  * @}
  */
 
index bb46adc..f23ae85 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       capi-media-controller
 Summary:    A media controller library in Tizen Native API
-Version:    0.1.70
+Version:    0.1.71
 Release:    1
 Group:      Multimedia/API
 License:    Apache-2.0
index 3eee2ce..855bc40 100755 (executable)
@@ -70,13 +70,13 @@ static void __client_server_cb(const char *interface_name, const char *signal_na
 
 static void __client_playback_cb(const char *interface_name, const char *signal_name, const char *message, const char *request_id, void *user_data)
 {
-       gchar **params = NULL;
-       media_controller_playback_s *playback = NULL;
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       mc_playback_h playback = NULL;
 
-       media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data;
-       mc_retm_if(reciever == NULL, "reciever is NULL");
+       media_controller_client_s *mc_client = (media_controller_client_s *)user_data;
+       mc_retm_if(mc_client == NULL, "mc_client is NULL");
 
-       mc_playback_updated_cb callback = (mc_playback_updated_cb)reciever->callback;
+       mc_playback_updated_cb callback = (mc_playback_updated_cb)mc_client->updated_cb[MC_CLIENT_EVENT_PLAYBACK_INFO].callback;
        mc_retm_if(callback == NULL, "playback_cb is NULL");
        mc_retm_if(message == NULL, "message is NULL");
 
@@ -85,23 +85,13 @@ static void __client_playback_cb(const char *interface_name, const char *signal_
        playback = (media_controller_playback_s *)calloc(1, sizeof(media_controller_playback_s));
        mc_retm_if(playback == NULL, "Error allocation memory");
 
-       params = g_strsplit(message, MC_STRING_DELIMITER, 0);
-       if (params == NULL) {
-               mc_error("invalid playback data");
-               MC_SAFE_FREE(playback);
-               return;
-       }
-
-       playback->state = atoi(params[1]);
-       playback->position = strtoull(params[2], NULL, 10);
-       playback->index = g_strdup(params[3]);
-       playback->content_type = atoi(params[4]);
+       ret = mc_db_get_playback_info(mc_client->db_handle, message, &playback);
+       if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+               mc_error("Fail to mc_db_get_playback_info");
 
-       callback(params[0], (mc_playback_h) playback, reciever->user_data);
+       callback(message, playback, mc_client->updated_cb[MC_CLIENT_EVENT_PLAYBACK_INFO].user_data);
 
        mc_client_destroy_playback(playback);
-
-       g_strfreev(params);
 }
 
 static void __client_metadata_cb(const char *interface_name, const char *signal_name, const char *message, const char *request_id, void *user_data)
@@ -660,7 +650,7 @@ static int __mc_client_set_updated_cb(mc_client_h client, mc_client_receive_even
 
                MC_SAFE_FREE(interface_name);
 
-       } else if ((event == MC_CLIENT_EVENT_METADATA) || event == MC_CLIENT_EVENT_PLAYBACK_ABILITY) {
+       } else if ((event == MC_CLIENT_EVENT_PLAYBACK_INFO) || (event == MC_CLIENT_EVENT_METADATA) || event == MC_CLIENT_EVENT_PLAYBACK_ABILITY) {
                ret = mc_ipc_register_listener(&mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, cb_event[event].signal_name,
                                                cb_event[event].cb_func, (void *)(mc_client));
        } else {
@@ -1007,6 +997,18 @@ int mc_client_get_playback_content_type(mc_playback_h playback, mc_content_type_
        return MEDIA_CONTROLLER_ERROR_NONE;
 }
 
+int mc_client_get_age_rating(mc_playback_h playback, mc_content_age_rating_e *age_rating)
+{
+       media_controller_playback_s *mc_playback = (media_controller_playback_s *)playback;
+
+       mc_retvm_if(playback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       mc_retvm_if(age_rating == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "age_rating is NULL");
+
+       *age_rating = mc_playback->age_rating;
+
+       return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
 int mc_client_get_metadata(mc_metadata_h metadata, mc_meta_e attribute, char **value)
 {
        char *meta_val = NULL;
@@ -1432,6 +1434,126 @@ int mc_client_send_custom_cmd(mc_client_h client, const char *server_name, const
        return ret;
 }
 
+int __mc_client_get_bundle_from_search(mc_search_h search, bundle **res_bundle)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_search_s *mc_search = (media_controller_search_s *)search;
+       int idx = 0;
+       int length = 0;
+       mc_search_item_s *search_item = NULL;
+       bundle * bundle_data = NULL;
+       char *bundle_str = NULL;
+       char *val_str = NULL;
+
+       mc_retvm_if(mc_search == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Search is NULL");
+       mc_retvm_if(res_bundle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "res_bundle is NULL");
+
+       length = g_list_length(mc_search->search_list);
+       mc_retvm_if(length == 0, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "No search item");
+       mc_retvm_if(length > 20, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "So many search items");
+
+       bundle_data = bundle_create();
+       mc_retvm_if(bundle_data == NULL, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "fail to bundle_create");
+
+       for (idx = 0; idx < length; idx++) {
+               search_item = (mc_search_item_s*)g_list_nth_data(mc_search->search_list, idx);
+               if (search_item == NULL) {
+                       mc_error("Invalid item [%d]", idx);
+                       ret = MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+                       goto ERROR;
+               }
+
+               if (search_item->search_keyword == NULL) {
+                       mc_error("Invalid search_keyword [%d]", idx);
+                       ret = MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+                       goto ERROR;
+               }
+
+               if (search_item->data != NULL) {
+                       ret = mc_util_bundle_to_string(search_item->data, &bundle_str);
+                       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+                               mc_error("Error when encode bundle [%d][%d]", ret, idx);
+                               goto ERROR;
+                       }
+               }
+
+               /*set content_type, category, bundle_size, bundle */
+               if (bundle_str != NULL) {
+                       val_str = g_strdup_printf("%d%s%d%s%s",
+                               search_item->content_type, MC_STRING_DELIMITER,
+                               search_item->category,  MC_STRING_DELIMITER,
+                               bundle_str);
+               } else {
+                       val_str = g_strdup_printf("%d%s%d%s%d",
+                               search_item->content_type, MC_STRING_DELIMITER,
+                               search_item->category,  MC_STRING_DELIMITER,
+                               0);
+               }
+               MC_SAFE_FREE(bundle_str);
+
+               mc_secure_debug("[%d][%d][%s][%s]", idx, length, search_item->search_keyword, val_str);
+
+               if (val_str == NULL) {
+                       mc_error("fail to make val_str [%d]", idx);
+                       ret = MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY;
+                       goto ERROR;
+               }
+
+               /*key - keyword, val - val_str (content_type, category, bundle_size, bundle)*/
+               ret = bundle_add_str(bundle_data, search_item->search_keyword, val_str);
+               MC_SAFE_FREE(val_str);
+               if (ret != BUNDLE_ERROR_NONE) {
+                       mc_error("Error bundle_add_str [%d][%d]", ret, idx);
+                       ret = MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+                       goto ERROR;
+               }
+
+       }
+
+       *res_bundle = bundle_data;
+
+       return ret;
+
+ERROR:
+       bundle_free(bundle_data);
+
+       return ret;
+}
+
+int mc_client_send_search_cmd(mc_client_h client, const char *server_name, mc_search_h search, char **request_id)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_client_s *mc_client = (media_controller_client_s *)client;
+       bundle *bundle_data = NULL;
+       char *message = NULL;
+       char *bundle_str = NULL;
+
+       mc_debug_fenter();
+
+       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, "Invalid server_name");
+
+       ret = __mc_client_check_server(mc_client->db_handle, server_name);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Error __mc_client_check_server [%d]", ret);
+
+       ret = __mc_client_get_bundle_from_search(search, &bundle_data);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Error __mc_client_get_bundle_from_search [%d]", ret);
+
+       ret = mc_util_bundle_to_string(bundle_data, &bundle_str);
+       bundle_free(bundle_data);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Error when make string from bundle");
+
+       message = g_strdup_printf("%s%s%s", mc_client->client_name, 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_client_send_command(client, server_name, MC_COMMAND_SEARCH, NULL, MC_DBUS_SIGNAL_NAME_SEARCH_CMD, message, request_id);
+
+       MC_SAFE_G_FREE(message);
+
+       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;
index 8f8c2a5..945dd61 100755 (executable)
@@ -35,6 +35,7 @@ typedef enum {
        MC_SERVER_FIELD_PLAYLIST_NAME,
        MC_SERVER_FIELD_PLAYLIST_INDEX,
        MC_SERVER_FIELD_PLAYBACK_CONTENT_TYPE,
+       MC_SERVER_FIELD_PLAYBACK_AGING_RATE,
        MC_SERVER_FIELD_TITLE,
        MC_SERVER_FIELD_ARTIST,
        MC_SERVER_FIELD_ALBUM,
@@ -287,13 +288,14 @@ int mc_db_update_playback_info(void *handle, const char *server_name, const medi
        mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
        mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
 
-       sql_str = g_strdup_printf("%s%s%s%s%d%s%llu%s%s%s%s%s%d", MC_DB_CMD_UPDATE_PLAYBACK, MC_STRING_DELIMITER,
+       sql_str = g_strdup_printf("%s%s%s%s%d%s%llu%s%s%s%s%s%d%s%d", MC_DB_CMD_UPDATE_PLAYBACK, MC_STRING_DELIMITER,
                        server_name,  MC_STRING_DELIMITER,
                        playback.state,  MC_STRING_DELIMITER,
                        playback.position,  MC_STRING_DELIMITER,
                        playback.playlist_name,  MC_STRING_DELIMITER,
                        playback.index,  MC_STRING_DELIMITER,
-                       playback.content_type);
+                       playback.content_type, MC_STRING_DELIMITER,
+                       playback.age_rating);
        mc_retvm_if(sql_str == NULL, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "fail making sql_str");
 
        ret = __mc_db_update_db(handle, MC_PRIV_TYPE_SERVER, sql_str);
@@ -453,18 +455,20 @@ int mc_db_get_playback_info(void *handle, const char *server_name, mc_playback_h
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
        mc_playback_states_e playback_state = MC_PLAYBACK_STATE_PLAYING;
        unsigned long long position = 0;
+       char *playlist_name = NULL;
+       char *index = NULL;
        mc_content_type_e content_type = MC_CONTENT_TYPE_UNDECIDED;
+       mc_content_age_rating_e age_rating = MC_CONTENT_RATING_ALL;
        media_controller_playback_s *_playback = NULL;
        char *sql_str = NULL;
        sqlite3_stmt *stmt = NULL;
        sqlite3 *db_handle = (sqlite3 *)handle;
-       char *index = NULL;
 
        mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
        mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
        mc_retvm_if(playback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "playback is NULL");
 
-       sql_str = sqlite3_mprintf("SELECT playback_state, playback_position, playlist_index, playback_content_type FROM '%q';", server_name);
+       sql_str = sqlite3_mprintf("SELECT playback_state, playback_position, playlist_name, playlist_index, playback_content_type, age_rating FROM '%q';", server_name);
        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);
@@ -484,8 +488,10 @@ int mc_db_get_playback_info(void *handle, const char *server_name, mc_playback_h
 
        playback_state = sqlite3_column_int(stmt, 0);
        position = (unsigned long long)sqlite3_column_int64(stmt, 1);
-       index = g_strdup((const char *)sqlite3_column_text(stmt, 2));
-       content_type = sqlite3_column_int(stmt, 3);
+       playlist_name = g_strdup((const char *)sqlite3_column_text(stmt, 2));
+       index = g_strdup((const char *)sqlite3_column_text(stmt, 3));
+       content_type = sqlite3_column_int(stmt, 4);
+       age_rating = sqlite3_column_int(stmt, 5);
 
        SQLITE3_FINALIZE(stmt);
        SQLITE3_SAFE_FREE(sql_str);
@@ -499,8 +505,10 @@ int mc_db_get_playback_info(void *handle, const char *server_name, mc_playback_h
 
        _playback->state = playback_state;
        _playback->position = position;
+       _playback->playlist_name = playlist_name;
        _playback->index = index;
        _playback->content_type = content_type;
+       _playback->age_rating = age_rating;
 
        *playback = (mc_playback_h)_playback;
 
@@ -837,17 +845,17 @@ int mc_db_get_playlist_item(void *handle, const char *server_name, char *playlis
                }
 
                index = g_strdup((char *)sqlite3_column_text(stmt, 2)); //0 : server_name, 1 : playlist_name
-               _metadata->title = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_TITLE -4));
-               _metadata->artist = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_ARTIST -4));
-               _metadata->album = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_ALBUM -4));
-               _metadata->author = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_AUTHOR -4));
-               _metadata->genre = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_GENRE -4));
-               _metadata->duration = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DURATION -4));
-               _metadata->date = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DATE -4));
-               _metadata->copyright = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_COPYRIGHT -4));
-               _metadata->description = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DESCRIPTION -4));
-               _metadata->track_num = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_TRACK_NUM -4));
-               _metadata->picture = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_PICTURE -4));
+               _metadata->title = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_TITLE -5));
+               _metadata->artist = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_ARTIST -5));
+               _metadata->album = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_ALBUM -5));
+               _metadata->author = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_AUTHOR -5));
+               _metadata->genre = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_GENRE -5));
+               _metadata->duration = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DURATION -5));
+               _metadata->date = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DATE -5));
+               _metadata->copyright = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_COPYRIGHT -5));
+               _metadata->description = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DESCRIPTION -5));
+               _metadata->track_num = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_TRACK_NUM -5));
+               _metadata->picture = g_strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_PICTURE -5));
 
                if (callback(index, (mc_metadata_h)_metadata, user_data) == false) {
                        MC_SAFE_FREE(index);
index 7f5dbb6..f5d7007 100755 (executable)
@@ -189,3 +189,133 @@ int mc_playback_action_is_supported(mc_playback_ability_h ability, mc_playback_a
 
        return ret;
 }
+
+int mc_search_create(mc_search_h *search)
+{
+       media_controller_search_s *mc_search = NULL;
+       mc_retvm_if(search == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "search is NULL");
+
+       mc_search = (media_controller_search_s *)calloc(1, sizeof(media_controller_search_s));
+       mc_retvm_if(mc_search == NULL, MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY, "Error allocation memory");
+
+       *search = (mc_search_h)mc_search;
+
+       return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_search_set_condition(mc_search_h search, mc_content_type_e content_type, mc_search_category_e category, const char *search_keyword, bundle *data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_search_s *mc_search = (media_controller_search_s *)search;
+       int length = 0;
+
+       mc_retvm_if(mc_search == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "search is NULL");
+       mc_retvm_if(((content_type < MC_CONTENT_TYPE_IMAGE) || (content_type > MC_CONTENT_TYPE_UNDECIDED)), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "content_type is invalid [%d]", content_type);
+       mc_retvm_if(((category < MC_SEARCH_NO_CATEGORY) || (category > MC_SEARCH_TPO)), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "category is invalid [%d]", category);
+       mc_retvm_if(!MC_STRING_VALID(search_keyword), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid search_keyword");
+
+       length = g_list_length(mc_search->search_list);
+       mc_retvm_if(length > 20, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "So many search items");
+
+       mc_search_item_s *search_item = (mc_search_item_s*)calloc(1, sizeof(mc_search_item_s));
+       mc_retvm_if(search_item == NULL, MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
+
+       search_item->content_type = content_type;
+       search_item->category = category;
+       search_item->search_keyword = g_strdup(search_keyword);
+       if (data != NULL)
+               search_item->data = bundle_dup(data);
+
+       mc_search->search_list = g_list_append(mc_search->search_list, search_item);
+
+       return ret;
+}
+
+int mc_search_destroy(mc_search_h search)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_search_s *mc_search = (media_controller_search_s *)search;
+       mc_search_item_s *search_item = NULL;
+       int length = 0;
+       int idx = 0;
+
+       mc_retvm_if(mc_search == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "search is NULL");
+
+       length = g_list_length(mc_search->search_list);
+
+       for (idx = 0; idx > length; idx++) {
+               search_item = (mc_search_item_s*)g_list_nth_data(mc_search->search_list, idx);
+
+               if (search_item != NULL) {
+                       MC_SAFE_FREE(search_item->search_keyword);
+                       if (search_item->data != NULL)
+                               bundle_free(search_item->data);
+                       MC_SAFE_FREE(search_item);
+               }
+       }
+
+       MC_SAFE_FREE(mc_search);
+
+       return ret;
+}
+
+int mc_search_foreach_condition(mc_search_h search, mc_search_condition_cb callback, void *user_data)
+{
+       media_controller_search_s *mc_search = (media_controller_search_s *)search;
+       mc_search_item_s *search_item = NULL;
+       int length = 0;
+       int idx = 0;
+
+       mc_retvm_if(mc_search == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid search");
+       mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback");
+
+       length = g_list_length(mc_search->search_list);
+
+       mc_debug("mc_search_foreach_condition length [%d]", length);
+
+       for (idx = 0; idx < length; idx++) {
+               search_item = (mc_search_item_s*)g_list_nth_data(mc_search->search_list, idx);
+               if (search_item != NULL) {
+                       if (callback(search_item->content_type, search_item->category, search_item->search_keyword, search_item->data, user_data) == false) {
+                               break;
+                       }
+               }
+       }
+
+       return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_search_clone(mc_search_h src, mc_search_h *dst)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_search_s *_src = (media_controller_search_s *)src;
+       mc_search_h _dst = NULL;
+       mc_search_item_s *search_item = NULL;
+       int length = 0;
+       int idx = 0;
+
+       mc_retvm_if(_src == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "invalid src");
+       mc_retvm_if(dst == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "invalid dst");
+
+       ret = mc_search_create(&_dst);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to mc_search_create()");
+
+       length = g_list_length(_src->search_list);
+
+       for (idx = 0; idx < length; idx++) {
+               search_item = (mc_search_item_s*)g_list_nth_data(_src->search_list, idx);
+               if (search_item == NULL) {
+                       mc_error("Invalid item [%d]", idx);
+                       ret = MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+                       mc_search_destroy(_dst);
+                       break;
+               }
+
+               ret = mc_search_set_condition(_dst, search_item->content_type, search_item->category, search_item->search_keyword, search_item->data);
+       }
+
+       *dst = _dst;
+
+       return ret;
+}
+
index 1ac33d0..64bdfb9 100755 (executable)
@@ -30,6 +30,8 @@ static void __server_custom_command_cb(const char *interface_name, const char *s
 static void __server_play_playlist_cmd_cb(const char *interface_name, const char *signal_name, const char *message, const char *request_id, void *user_data);
 static void __server_custom_cmd_cb(const char *interface_name, const char *signal_name, const char *message, const char *request_id, void *user_data);
 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);
+static void __server_search_cmd_cb(const char *interface_name, const char *signal_name, const char *message, const char *request_id, void *user_data);
+
 
 static mc_cb_event_s cb_event[MC_SERVER_EVENT_MAX] = {
        {MC_DBUS_SIGNAL_NAME_PLAYBACK_STATE_CMD, __server_playback_state_command_cb},
@@ -41,6 +43,7 @@ static mc_cb_event_s cb_event[MC_SERVER_EVENT_MAX] = {
        {MC_DBUS_SIGNAL_NAME_CUSTOM_CMD, __server_custom_cmd_cb},
        {MC_DBUS_SIGNAL_NAME_CUSTOM_COMMAND, __server_custom_command_cb},       //deprecated one
        {MC_DBUS_SIGNAL_NAME_EVENT_REPLY, __server_event_reply_received_cb},
+       {MC_DBUS_SIGNAL_NAME_SEARCH_CMD, __server_search_cmd_cb},
 };
 
 static int __mc_server_create(media_controller_server_s **mc_server)
@@ -318,9 +321,10 @@ static void __server_custom_command_cb(const char *interface_name, const char *s
        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_retm_if(message == NULL, "message is NULL");
 
        mc_server_custom_command_received_cb callback = receiver->callback;
        mc_retm_if(receiver->callback == NULL, "custom_command_received_cb is NULL");
@@ -401,9 +405,10 @@ static void __server_custom_cmd_cb(const char *interface_name, const char *signa
        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_retm_if(message == NULL, "message is NULL");
 
        mc_server_custom_cmd_received_cb callback = receiver->callback;
        mc_retm_if(receiver->callback == NULL, "custom_command_received_cb is NULL");
@@ -442,9 +447,10 @@ static void __server_event_reply_received_cb(const char *interface_name, const c
        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_retm_if(message == NULL, "message 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");
@@ -468,6 +474,130 @@ static void __server_event_reply_received_cb(const char *interface_name, const c
        g_strfreev(params);
 }
 
+void  _search_cb(const char *key, const int type, const bundle_keyval_t *kv, void *user_data)
+{
+       void *basic_val = NULL;
+       size_t basic_size = 0;
+       gchar **params = NULL;
+       int content_type = 0;
+       int category = 0;
+       int bundle_size = 0;
+       bundle *bundle_data = NULL;
+       GList **mc_search = (GList**)user_data;
+
+       bundle_keyval_get_basic_val((bundle_keyval_t *)kv, &basic_val, &basic_size);
+
+       mc_secure_debug("Key [%s], Type [%d], basic_val [%s]", key, type, basic_val);
+
+       params = g_strsplit(basic_val, MC_STRING_DELIMITER, 0);
+       mc_retm_if(params == NULL, "invalid search data");
+
+       if (mc_safe_strtoi(params[0], &content_type) != MEDIA_CONTROLLER_ERROR_NONE) {
+               mc_error("Error get content_type");
+               g_strfreev(params);
+               return;
+       }
+
+       if (mc_safe_strtoi(params[1], &category) != MEDIA_CONTROLLER_ERROR_NONE) {
+               mc_error("Error get content_type");
+               g_strfreev(params);
+               return;
+       }
+
+       if (mc_safe_strtoi(params[2], &bundle_size) != MEDIA_CONTROLLER_ERROR_NONE) {
+               mc_error("Error get bundle_size");
+               g_strfreev(params);
+               return;
+       }
+
+       mc_secure_debug("content_type [%d], category [%d], bundle_size [%d]", content_type, category, bundle_size);
+
+       if (bundle_size > 0) {
+               bundle_data = bundle_decode((bundle_raw *)params[3], bundle_size);
+       }
+
+       g_strfreev(params);
+
+       mc_search_item_s *search_item = (mc_search_item_s*)calloc(1, sizeof(mc_search_item_s));
+       if (search_item == NULL) {
+               mc_error("Error OUT_OF_MEMORY");
+               bundle_free(bundle_data);
+               return;
+       }
+
+       search_item->content_type = content_type;
+       search_item->category = category;
+       search_item->search_keyword = g_strdup(key);
+       search_item->data = bundle_dup(bundle_data);
+
+       if (bundle_data != NULL)
+               bundle_free(bundle_data);
+
+       *mc_search = g_list_append(*mc_search, search_item);
+}
+
+static void __server_search_cmd_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;
+       bundle *bundle_data = NULL;
+       media_controller_receiver_s *receiver = (media_controller_receiver_s *)user_data;
+       media_controller_search_s *mc_search = NULL;
+
+       mc_retm_if(receiver == NULL, "reciever is NULL");
+       mc_retm_if(message == NULL, "message is NULL");
+
+       mc_server_search_cmd_received_cb callback = receiver->callback;
+       mc_retm_if(receiver->callback == NULL, "search_command_received_cb is NULL");
+
+       mc_debug("__server_search_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 search data");
+
+       if (mc_util_get_command_available(MC_PRIV_TYPE_SERVER, params[0], MC_COMMAND_SEARCH, NULL) != MEDIA_CONTROLLER_ERROR_NONE) {
+               mc_error("Error permission denied");
+               g_strfreev(params);
+               return;
+       }
+
+       if (mc_safe_strtoi(params[1], &enc_size) != MEDIA_CONTROLLER_ERROR_NONE) {
+               mc_error("Error get recieved search cmd");
+               g_strfreev(params);
+               return;
+       }
+
+       if (enc_size == 0) {
+               mc_error("Invalid search cmd");
+               g_strfreev(params);
+               return;
+       }
+
+       bundle_data = bundle_decode((bundle_raw *)params[2], enc_size);
+
+       if (bundle_data == NULL) {
+               mc_error("Error when get data. data is NULL");
+               g_strfreev(params);
+               return;
+       }
+
+       mc_search = (media_controller_search_s *)calloc(1, sizeof(media_controller_search_s));
+       if (mc_search == NULL) {
+               mc_error("Error allocation memory");
+               g_strfreev(params);
+               bundle_free(bundle_data);
+               return;
+       }
+
+       bundle_foreach(bundle_data, _search_cb, &mc_search->search_list);
+
+       bundle_free(bundle_data);
+
+       callback(params[0], request_id, (mc_search_h)mc_search, receiver->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;
@@ -490,7 +620,7 @@ static int __mc_server_current_is_latest(media_controller_server_s *mc_server, b
        return MEDIA_CONTROLLER_ERROR_NONE;
 }
 
-static int __mc_server_send_message(media_controller_server_s *mc_server, const char *interface_name, const char *signal_name, const int param1, const unsigned long long param2, const char* param3, const int param4)
+static int __mc_server_send_message(media_controller_server_s *mc_server, const char *interface_name, const char *signal_name, const int param1, const unsigned long long param2, const char* param3)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
        char *message = NULL;
@@ -499,11 +629,9 @@ static int __mc_server_send_message(media_controller_server_s *mc_server, const
        mc_retvm_if(interface_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "interface_name is NULL");
        mc_retvm_if(signal_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "signal_name is NULL");
 
-       if (!g_strcmp0(MC_DBUS_SIGNAL_NAME_PLAY_BACK, signal_name))
-               message = g_strdup_printf("%s%s%d%s%llu%s%s%s%d", mc_server->server_name, MC_STRING_DELIMITER, param1, MC_STRING_DELIMITER, param2, MC_STRING_DELIMITER, param3, MC_STRING_DELIMITER, param4);
-       else if (!g_strcmp0(MC_DBUS_SIGNAL_NAME_METADATA, signal_name))
-               message = g_strdup_printf("%s", mc_server->server_name);
-       else if (!g_strcmp0(MC_DBUS_SIGNAL_NAME_PLAYBACK_ABILITY, signal_name))
+       if ((!g_strcmp0(MC_DBUS_SIGNAL_NAME_PLAY_BACK, signal_name))
+               || (!g_strcmp0(MC_DBUS_SIGNAL_NAME_METADATA, signal_name))
+               || (!g_strcmp0(MC_DBUS_SIGNAL_NAME_PLAYBACK_ABILITY, signal_name)))
                message = g_strdup_printf("%s", mc_server->server_name);
        else if (!g_strcmp0(MC_DBUS_SIGNAL_NAME_PLAYLIST, signal_name))
                message = g_strdup_printf("%s%s%d%s%s", mc_server->server_name, MC_STRING_DELIMITER, param1, MC_STRING_DELIMITER, param3);
@@ -654,6 +782,21 @@ int mc_server_set_playback_content_type(mc_server_h server, mc_content_type_e co
        return ret;
 }
 
+int mc_server_set_content_age_rating(mc_server_h server, mc_content_age_rating_e age_rating)
+{
+       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(((age_rating < MC_CONTENT_RATING_ALL) || (age_rating > MC_CONTENT_RATING_19_PLUS)), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "age_rating is invalid [%d]", age_rating);
+
+       mc_debug("age_rating [%d]", age_rating);
+
+       mc_server->playback.age_rating = age_rating;
+
+       return ret;
+}
+
 int mc_server_update_playback_info(mc_server_h server)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -661,8 +804,8 @@ int mc_server_update_playback_info(mc_server_h server)
 
        mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
 
-       mc_debug("playback info update: state [%d], position [%llu], playlist_name[%s], index [%s], content_type [%d]",
-               mc_server->playback.state, mc_server->playback.position, mc_server->playback.playlist_name, mc_server->playback.index, mc_server->playback.content_type);
+       mc_debug("playback info update: state [%d], position [%llu], playlist_name[%s], index [%s], content_type [%d], age_rating [%d]",
+               mc_server->playback.state, mc_server->playback.position, mc_server->playback.playlist_name, mc_server->playback.index, mc_server->playback.content_type, mc_server->playback.age_rating);
 
        ret = mc_db_update_playback_info(mc_server->db_handle, mc_server->server_name, mc_server->playback);
        if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
@@ -670,7 +813,7 @@ int mc_server_update_playback_info(mc_server_h server)
                return ret;
        }
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAY_BACK, mc_server->playback.state, mc_server->playback.position, mc_server->playback.index, mc_server->playback.content_type);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAY_BACK, 0, 0, NULL);
        if (ret != MEDIA_CONTROLLER_ERROR_NONE)
                mc_error("Error __mc_server_send_message [%d]", ret);
 
@@ -702,7 +845,7 @@ int mc_server_update_shuffle_mode(mc_server_h server, mc_shuffle_mode_e mode)
        ret = mc_db_update_shuffle_mode(mc_server->db_handle, mc_server->server_name, mode);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to mc_db_update_shuffle_mode");
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE, mode, 0, NULL, 0);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE, mode, 0, NULL);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
 
        return ret;
@@ -721,7 +864,7 @@ int mc_server_update_repeat_mode(mc_server_h server, mc_repeat_mode_e mode)
        ret = mc_db_update_repeat_mode(mc_server->db_handle, mc_server->server_name, mode);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to mc_db_update_repeat_mode");
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT, mode, 0, NULL, 0);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT, mode, 0, NULL);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
 
        return ret;
@@ -812,7 +955,7 @@ int mc_server_update_metadata(mc_server_h server)
                                                                        mc_server->metadata->description, mc_server->metadata->track_num, mc_server->metadata->picture);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to mc_db_update_whole_metadata");
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_METADATA, 0, 0, NULL, 0);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_METADATA, 0, 0, NULL);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
 
        return ret;
@@ -848,7 +991,7 @@ int mc_server_update_playlist_done(mc_server_h server, mc_playlist_h playlist)
        ret = _mc_playlist_update(MC_PRIV_TYPE_SERVER, mc_server->db_handle, mc_server->server_name, playlist);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to _mc_playlist_update");
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYLIST, MC_PLAYLIST_UPDATED, 0, _playlist->playlist_name, 0);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYLIST, MC_PLAYLIST_UPDATED, 0, _playlist->playlist_name);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
 
        return ret;
@@ -867,7 +1010,7 @@ int mc_server_delete_playlist(mc_server_h server, mc_playlist_h playlist)
        ret = mc_db_remove_playlist(mc_server->db_handle, mc_server->server_name, _playlist->playlist_name);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to mc_db_remove_playlist");
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYLIST, MC_PLAYLIST_REMOVED, 0, _playlist->playlist_name, 0);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYLIST, MC_PLAYLIST_REMOVED, 0, _playlist->playlist_name);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
 
        return ret;
@@ -1028,6 +1171,16 @@ int mc_server_unset_event_reply_received_cb(mc_server_h server)
        return __mc_server_unset_updated_cb(server, MC_SERVER_EVENT_REPLY_CUSTOM);
 }
 
+int mc_server_set_search_cmd_received_cb(mc_server_h server, mc_server_search_cmd_received_cb callback, void *user_data)
+{
+       return __mc_server_set_updated_cb(server, MC_SERVER_EVENT_SEARCH, callback, user_data);
+}
+
+int mc_server_unset_search_cmd_received_cb(mc_server_h server)
+{
+       return __mc_server_unset_updated_cb(server, MC_SERVER_EVENT_SEARCH);
+}
+
 int mc_server_send_command_reply(mc_server_h server, const char *client_name, int result_code, bundle *data)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -1171,7 +1324,7 @@ int mc_server_update_playback_ability(mc_server_h server)
 
        mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_ABILITY, 0, 0, NULL, 0);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_ABILITY, 0, 0, NULL);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
 
        return ret;
@@ -1185,7 +1338,7 @@ int mc_server_set_shuffle_ability(mc_server_h server, mc_ability_support_e suppo
        ret = __mc_server_update_ability(server, MC_ABILITY_SHUFFLE, support);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_update_ability");
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SHUFFLE_ABILITY, support, 0, NULL, 0);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SHUFFLE_ABILITY, support, 0, NULL);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
 
        return ret;
@@ -1199,7 +1352,7 @@ int mc_server_set_repeat_ability(mc_server_h server, mc_ability_support_e suppor
        ret = __mc_server_update_ability(server, MC_ABILITY_REPEAT, support);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_update_ability");
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_REPEAT_ABILITY, support, 0, NULL, 0);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_REPEAT_ABILITY, support, 0, NULL);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
 
        return ret;
@@ -1286,7 +1439,7 @@ int mc_server_create(mc_server_h *server)
                return ret;
        }
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SERVER_STATE, MC_SERVER_STATE_ACTIVATE, 0, NULL, 0);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SERVER_STATE, MC_SERVER_STATE_ACTIVATE, 0, NULL);
        if (ret != MEDIA_CONTROLLER_ERROR_NONE)
                mc_error("Error __mc_server_send_message [%d]", ret);
 
@@ -1326,7 +1479,7 @@ int mc_server_destroy(mc_server_h server)
                        mc_error("fail mc_db_delete_server_table [%d]", ret);
        }
 
-       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SERVER_STATE, MC_SERVER_STATE_DEACTIVATE, 0, NULL, 0);
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SERVER_STATE, MC_SERVER_STATE_DEACTIVATE, 0, NULL);
        if (ret != MEDIA_CONTROLLER_ERROR_NONE)
                mc_error("Error __mc_server_send_message [%d]", ret);
 
index 24c9cae..6e6ef47 100755 (executable)
@@ -468,6 +468,7 @@ int mc_db_parse_and_update_db(uid_t uid, const char *data, int data_size)
        gchar **params = NULL;
        int i_value = 0;
        int i_value_1 = 0;
+       int i_value_2 = 0;
        unsigned long long llu_value = 0, llu_value2 = 0;
        void* _db_handle = NULL;
        bool is_playlist = FALSE;
@@ -493,6 +494,7 @@ int mc_db_parse_and_update_db(uid_t uid, const char *data, int data_size)
                                playlist_name           TEXT, \
                                playlist_index          TEXT, \
                                playback_content_type   INTEGER DEFAULT 4, \
+                               age_rating              INTEGER DEFAULT 0, \
                                title                           TEXT, \
                                artist                          TEXT, \
                                album                           TEXT, \
@@ -540,7 +542,9 @@ int mc_db_parse_and_update_db(uid_t uid, const char *data, int data_size)
                mc_safe_strtoi(params[2], &i_value);
                mc_safe_strtoull(params[3], &llu_value);
                mc_safe_strtoi(params[6], &i_value_1);
-               sql_str = sqlite3_mprintf("UPDATE '%q' SET playback_state=%d, playback_position=%llu, playlist_name=%Q, playlist_index=%Q, playback_content_type=%d;", params[1], i_value, llu_value, params[4], params[5], i_value_1);
+               mc_safe_strtoi(params[7], &i_value_2);
+               sql_str = sqlite3_mprintf("UPDATE '%q' SET playback_state=%d, playback_position=%llu, playlist_name=%Q, playlist_index=%Q, playback_content_type=%d, age_rating=%d;",
+                       params[1], i_value, llu_value, params[4], params[5], i_value_1, i_value_2);
 
        } else if (strncmp(MC_DB_CMD_UPDATE_META, params[0], strlen(MC_DB_CMD_UPDATE_META)) == 0) {
                sql_str = sqlite3_mprintf("UPDATE '%q' SET title=%Q, artist=%Q, album=%Q, author=%Q, genre=%Q, duration=%Q, date=%Q, copyright=%Q, description=%Q, track_num=%Q, picture=%Q",
index 5d629c7..7761de3 100755 (executable)
@@ -54,6 +54,7 @@ typedef enum {
        TEST_REQ_REPEAT_CMD,
        TEST_REQ_PLAYLIST_CMD,
        TEST_REQ_CUSTOM_CMD,
+       TEST_REQ_SEARCH_CMD,
        TEST_REQ_MAX,
 } test_req_e;
 static char *g_request_id[TEST_REQ_MAX];
@@ -101,6 +102,7 @@ void _mc_playback_updated_cb(const char *server_name, mc_playback_h playback, vo
        char *playlist_name = NULL;
        char *index = NULL;
        mc_content_type_e content_type = MC_CONTENT_TYPE_UNDECIDED;
+       mc_content_age_rating_e age_rating = MC_CONTENT_RATING_ALL;
 
        mc_client_get_playback_position(playback, &position);
        mc_client_get_playback_state(playback, &playback_state);
@@ -109,9 +111,10 @@ void _mc_playback_updated_cb(const char *server_name, mc_playback_h playback, vo
 
        mc_client_get_playlist_item_info(playback, &playlist_name, &index);
        mc_client_get_playback_content_type(playback, &content_type);
+       mc_client_get_age_rating(playback, &age_rating);
 
-       mc_debug("[Client:%s] Playback updated from server[%s] playback_state[%d] position[%lld] playlist_name [%s] index[%s] content_type[%d]",
-               _client->client_name, server_name, playback_state, position, playlist_name, index, content_type);
+       mc_debug("[Client:%s] Playback updated from server[%s] playback_state[%d] position[%lld] playlist_name [%s] index[%s] content_type[%d] age_rating[%d]",
+               _client->client_name, server_name, playback_state, position, playlist_name, index, content_type, age_rating);
 
        MC_SAFE_FREE(playlist_name);
        MC_SAFE_FREE(index);
@@ -198,21 +201,31 @@ void _mc_cmd_reply_received_cb(const char *server_name, const char *request_id,
 {
        char *value = NULL;
        media_controller_client_s *_client = (media_controller_client_s *)g_mc_client;
+       unsigned int i = 0;
+       unsigned int found = 0;
+       char *find_request_id = NULL;
 
        mc_error("[No-Errror][Id:%s]", request_id);
 
-       unsigned int i = 0;
-       unsigned int found = 0;
+       if (request_id == NULL) {
+               mc_error("Invalid request_id");
+       }
+
        for (i = 0; i < TEST_REQ_MAX; i++) {
                if ((g_request_id[i] != NULL) && (strcmp(request_id, g_request_id[i]) == 0)) {
                        found = 1;
+                       find_request_id = strdup(g_request_id[i]);
+                       MC_SAFE_FREE(g_request_id[i]);
                        break;
                }
        }
+
        if (!found) {
                mc_error("[Client:%s] Wrong request_id[%s]", _client->client_name, request_id);
+               return;
        }
-       if (strcmp(request_id, g_request_id[TEST_REQ_CUSTOM_CMD]) == 0) {
+
+       if ((g_request_id[TEST_REQ_CUSTOM_CMD] != NULL) && (strcmp(request_id, g_request_id[TEST_REQ_CUSTOM_CMD]) == 0)) {
                if (data)
                        bundle_get_str(data, "key1", &value);
 
@@ -220,6 +233,9 @@ void _mc_cmd_reply_received_cb(const char *server_name, const char *request_id,
        } else {
                mc_error("[Client:%s] Reply result code[%d] from server[%s]", _client->client_name, result_code, server_name);
        }
+
+       MC_SAFE_FREE(find_request_id);
+
 }
 
 void _mc_custom_event_received_cb(const char *server_name, const char *request_id, const char *event, bundle *data, void *user_data)
@@ -578,6 +594,7 @@ static gboolean _send()
 {
        g_print("== send command to latest server \n");
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       bundle *bundle_data = NULL;
 
        if (g_playback_state == MC_PLAYBACK_STATE_PLAYING)
                g_playback_state = MC_PLAYBACK_STATE_STOPPED;
@@ -641,7 +658,7 @@ static gboolean _send()
        reqtime.tv_nsec = 500000000;
        nanosleep(&reqtime, NULL);
 
-       bundle *bundle_data = bundle_create();
+       bundle_data = bundle_create();
        bundle_add_str(bundle_data, "key1", "val1");
        bundle_add_str(bundle_data, "key2", "val2");
        bundle_add_str(bundle_data, "key3", "val3");
@@ -669,6 +686,38 @@ static gboolean _send()
        }
        bundle_free(bundle_data);
 
+       /*Send Search Command*/
+       mc_search_h mc_search = NULL;
+       bundle_data = bundle_create();
+       bundle_add_str(bundle_data, "key1", "val1_2");
+       bundle_add_str(bundle_data, "key2", "val2_2");
+
+       ret = mc_search_create(&mc_search);
+       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+               mc_error("Fail mc_search_create [%d]", ret);
+               bundle_free(bundle_data);
+               return FALSE;
+       }
+
+       ret = mc_search_set_condition(mc_search, MC_CONTENT_TYPE_MUSIC, MC_SEARCH_TITLE, "search title 1", NULL);
+       ret = mc_search_set_condition(mc_search, MC_CONTENT_TYPE_VIDEO, MC_SEARCH_GENRE, "search genre 4", bundle_data);
+
+       ret = mc_client_send_search_cmd(g_mc_client, g_server_name, mc_search, &g_request_id[TEST_REQ_SEARCH_CMD]);
+       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+               bundle_free(bundle_data);
+               mc_search_destroy(mc_search);
+               mc_error("Fail to send search command %d", ret);
+               return FALSE;
+       }
+
+       bundle_free(bundle_data);
+
+       ret = mc_search_destroy(mc_search);
+       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+               mc_error("Fail to mc_search_destroy [%d]", ret);
+               return FALSE;
+       }
+
        unsigned int i = 0;
        for (i = 0; i < TEST_REQ_MAX; i++)
                mc_error("[No-Errror][%02u][Id:%s]", i, g_request_id[i]);
index a80da61..9801bd9 100755 (executable)
@@ -69,6 +69,7 @@ enum {
        CURRENT_STATE_SET_PLAYBACK_POSITION,
        CURRENT_STATE_SET_ITEM_ID,
        CURRENT_STATE_SET_CONTENT_TYPE,
+       CURRENT_STATE_SET_AGE_RATING,
        CURRENT_STATE_SET_METADATA_NAME,
        CURRENT_STATE_SET_METADATA_VALUE,
 };
@@ -186,6 +187,36 @@ void __custom_command_received_cb(const char *client_name, const char *command,
                g_free(bundle_data);
 }
 
+bool __mc_search_item_cb(mc_content_type_e content_type, mc_search_category_e category, const char *search_keyword, bundle *data, void *user_data)
+{
+       char *get_value1 = NULL;
+       char *get_value2 = NULL;
+
+       g_print("[search_item] content_type [%d] category [%d] search_keyword [%s]\n", content_type, category, search_keyword);
+
+       if (data != NULL) {
+               bundle_get_str(data, "key1", &get_value1);
+               bundle_get_str(data, "key2", &get_value2);
+               g_print("[search_item] bundle key1 : [%s] key2 : [%s]\n", get_value1, get_value2);
+       }
+
+       return TRUE;
+}
+
+void __search_cmd_received_cb(const char *client_name, const char *request_id, mc_search_h search, void *user_data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       g_print("[%s] recieved search cmd from [%s]\n", request_id, client_name);
+
+       ret = mc_search_foreach_condition(search, __mc_search_item_cb, NULL);
+
+       if (request_id != NULL) {
+               ret = mc_server_send_cmd_reply(g_mc_server, client_name, request_id, ret, NULL);
+               if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+                       g_print("Fail to mc_server_send_command_reply\n");
+       }
+}
+
 bool server_playlist_item_cb(const char *index, mc_metadata_h meta, void *user_data)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -489,6 +520,12 @@ static gboolean _set_cb()
                return FALSE;
        }
 
+       ret = mc_server_set_search_cmd_received_cb(g_mc_server, __search_cmd_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;
@@ -498,7 +535,8 @@ static gboolean _set_info(int type, char *cmd)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
        int playback_state = 0;
-       int content_type = 0;
+       mc_content_type_e content_type = 0;
+       mc_content_age_rating_e age_rating = 0;
        unsigned long long playback_position = 0;
        char *metadata = NULL;
 
@@ -549,12 +587,19 @@ static gboolean _set_info(int type, char *cmd)
                }
                g_print("set content type : %d", content_type);
                break;
-
+       case CURRENT_STATE_SET_AGE_RATING:
+               age_rating = atoi(cmd);
+               ret = mc_server_set_content_age_rating(g_mc_server, age_rating);
+               if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+                       g_print("Fail to set age_rating");
+                       return FALSE;
+               }
+               g_print("set age rating : %d", age_rating);
+               break;
        case CURRENT_STATE_SET_METADATA_NAME:
                g_metadata_type = atoi(cmd);
                g_print("set metadata name: %d", g_metadata_type);
                break;
-
        case CURRENT_STATE_SET_METADATA_VALUE:
                metadata = strdup(cmd);
                ret = mc_server_set_metadata(g_mc_server, g_metadata_type, metadata);
@@ -824,8 +869,9 @@ static void display_set_info_menu(void)
        g_print("2. set server playback position \n");
        g_print("3. set server media id \n");
        g_print("4. set server content type \n");
-       g_print("5. set server metadata name\n");
-       g_print("6. set server metadata value\n");
+       g_print("5. set server content age rating \n");
+       g_print("6. set server metadata name\n");
+       g_print("7. set server metadata value\n");
        g_print("0. back \n");
        g_print("----------------------------------------------------\n");
        g_print("====================================================\n");
@@ -924,8 +970,10 @@ void _interpret_set_info_menu(char *cmd)
                else if (!strncmp(cmd, "4", len))
                        g_menu_set_state = CURRENT_STATE_SET_CONTENT_TYPE;
                else if (!strncmp(cmd, "5", len))
-                       g_menu_set_state = CURRENT_STATE_SET_METADATA_NAME;
+                       g_menu_set_state = CURRENT_STATE_SET_AGE_RATING;
                else if (!strncmp(cmd, "6", len))
+                       g_menu_set_state = CURRENT_STATE_SET_METADATA_NAME;
+               else if (!strncmp(cmd, "7", len))
                        g_menu_set_state = CURRENT_STATE_SET_METADATA_VALUE;
                else if (!strncmp(cmd, "0", len)) {
                        reset_current_menu_state();
@@ -1002,6 +1050,7 @@ static void interpret_cmd(char *cmd)
                case CURRENT_STATE_SET_PLAYBACK_POSITION:
                case CURRENT_STATE_SET_ITEM_ID:
                case CURRENT_STATE_SET_CONTENT_TYPE:
+               case CURRENT_STATE_SET_AGE_RATING:
                case CURRENT_STATE_SET_METADATA_NAME:
                case CURRENT_STATE_SET_METADATA_VALUE:
                        _set_info(g_menu_set_state, cmd);