[ACR-1190] Add new APIs to support playlist 76/174176/14
authorhj kim <backto.kim@samsung.com>
Thu, 29 Mar 2018 01:40:42 +0000 (10:40 +0900)
committerhj kim <backto.kim@samsung.com>
Mon, 2 Apr 2018 08:38:32 +0000 (17:38 +0900)
Change-Id: Iec9a08c93aa755d46fe3bb8bac48151ede42c55d

13 files changed:
include/media_controller_client.h
include/media_controller_db.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_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 1d88befbd8f3766835378fd06e741cae6ecdbb39..6f4552f81d008a799be61d5062bbc4897a6c24e8 100755 (executable)
@@ -40,7 +40,7 @@ extern "C" {
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] server_name The app_id of the updated media controller server, it can be used only in the callback. To use outside, make a copy.
+ * @param[in] server_name The app_id of the media controller server which sent the notification. It can be used only in the callback. To use outside, make a copy.
  * @param[in] state The state of the updated media controller server
  * @param[in] user_data        The user data passed from the mc_client_set_server_update_cb() function
  *
@@ -56,8 +56,8 @@ typedef void (*mc_server_state_updated_cb)(const char *server_name, mc_server_st
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] server_name The app_id of the updated media controller server. it can be used only in the callback. To use outside, make a copy.
- * @param[in] playback The playback information of the updated media controller server. it can be used only in the callback.
+ * @param[in] server_name The app_id of the media controller server which sent the notification. It can be used only in the callback. To use outside, make a copy.
+ * @param[in] playback The playback information of the updated media controller server. It can be used only in the callback.
  * @param[in] user_data        The user data passed from the mc_client_set_playback_update_cb() function
  *
  * @pre mc_client_set_playback_update_cb()
@@ -72,8 +72,8 @@ typedef void (*mc_playback_updated_cb)(const char *server_name, mc_playback_h pl
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] server_name The app_id of the updated media controller server. it can be used only in the callback. To use outside, make a copy.
- * @param[in] metadata the metadata of the updated media controller server. it can be used only in the callback.
+ * @param[in] server_name The app_id of the media controller server which sent the notification. It can be used only in the callback. To use outside, make a copy.
+ * @param[in] metadata the metadata of the updated media controller server. It can be used only in the callback.
  * @param[in] user_data        The user data passed from the mc_client_set_metadata_update_cb() function
  *
  * @pre mc_client_set_metadata_update_cb()
@@ -88,7 +88,7 @@ typedef void (*mc_metadata_updated_cb)(const char *server_name, mc_metadata_h me
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] server_name The app_id of the updated media controller server, it can be used only in the callback. To use outside, make a copy.
+ * @param[in] server_name The app_id of the media controller server which sent the notification. It can be used only in the callback. To use outside, make a copy.
  * @param[in] mode The shuffle mode of the updated media controller server
  * @param[in] user_data        The user data passed from the mc_client_set_shuffle_mode_update_cb() function
  *
@@ -104,7 +104,7 @@ typedef void (*mc_shuffle_mode_changed_cb)(const char *server_name, mc_shuffle_m
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] server_name The app_id of the updated media controller server, it can be used only in the callback. To use outside, make a copy.
+ * @param[in] server_name The app_id of the media controller server which sent the notification. It can be used only in the callback. To use outside, make a copy.
  * @param[in] mode The repeat mode of the updated media controller server
  * @param[in] user_data        The user data passed from the mc_client_set_repeat_mode_update_cb() function
  *
@@ -120,7 +120,7 @@ typedef void (*mc_repeat_mode_changed_cb)(const char *server_name, mc_repeat_mod
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] server_name The app_id of the activated media controller server, it 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. It can be used only in the callback. To use outside, make a copy.
  * @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,
@@ -136,9 +136,9 @@ typedef bool (*mc_activated_server_cb)(const char *server_name, void *user_data)
  * @brief Called when receiving the command processing result from the server.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
- * @remarks The callback is called in the dbus event loop. @a data should be released using bundle_free().
+ * @remarks The callback is called in the dbus event loop. @a data should be released using @c bundle_free().
  *
- * @param[in] server_name    The app_id of the updated media controller server, it can be used only in the callback. To use outside, make a copy.
+ * @param[in] server_name    The app_id of the media controller server which sent the reply, It can be used only in the callback. To use outside, make a copy.
  * @param[in] result_code    The result code of custom command
  * @param[in] data The extra data
  * @param[in] user_data        The user data passed from the mc_client_send_custom_command() function
@@ -155,7 +155,7 @@ typedef void (*mc_command_reply_received_cb)(const char *server_name, int result
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] server_name The app_id of the subscribed media controller server, it 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. It can be used only in the callback. To use outside, make a copy.
  * @param[in] user_data        The user data passed from the mc_client_foreach_server_subscribed() function
  *
  * @return @c true to continue with the next iteration of the loop,
@@ -167,6 +167,25 @@ typedef void (*mc_command_reply_received_cb)(const char *server_name, int result
  */
 typedef bool (*mc_subscribed_server_cb)(const char *server_name, void *user_data);
 
+/**
+ * @brief Called when updating the playlist of the media controller server.
+ * @since_tizen 5.0
+ *
+ * @remarks The callback is called in the dbus event loop. @a data is a bundle. A bundle is a set of key-value pairs. "item id" is the key and "item metadata" is the value.
+ *
+ * @param[in] server_name The app_id of the media controller server which sent the notification. It can be used only in the callback. To use outside, make a copy.
+ * @param[in] mode The playlist update mode of the updated media controller server
+ * @param[in] playlist_name Updated playlist name. It can be used only in the callback. To use outside, make a copy.
+ * @param[in] data The playlist of the media controller server. When the playlist has been removed or it has no items after the change, @a data is NULL. It can be used only in the callback. To use outside, make a copy using @c bundle_dup().
+ * @param[in] user_data The user data passed from the mc_client_set_playlist_update_cb() function
+ *
+ * @pre mc_client_set_playlist_update_cb()
+ *
+ * @see mc_client_set_playlist_update_cb()
+ * @see mc_server_update_playlist()
+ */
+typedef void (*mc_playlist_updated_cb)(const char *server_name, mc_playlist_update_mode_e mode, const char *playlist_name, 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.
@@ -175,7 +194,7 @@ typedef bool (*mc_subscribed_server_cb)(const char *server_name, void *user_data
  * @privlevel public
  * @privilege %http://tizen.org/privilege/mediacontroller.client
  *
- * @remarks The @a client should be released using mc_client_destroy().
+ * @remarks The @a client should be released using @c mc_client_destroy().
  *
  * @param[out] client The handle to the media controller client
  * @return @c 0 on success,
@@ -190,7 +209,7 @@ int mc_client_create(mc_client_h *client);
 
 /**
  * @brief Sets the callback for monitoring status of the media controller server.
- * @details If media controller client call this function, basically the media controller client receive the callback from all media controller servers.
+ * @details The media controller client which calls this function will receive notifications from all media controller servers.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
  * @privlevel public
@@ -231,7 +250,7 @@ int mc_client_unset_server_update_cb(mc_client_h client);
 
 /**
  * @brief Sets the callback for monitoring playback status of the media controller server.
- * @details If media controller client call this function, basically the media controller client receive the callback from all media controller servers. \n
+ * @details The media controller client which calls this function will receive notifications from all media controller servers. \n
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
  * @privlevel public
@@ -272,7 +291,7 @@ int mc_client_unset_playback_update_cb(mc_client_h client);
 
 /**
  * @brief Sets the callback for monitoring metadata status of the media controller server.
- * @details If media controller client call this function, basically the media controller client receive the callback from all media controller servers.
+ * @details The media controller client which calls this function will receive notifications from all media controller servers.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
  * @privlevel public
@@ -313,7 +332,7 @@ int mc_client_unset_metadata_update_cb(mc_client_h client);
 
 /**
  * @brief Sets the callback for monitoring shuffle mode of the media controller server.
- * @details If media controller client call this function, basically the media controller client receive the callback from all media controller servers.
+ * @details The media controller client which calls this function will receive notifications from all media controller servers.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
  * @privlevel public
@@ -354,7 +373,7 @@ int mc_client_unset_shuffle_mode_update_cb(mc_client_h client);
 
 /**
  * @brief Sets the callback for monitoring repeat mode of the media controller server.
- * @details If media controller client call this function, basically the media controller client receive the callback from all media controller servers.
+ * @details The media controller client which calls this function will receive notifications from all media controller servers.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
  * @privlevel public
@@ -393,6 +412,47 @@ int mc_client_set_repeat_mode_update_cb(mc_client_h client, mc_repeat_mode_chang
  */
 int mc_client_unset_repeat_mode_update_cb(mc_client_h client);
 
+/**
+ * @brief Sets the callback for monitoring playlist status of the media controller server.
+ * @details The media controller client which calls this function will receive notifications from all media controller servers.
+ * @since_tizen 5.0
+ *
+ * @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 playlist status is changed
+ * @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 client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_set_playlist_update_cb(mc_client_h client, mc_playlist_updated_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for monitoring playlist status of the media controller server.
+ * @since_tizen 5.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 client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_unset_playlist_update_cb(mc_client_h client);
+
 /**
  * @brief Subscribes media controller server for monitoring status.
  * @details If media controller client subscribe media controller server, \n
@@ -597,7 +657,7 @@ int mc_client_get_latest_server_info(mc_client_h client, char **server_name, mc_
  *                   If there is no playback info, return value of the playback is NULL.
  *
  * @param[in] client    The handle to the media controller client
- * @param[in] server_name    The app_id of the server to requesting
+ * @param[in] server_name    The app_id of the media controller server
  * @param[out] playback    The handle to playback
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -619,7 +679,7 @@ int mc_client_get_server_playback_info(mc_client_h client, const char *server_na
  *                   If there is no metadata, return value of the metadata is NULL.
  *
  * @param[in] client    The handle to the media controller client
- * @param[in] server_name    The app_id of the server to requesting
+ * @param[in] server_name    The app_id of the media controller server
  * @param[out] metadata    The handle to metadata
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -640,7 +700,7 @@ int mc_client_get_server_metadata(mc_client_h client, const char *server_name, m
  * @remarks If there is no shuffle mode info, return value is #MC_SHUFFLE_MODE_OFF.
  *
  * @param[in] client    The handle to the media controller client
- * @param[in] server_name    The app_id of the server to requesting
+ * @param[in] server_name    The app_id of the media controller server
  * @param[out] mode    The info of the latest shuffle mode
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -661,7 +721,7 @@ int mc_client_get_server_shuffle_mode(mc_client_h client, const char *server_nam
  * @remarks If there is no repeat mode info, return value is #MC_REPEAT_MODE_OFF.
  *
  * @param[in] client    The handle to the media controller client
- * @param[in] server_name    The app_id of the server to requesting
+ * @param[in] server_name    The app_id of the media controller server
  * @param[out] mode    The info of the latest shuffle mode
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -671,6 +731,34 @@ 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 Gets the playlist.
+ * @details The media controller client will get the playlist information from @a server_name.
+ * @since_tizen 5.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @remarks The @a playlist_name should be released using free(). \n
+ *               @a playlist is a bundle. A bundle is a set of key-value pairs. "item id" is the key and "item metadata" is the value. \n
+ *               And also the @a playlist should be released using @c bundle_free(). \n
+ *               If there is no playlist, return value of @a playlist_name and @a playlist is NULL.
+ *
+ * @param[in] client    The handle to the media controller client
+ * @param[in] server_name    The app_id of the media controller server
+ * @param[out] playlist_name    The playlist name of the server
+ * @param[out] playlist    The item list of the playlist
+ * @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
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ * @see mc_server_update_playlist()
+ */
+int mc_client_get_server_playlist(mc_client_h client, const char *server_name, char **playlist_name, bundle **playlist);
+
 /**
  * @brief Retrieves all activated Server.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
index 81a05d344f5e889d7fc94856b80bc8bf2df700b9..7cc718b8c5e11030a6c3fa9296029fa07e070582 100755 (executable)
@@ -20,6 +20,7 @@
 #include <db-util.h>
 #include <sqlite3.h>
 #include <tzplatform_config.h>
+#include <bundle.h>
 
 #define FAT_FILEPATH_LEN_MAX   4096    /* inc null */
 #define MC_FILE_PATH_LEN_MAX   FAT_FILEPATH_LEN_MAX    /**< File path max length (include file name) on file system */
@@ -82,6 +83,7 @@ int mc_db_get_playback_info(void *handle, const char *server_name, mc_playback_h
 int mc_db_get_metadata_info(void *handle, const char *server_name, mc_metadata_h *metadata);
 int mc_db_get_shuffle_mode(void *handle, const char *server_name, mc_shuffle_mode_e *mode);
 int mc_db_get_repeat_mode(void *handle, const char *server_name, mc_repeat_mode_e *mode);
+int mc_db_get_playlist(void *handle, const char *server_name, char **playlist_name, bundle **playlist);
 
 int mc_db_insert_server_address_into_table(void *db_handle, const char *table_name, char *address);
 int mc_db_delete_server_address_from_table(void *db_handle, const char *table_name, char *address);
@@ -90,6 +92,8 @@ int mc_db_foreach_server_list(void *handle, mc_activated_server_cb callback, voi
 int mc_db_update_server_state(void *handle, const char *server_name, mc_server_state_e server_state);
 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);
+int mc_db_update_playlist(void *handle, const char *server_name, const char *playlist_name, bundle *data);
 
 
 #endif /*__TIZEN_MULTIMEDIA_MEDIA_CONTROLLER_DB_H__*/
index b3606f5fcaa6783888f3d6c6ea9f4733afbf3660..1de3966ca6df4134a5079e11bcadacd4b6203fc0 100755 (executable)
@@ -155,6 +155,7 @@ extern "C" {
 #define MC_DBUS_SIGNAL_NAME_REPEAT_CMD                         "repeat_cmd"
 #define MC_DBUS_SIGNAL_NAME_CUSTOM_CMD                         "custom_cmd"
 #define MC_DBUS_SIGNAL_NAME_CMD_REPLY                          "custom_cmd_reply"
+#define MC_DBUS_SIGNAL_NAME_PLAYLIST                                   "playlist"
 
 #define MC_COMMAND_PLAYBACKSTATE               "_pb_state_cmd_"
 #define MC_COMMAND_PLAYBACKACTION              "_pb_action_cmd_"
@@ -241,6 +242,7 @@ typedef struct {
        media_controller_receiver_s shuffle_cb;
        media_controller_receiver_s repeat_cb;
        media_controller_receiver_s reply_cb;
+       media_controller_receiver_s playlist_cb;
 } media_controller_client_s;
 
 /* formal callback to receive signal */
index 8586410d4d7558b3f6ef01a342fbb9ef041249ed..f993540a49e65ff2b0dc930bf6ef937365d5ffc3 100755 (executable)
@@ -41,7 +41,7 @@ extern "C" {
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] client_name    The app_id of the media controller client, it 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. It can be used only in the callback. To use outside, make a copy.
  * @param[in] state    The received playback state
  * @param[in] user_data        The user data passed from the mc_server_set_playback_state_command_received_cb() function
  *
@@ -52,12 +52,12 @@ extern "C" {
 typedef void (*mc_server_playback_state_command_received_cb)(const char* client_name, mc_playback_states_e state, void *user_data);
 
 /**
- * @brief Called when the server receives the playback action commandfrom the client.
+ * @brief Called when the server receives the playback action command from the client.
  * @since_tizen 5.0
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] client_name    The app_id of the media controller client, it 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. It can be used only in the callback. To use outside, make a copy.
  * @param[in] action    The received playback action
  * @param[in] user_data        The user data passed from the mc_server_set_playback_action_received_cb() function
  *
@@ -73,7 +73,7 @@ typedef void (*mc_server_playback_action_received_cb)(const char* client_name, m
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] client_name    The app_id of the media controller client, it 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. It can be used only in the callback. To use outside, make a copy.
  * @param[in] position    The received playback position
  * @param[in] user_data        The user data passed from the mc_server_set_playback_position_command_received_cb() function
  *
@@ -89,7 +89,7 @@ typedef void (*mc_server_playback_position_command_received_cb)(const char* clie
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] client_name    The app_id of the media controller client, it 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. It can be used only in the callback. To use outside, make a copy.
  * @param[in] shuffle_mode    The received shuffle_mode
  * @param[in] user_data        The user data passed from the mc_server_set_shuffle_mode_command_received_cb() function
  *
@@ -105,7 +105,7 @@ typedef void (*mc_server_shuffle_mode_command_received_cb)(const char* client_na
  *
  * @remarks The callback is called in the dbus event loop.
  *
- * @param[in] client_name    The app_id of the media controller client, it 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. It can be used only in the callback. To use outside, make a copy.
  * @param[in] repeat_mode    The received repeat mode
  * @param[in] user_data        The user data passed from the mc_server_set_repeat_mode_command_received_cb() function
  *
@@ -123,8 +123,8 @@ typedef void (*mc_server_repeat_mode_command_received_cb)(const char* client_nam
  *
  * @remarks The callback is called in the dbus event loop. @a data should be released using bundle_free().
  *
- * @param[in] client_name    The app_id of the media controller client. it can be used only in the callback. To use outside, make a copy.
- * @param[in] command    The received command. it 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. It can be used only in the callback. To use outside, make a copy.
+ * @param[in] command    The received command. It can be used only in the callback. To use outside, make a copy.
  * @param[in] data    The extra data
  * @param[in] user_data        The user data passed from the mc_server_set_custom_command_received_cb() function
  *
@@ -237,7 +237,7 @@ int mc_server_set_metadata(mc_server_h server, mc_meta_e attribute, const char *
 
 /**
  * @brief Updates the modified metadata info.
- * @details If this function is called, the updated metadata will be sent to all controllers.
+ * @details If this function is called, the updated metadata will be sent to all clients.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
  * @privlevel public
@@ -258,7 +258,7 @@ int mc_server_update_metadata(mc_server_h server);
 
 /**
  * @brief Updates the modified shuffle mode.
- * @details If this function is called, the updated mode information will be sent to all controllers.
+ * @details If this function is called, the updated mode information will be sent to all clients.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
  * @privlevel public
@@ -280,7 +280,7 @@ int mc_server_update_shuffle_mode(mc_server_h server, mc_shuffle_mode_e mode);
 
 /**
  * @brief Updates the modified repeat mode.
- * @details If this function is called, the updated mode information will be sent to all controllers.
+ * @details If this function is called, the updated mode information will be sent to all clients.
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
  *
  * @privlevel public
@@ -300,6 +300,62 @@ int mc_server_update_shuffle_mode(mc_server_h server, mc_shuffle_mode_e mode);
  */
 int mc_server_update_repeat_mode(mc_server_h server, mc_repeat_mode_e mode);
 
+/**
+ * @brief Updates the modified playlist info.
+ * @details If this function is called, the updated playlist will be sent to all clients. \n
+ *            The server can register only one playlist. If a new one is registered, the old one is removed. \n
+ *            @a data is a bundle. A bundle is a set of key-value pairs. "item id" is the key and "item metadata" is the value. \n
+ *            Therefore you should fill the metadata order using #mc_meta_e. \n
+ *            If there are no playlist items or the server wants to remove the playlist, set @data to NULL.
+ * @since_tizen 5.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param[in] server The handle to media controller server
+ * @param[in] mode The playlist update status
+ * @param[in] playlist_name The name of the server playlist
+ * @param[in] data The item list of playlist.
+ *
+ * @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 File does not exist
+ * @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()
+ *
+ * @code
+ #include <media_controller_server.h>
+ #include <bundle.h>
+ const char *playlist_item[11];
+ bundle * b = NULL;
+
+ playlist_item[MC_META_MEDIA_TITLE] = "title";
+ playlist_item[MC_META_MEDIA_ARTIST] = "artist";
+ playlist_item[MC_META_MEDIA_ALBUM] = "album";
+ playlist_item[MC_META_MEDIA_AUTHOR] = "author";
+ playlist_item[MC_META_MEDIA_GENRE] = "Rock";
+ playlist_item[MC_META_MEDIA_DURATION] = "100";
+ playlist_item[MC_META_MEDIA_DATE] = "2018";
+ playlist_item[MC_META_MEDIA_COPYRIGHT] = "copyright";
+ playlist_item[MC_META_MEDIA_DESCRIPTION] = "description";
+ playlist_item[MC_META_MEDIA_TRACK_NUM] = "9";
+ playlist_item[MC_META_MEDIA_PICTURE] = "picture_path";
+
+ bundle_add_str_array(b, "1", playlist_item, 11);
+
+ mc_server_update_playlist(server, MC_PLAYLIST_UPDATED, "playlist_1", b);      //create or update playlist
+ mc_server_update_playlist(server, MC_PLAYLIST_REMOVED, "playlist_1", NULL);   //remove playlist
+
+ bundle_free(bundle_data);
+
+ * @endcode
+ */
+int mc_server_update_playlist(mc_server_h server, mc_playlist_update_mode_e mode, const char *playlist_name, bundle *data);
+
 /**
  * @deprecated Deprecated since 5.0. Use mc_server_set_playback_action_received_cb() instead.
  * @brief Sets the callback for receiving playback state command from client.
index d0edab84141dc49264a6e128693dec7a691adc1c..970b4e4bb5c8e49f8fc645f5189e9b7dbd6adcf1 100755 (executable)
@@ -163,8 +163,18 @@ typedef enum {
        MC_SUBSCRIPTION_TYPE_METADATA,                                          /**< Metadata */
        MC_SUBSCRIPTION_TYPE_SHUFFLE_MODE,                                      /**< Shuffle mode */
        MC_SUBSCRIPTION_TYPE_REPEAT_MODE,                                       /**< Repeat mode */
+       MC_SUBSCRIPTION_TYPE_PLAYLIST,                                          /**< Playlist (Since 5.0) */
 } mc_subscription_type_e;
 
+/**
+ * @brief Enumeration for the playlist update mode.
+ * @since_tizen 5.0
+ */
+typedef enum {
+       MC_PLAYLIST_UPDATED,    /**< Create or Update playlist */
+       MC_PLAYLIST_REMOVED,    /**< Remove playlist */
+} mc_playlist_update_mode_e;
+
 /**
  * @}
  */
index 2aa589c677af0fa82e3762343bd18185715c9bbe..ec609f664ba84380bb8b81c45255bd9a7ac0b9f6 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       capi-media-controller
 Summary:    A media controller library in Tizen Native API
-Version:    0.1.52
+Version:    0.1.53
 Release:    1
 Group:      Multimedia/API
 License:    Apache-2.0
index 830236fd5a151ef15f8e30442895e33a23e135fb..a7517ad6550cf39351cd36f4625edb989a4a71c4 100755 (executable)
@@ -158,6 +158,43 @@ static void __client_reply_cb(const char *interface_name, const char *signal_nam
        g_strfreev(params);
 }
 
+static void __client_playlist_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       gchar **params = NULL;
+       bundle *playlist = NULL;
+       char *playlist_name = NULL;
+       mc_playlist_update_mode_e mode = MC_PLAYLIST_UPDATED;
+       media_controller_client_s *mc_client = (media_controller_client_s *)user_data;
+       mc_retm_if(mc_client == NULL, "mc_client is NULL");
+       mc_playlist_updated_cb callback = (mc_playlist_updated_cb)mc_client->playlist_cb.callback;
+
+       mc_retm_if(mc_client->playlist_cb.callback == NULL, "playlist_cb is NULL");
+       mc_retm_if(message == NULL, "message is NULL");
+
+       mc_debug("__client_playlist_cb(%s, %s, %s, %d, %p)", interface_name, signal_name, message, size, user_data);
+
+       params = g_strsplit(message, MC_STRING_DELIMITER, 0);
+       mc_retm_if(params == NULL, "invalid custom data");
+
+       mode = atoi(params[1]);
+
+       if (mode == MC_PLAYLIST_UPDATED) {
+               ret = mc_db_get_playlist(mc_client->db_handle, params[0], &playlist_name, &playlist);
+               if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+                       mc_error("Fail to mc_db_get_playlist");
+       }
+
+       callback(params[0], mode, params[2], playlist, mc_client->playlist_cb.user_data);
+
+       g_strfreev(params);
+       MC_SAFE_FREE(playlist_name);
+       if (playlist != NULL)
+               bundle_free(playlist);
+
+       return;
+}
+
 static int __mc_client_create(media_controller_client_s **mc_client)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -542,6 +579,42 @@ int mc_client_unset_repeat_mode_update_cb(mc_client_h client)
        return ret;
 }
 
+int mc_client_set_playlist_update_cb(mc_client_h client, mc_playlist_updated_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_retvm_if(mc_client->playlist_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set");
+
+       mc_client->playlist_cb.callback = callback;
+       mc_client->playlist_cb.user_data = user_data;
+
+       ret = mc_ipc_register_listener(&mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYLIST,
+                                                       __client_playlist_cb, (void *)(mc_client));
+
+       return ret;
+}
+
+int mc_client_unset_playlist_update_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");
+
+       ret = mc_ipc_unregister_listener(&mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYLIST);
+
+       ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->playlist_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAYLIST);
+
+       mc_client->playlist_cb.callback = NULL;
+       mc_client->playlist_cb.user_data = NULL;
+       mc_client->playlist_cb.filter_list = NULL;
+
+       return ret;
+}
+
 int mc_client_subscribe(mc_client_h client, const mc_subscription_type_e subscription_type, const char *server_name)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -586,6 +659,13 @@ int mc_client_subscribe(mc_client_h client, const mc_subscription_type_e subscri
                ret = __mc_client_register_filter_listener(mc_client, &mc_client->repeat_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT,
                                        __client_repeat_cb, (void *)&(mc_client->repeat_cb));
                break;
+       case MC_SUBSCRIPTION_TYPE_PLAYLIST:
+               mc_retvm_if(mc_client->playlist_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback");
+
+               ret = mc_ipc_unregister_listener(&mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYLIST);
+               ret = __mc_client_register_filter_listener(mc_client, &mc_client->playlist_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYLIST,
+                                       __client_playlist_cb, (void *)&(mc_client));
+               break;
        default:
                mc_error("Invalid subscription_type [%d]", subscription_type);
                return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
@@ -633,6 +713,12 @@ int mc_client_unsubscribe(mc_client_h client, const mc_subscription_type_e subsc
 
                ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->repeat_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT);
                break;
+       case MC_SUBSCRIPTION_TYPE_PLAYLIST:
+               mc_retvm_if(mc_client->playlist_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe");
+               mc_retvm_if(mc_client->playlist_cb.filter_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid filter_list. No list to unsubscribe");
+
+               ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->playlist_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYLIST);
+               break;
        default:
                mc_error("Invalid subscription_type [%d]", subscription_type);
                return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
@@ -670,6 +756,9 @@ int mc_client_foreach_server_subscribed(mc_client_h client, const mc_subscriptio
        case MC_SUBSCRIPTION_TYPE_REPEAT_MODE:
                filter_list = mc_client->repeat_cb.filter_list;
                break;
+       case MC_SUBSCRIPTION_TYPE_PLAYLIST:
+               filter_list = mc_client->playlist_cb.filter_list;
+               break;
        default:
                mc_error("Invalid subscription_type [%d]", subscription_type);
                return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
@@ -937,6 +1026,25 @@ int mc_client_get_server_repeat_mode(mc_client_h client, const char *server_name
        return ret;
 }
 
+int mc_client_get_server_playlist(mc_client_h client, const char *server_name, char **playlist_name, bundle **playlist)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       media_controller_client_s *mc_client = (media_controller_client_s *)client;
+       bool exist_server = FALSE;
+
+       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");
+       mc_retvm_if(playlist == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "playlist is NULL");
+
+       ret = mc_db_check_server_table_exist(mc_client->db_handle, server_name, &exist_server);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Error mc_db_check_server_table_exist [%d]", ret);
+       mc_retvm_if(exist_server == FALSE, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Error Invalid server_name");
+
+       ret = mc_db_get_playlist(mc_client->db_handle, server_name, playlist_name, playlist);
+
+       return ret;
+}
+
 int mc_client_foreach_server(mc_client_h client, mc_activated_server_cb callback, void *user_data)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -1177,6 +1285,7 @@ int mc_client_destroy(mc_client_h client)
        ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->metadata_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_METADATA);
        ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->shuffle_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE);
        ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->repeat_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT);
+       ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->playlist_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAYLIST);
 
        /*Unregister all listener*/
        ret = mc_ipc_unregister_all_listener(&mc_client->listeners, mc_client->dconn);
index c6eb60b3b2143a4bd9cd828b6c68e1672a907868..d2353f547665066fc923f0a91619d46de2363535 100755 (executable)
@@ -46,6 +46,8 @@ typedef enum {
        MC_SERVER_FIELD_REPEAT_MODE,
 } server_table_field_e;
 
+#define MC_DB_TABLE_PLAYLIST                   "server_playlist"
+
 static int __mc_db_busy_handler(void *pData, int count)
 {
        MC_MILLISEC_SLEEP(50);
@@ -146,6 +148,69 @@ static int __mc_db_get_ulong_value_of_key(void *handle, const char *server_name,
        return MEDIA_CONTROLLER_ERROR_NONE;
 }
 
+static int __db_get_playlist(void *handle, const char *server_name, char **playlist_name, bundle **playlist)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       char *sql_str = NULL;
+       sqlite3_stmt *stmt = NULL;
+       sqlite3 *db_handle = (sqlite3 *)handle;
+       char * _name = NULL;
+       bundle * _bundle_data = NULL;
+       bundle_raw *_raw_data = NULL;
+       int _raw_size = 0;
+
+       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 = sqlite3_mprintf("SELECT * from %s WHERE server_name = %Q", MC_DB_TABLE_PLAYLIST, server_name);
+       mc_retvm_if(!MC_STRING_VALID(sql_str), MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "SQL string is null");
+
+       mc_secure_debug("sql_str [%s]", sql_str);
+
+       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_debug("playlist is not exist [%s]", sqlite3_errmsg(db_handle));
+               SQLITE3_FINALIZE(stmt);
+               SQLITE3_SAFE_FREE(sql_str);
+               return MEDIA_CONTROLLER_ERROR_NONE;
+       }
+
+       while (SQLITE_ROW == ret) {
+               _name = g_strdup((const char *)sqlite3_column_text(stmt, 1));
+               _raw_data = (bundle_raw *)g_strdup((const char *)sqlite3_column_text(stmt, 2));
+               _raw_size = (int)sqlite3_column_int(stmt, 3);
+               ret = sqlite3_step(stmt);
+       }
+
+       SQLITE3_FINALIZE(stmt);
+       SQLITE3_SAFE_FREE(sql_str);
+
+       if ((_raw_data != NULL) && (_raw_size > 0)) {
+               _bundle_data = bundle_decode(_raw_data, _raw_size);
+
+               if (_bundle_data == NULL) {
+                       mc_error("fail while decoding bundle");
+                       MC_SAFE_FREE(_name);
+                       MC_SAFE_FREE(_raw_data);
+                       return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+               }
+       }
+
+       MC_SAFE_FREE(_raw_data);
+
+       *playlist_name = _name;
+       *playlist = _bundle_data;
+
+       return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
 static char* __mc_get_db_name(uid_t uid)
 {
        char result_psswd[MC_FILE_PATH_LEN_MAX] = {0, };
@@ -403,7 +468,7 @@ int mc_db_get_metadata_info(void *handle, const char *server_name, mc_metadata_h
                mc_error("end of row [%s]", sqlite3_errmsg(db_handle));
                SQLITE3_FINALIZE(stmt);
                SQLITE3_SAFE_FREE(sql_str);
-               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+               return MEDIA_CONTROLLER_ERROR_NONE;
        } else {
                _metadata = (media_controller_metadata_s *)calloc(1, sizeof(media_controller_metadata_s));
                if (_metadata == NULL) {
@@ -481,6 +546,14 @@ int mc_db_get_repeat_mode(void *handle, const char *server_name, mc_repeat_mode_
        return ret;
 }
 
+int mc_db_get_playlist(void *handle, const char *server_name, char **playlist_name, bundle **playlist)
+{
+       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");
+
+       return __db_get_playlist(handle, server_name, playlist_name, playlist);
+}
+
 int mc_db_insert_server_address_into_table(void *handle, const char *table_name, char *address)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
@@ -722,3 +795,46 @@ int mc_db_update_latest_server_table(void *handle, const char *server_name)
 
        return ret;
 }
+
+int mc_db_remove_playlist(void *handle, const char *server_name)
+{
+       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(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+       sql_str = sqlite3_mprintf("DELETE FROM '%q' WHERE server_name='%q';", MC_DB_TABLE_PLAYLIST, server_name);
+
+       ret = __mc_db_update_db(handle, sql_str);
+
+       SQLITE3_SAFE_FREE(sql_str);
+
+       return ret;
+}
+
+int mc_db_update_playlist(void *handle, const char *server_name, const char *playlist_name, bundle *data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       char *sql_str = NULL;
+       const char *db_fields = "server_name, playlist_name, data, data_size";
+       bundle_raw *raw_data = NULL;
+       int size_r = 0;
+
+       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(playlist_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "playlist_name is NULL");
+
+       if (data != NULL) {
+               ret = bundle_encode(data, &raw_data, &size_r);
+               mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "fail while encoding bundle [%d]", ret);
+       }
+
+       sql_str = sqlite3_mprintf("INSERT INTO '%q' (%q) VALUES (%Q, %Q, %Q, %d);", MC_DB_TABLE_PLAYLIST, db_fields, server_name, playlist_name, raw_data, size_r);
+
+       ret = __mc_db_update_db(handle, sql_str);
+
+       SQLITE3_SAFE_FREE(sql_str);
+
+       return ret;
+}
index 02931b7d1efa7fa85a3905c239fc6dcfc55e9d40..22415ae18aefad38aa01ad6a66b7d75368245c66 100755 (executable)
@@ -325,7 +325,7 @@ int mc_ipc_send_message_to_server(mc_msg_type_e msg_type, const int type, const
                return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
        }
 
-       mc_info("type [%d], message [%s]", type, request_msg);
+       mc_secure_debug("type [%d], message [%s]", type, request_msg);
 
        mc_comm_msg_s send_msg;
        memset((void *)&send_msg, 0, sizeof(mc_comm_msg_s));
index 326ad89f089af3ab0f60406188e6744c65bf4174..f5abcc1ce3c071086ac9527787c6502f76334e57 100755 (executable)
@@ -331,7 +331,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, int param1, unsigned long long param2)
+static int __mc_server_send_message(media_controller_server_s *mc_server, const char *interface_name, const char *signal_name, int param1, unsigned long long param2, const char* param3)
 {
        int ret = MEDIA_CONTROLLER_ERROR_NONE;
        char *message = NULL;
@@ -344,6 +344,8 @@ static int __mc_server_send_message(media_controller_server_s *mc_server, const
                message = g_strdup_printf("%s%s%d%s%llu", mc_server->server_name, MC_STRING_DELIMITER, param1, MC_STRING_DELIMITER, param2);
        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_PLAYLIST, signal_name))
+               message = g_strdup_printf("%s%s%d%s%s", mc_server->server_name, MC_STRING_DELIMITER, param1, MC_STRING_DELIMITER, param3);
        else
                message = g_strdup_printf("%s%s%d", mc_server->server_name, MC_STRING_DELIMITER, param1);
 
@@ -417,7 +419,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);
+       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, NULL);
        if (ret != MEDIA_CONTROLLER_ERROR_NONE)
                mc_error("Error __mc_server_send_message [%d]", ret);
 
@@ -449,7 +451,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);
+       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;
@@ -468,7 +470,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);
+       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;
@@ -559,7 +561,29 @@ 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);
+       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;
+}
+
+int mc_server_update_playlist(mc_server_h server, mc_playlist_update_mode_e mode, const char *playlist_name, bundle *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, "invalid server");
+       mc_retvm_if(!MC_STRING_VALID(playlist_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "invalid playlist_name");
+
+       ret = mc_db_remove_playlist(mc_server->db_handle, mc_server->server_name);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to mc_db_remove_playlist");
+
+       if (mode == MC_PLAYLIST_UPDATED) {
+               ret = mc_db_update_playlist(mc_server->db_handle, mc_server->server_name, playlist_name, data);
+               mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to mc_db_update_playlist");
+       }
+
+       ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYLIST, mode, 0, playlist_name);
        mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
 
        return ret;
@@ -915,7 +939,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);
+       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);
 
@@ -955,7 +979,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);
+       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 ec9f0cba652e96fc5142e9a9606a02f59075ddd4..d6b2fd80c9f3a84ea4b2eecc38221f73daa0e25c 100755 (executable)
@@ -31,6 +31,8 @@
 
 #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_TRIGGER_PLAYLIST                 "cleanup_playlist"
 
 #define DB_SELECT_ALL_SERVER_LIST_EXCEPT_LATEST        "SELECT name FROM SQLITE_MASTER WHERE type='table' AND (name != '%q') AND (name NOT IN (SELECT server_name FROM "MC_DB_TABLE_LATEST_SERVER"));"
 #define DB_SELECT_LATEST_SERVER "SELECT COUNT(*), server_name FROM "MC_DB_TABLE_LATEST_SERVER";"
@@ -134,6 +136,32 @@ static int __mc_create_server_list_table(sqlite3 *handle)
        return ret;
 }
 
+static int __mc_create_playlist_table(sqlite3 *handle)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       char *sql_str = NULL;
+
+       sql_str = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (\
+                               server_name TEXT PRIMARY KEY, \
+                               playlist_name TEXT NOT NULL, \
+                               data TEXT, \
+                               data_size INT);",
+                               MC_DB_TABLE_PLAYLIST);
+
+       ret = mc_db_util_update_db(handle, sql_str);
+       SQLITE3_SAFE_FREE(sql_str);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to create playlist table");
+
+       sql_str = sqlite3_mprintf("CREATE TRIGGER IF NOT EXISTS %s DELETE ON %s BEGIN DELETE FROM %s WHERE server_name=old.server_name;END",
+                                       MC_DB_TRIGGER_PLAYLIST, MC_DB_TABLE_SERVER_LIST, MC_DB_TABLE_PLAYLIST);
+
+       ret = mc_db_util_update_db(handle, sql_str);
+       SQLITE3_SAFE_FREE(sql_str);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to create playlist trigger");
+
+       return ret;
+}
+
 static char* __mc_get_db_name(uid_t uid)
 {
        char result_psswd[MC_FILE_PATH_LEN_MAX] = {0, };
@@ -269,6 +297,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_playlist_table(db_handle);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "create playlist table failed!err= [%d]", ret);
+
        return MEDIA_CONTROLLER_ERROR_NONE;
 }
 
@@ -281,7 +312,7 @@ int mc_db_util_update_db(void *handle, const char *sql_str)
        mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
        mc_retvm_if(sql_str == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "sql_str is NULL");
 
-       mc_debug("Update query [%s]", sql_str);
+       mc_secure_debug("Update query [%s]", sql_str);
 
        ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &err_msg);
        if (SQLITE_OK != ret) {
index cb69a67431d4d2642827ce44288f182f1a3ac954..61b9fb7cff242c9d8ed3784d7d62ec02045c9d87 100755 (executable)
@@ -17,6 +17,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <inttypes.h>
 
 #include <glib.h>
 #include <glib/gprintf.h>
@@ -122,6 +123,12 @@ void _mc_repeat_mode_updated_cb(const char *server_name, mc_repeat_mode_e mode,
        mc_debug("[Client:%s] Repeat mode(%d) updated from server[%s]", _client->client_name, mode, server_name);
 }
 
+void _mc_playlist_update_cb(const char *server_name, mc_playlist_update_mode_e mode, const char *playlist_name, bundle *data, void *user_data)
+{
+       media_controller_client_s *_client = (media_controller_client_s *)g_mc_client;
+       mc_debug("[Client:%s] playlist update mode[%d], playlist_name[%s] updated from server[%s]", _client->client_name, mode, playlist_name, server_name);
+}
+
 bool _mc_activated_server_cb(const char *server_name, void *user_data)
 {
        media_controller_client_s *_client = (media_controller_client_s *)g_mc_client;
@@ -143,7 +150,7 @@ void _mc_command_reply_received_cb(const char *server_name, int result_code, bun
 static gboolean _create()
 {
        g_print("== create \n");
-       int ret;
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
 
        ret = mc_client_create(&g_mc_client);
        if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
@@ -158,7 +165,7 @@ static gboolean _create()
 static gboolean _foreach()
 {
        g_print("== create \n");
-       int ret;
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
 
        ret = mc_client_foreach_server(g_mc_client, _mc_activated_server_cb, NULL);
        if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
@@ -170,90 +177,94 @@ static gboolean _foreach()
        return TRUE;
 }
 
-static gboolean _set()
+static gboolean _set_callback()
 {
-       g_print("== set default callback \n");
        int ret = TRUE;
 
+       mc_debug_fenter();
+
        ret = mc_client_set_server_update_cb(g_mc_client, _mc_server_state_updated_cb, NULL);
-       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-               g_print("Fail to set param and initialize %d", ret);
-               return FALSE;
-       }
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_set_server_update_cb [%d]", ret);
 
        ret = mc_client_set_playback_update_cb(g_mc_client, _mc_playback_updated_cb, NULL);
-       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-               g_print("Fail to set param and initialize %d", ret);
-               return FALSE;
-       }
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_set_playback_update_cb [%d]", ret);
 
        ret = mc_client_set_metadata_update_cb(g_mc_client, _mc_metadata_updated_cb, NULL);
-       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-               g_print("Fail to set param and initialize %d", ret);
-               return FALSE;
-       }
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_set_metadata_update_cb [%d]", ret);
 
        ret = mc_client_set_shuffle_mode_update_cb(g_mc_client, _mc_shuffle_mode_updated_cb, NULL);
-       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-               g_print("Fail to set param and initialize %d", ret);
-               return FALSE;
-       }
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_set_shuffle_mode_update_cb [%d]", ret);
 
        ret = mc_client_set_repeat_mode_update_cb(g_mc_client, _mc_repeat_mode_updated_cb, NULL);
-       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-               g_print("Fail to set param and initialize %d", ret);
-               return FALSE;
-       }
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_set_repeat_mode_update_cb [%d]", ret);
 
-       g_print("==\n");
+       ret = mc_client_set_playlist_update_cb(g_mc_client, _mc_playlist_update_cb, NULL);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_set_playlist_update_cb [%d]", ret);
+
+       mc_debug_fleave();
 
        return ret;
 }
 
-static gboolean _unset()
+static gboolean _unset_callback()
 {
-       g_print("== unset callback \n");
-       int ret;
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+       mc_debug_fenter();
 
        ret = mc_client_unset_server_update_cb(g_mc_client);
-       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-               g_print("Fail to deinitialize %d", ret);
-               return FALSE;
-       }
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_unset_server_update_cb [%d]", ret);
 
        ret = mc_client_unset_playback_update_cb(g_mc_client);
-       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-               g_print("Fail to deinitialize %d", ret);
-               return FALSE;
-       }
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_unset_playback_update_cb [%d]", ret);
 
        ret = mc_client_unset_metadata_update_cb(g_mc_client);
-       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-               g_print("Fail to deinitialize %d", ret);
-               return FALSE;
-       }
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_unset_metadata_update_cb [%d]", ret);
 
        ret = mc_client_unset_shuffle_mode_update_cb(g_mc_client);
-       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-               g_print("Fail to deinitialize %d", ret);
-               return FALSE;
-       }
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_unset_shuffle_mode_update_cb [%d]", ret);
 
        ret = mc_client_unset_repeat_mode_update_cb(g_mc_client);
-       if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-               g_print("Fail to deinitialize %d", ret);
-               return FALSE;
-       }
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_unset_repeat_mode_update_cb [%d]", ret);
+
+       ret = mc_client_unset_playlist_update_cb(g_mc_client);
+       mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_unset_playlist_update_cb [%d]", ret);
 
-       g_print("== success destroy \n");
+       mc_debug_fleave();
 
        return TRUE;
 }
 
+void __playlist_get_info_cb(const char *key, const int type, const bundle_keyval_t *kv, void *user_data)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+       void **array_val = NULL;
+       unsigned int array_len = 0;
+       size_t *array_elem_size = NULL;
+       unsigned int idx = 0;
+
+       printf("Key:%s, Type:%d\n", key, type);
+
+       if (bundle_keyval_type_is_array((bundle_keyval_t *)kv)) {
+               ret = bundle_keyval_get_array_val((bundle_keyval_t *)kv, &array_val, &array_len, &array_elem_size);
+               if (ret != BUNDLE_ERROR_NONE) {
+                       printf("Fail to bundle_keyval_type_is_array [%d]\n", ret);
+                       return;
+               }
+
+               printf("array_len [%d]\n", array_len);
+
+               for (idx = 0; idx < array_len; idx++) {
+                       printf("[%d] [%s][%zu]\n", idx, (char *)array_val[idx], array_elem_size[idx]);
+               }
+       } else {
+               printf("Wrong Type\n");
+       }
+}
+
 static gboolean _get_info(int type)
 {
-       g_print("== get information \n");
-       int ret;
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
        mc_server_state_e server_state;
        mc_playback_h playback;
        mc_playback_states_e playback_state;
@@ -262,22 +273,24 @@ static gboolean _get_info(int type)
        char *metadata_value;
        mc_shuffle_mode_e shuffle_mode;
        mc_repeat_mode_e repeate_mode;
+       bundle *playlist = NULL;
+       char *playlist_name = NULL;
+       int bundle_cnt = 0;
+
+       mc_debug_fenter();
 
        switch (type) {
        case 1:
                ret = mc_client_get_latest_server_info(g_mc_client, &g_server_name, &server_state);
-               if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-                       g_print("Fail to get latest server info");
-                       return FALSE;
-               }
+               mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_get_latest_server_info [%d]", ret);
+
                g_print("get server name: %s, state: %d", g_server_name, server_state);
+
                break;
        case 2:
                ret = mc_client_get_server_playback_info(g_mc_client, g_server_name, &playback);
-               if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-                       g_print("Fail to get playback info");
-                       return FALSE;
-               }
+               mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_get_server_playback_info [%d]", ret);
+
                ret = mc_client_get_playback_state(playback, &playback_state);
                if (ret != MEDIA_CONTROLLER_ERROR_NONE)
                        g_print("Fail to get playback state");
@@ -289,52 +302,62 @@ static gboolean _get_info(int type)
                g_print("playback state: %d, position: %lld", playback_state, playback_position);
 
                ret = mc_client_destroy_playback(playback);
-               if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-                       g_print("Fail to destroy playback");
-                       return FALSE;
-               }
+               mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_destroy_playback [%d]", ret);
+
                break;
        case 3:
                ret = mc_client_get_server_metadata(g_mc_client, g_server_name, &metadata);
-               if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-                       g_print("Fail to get metadata");
-                       return FALSE;
-               }
+               mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_get_server_metadata [%d]", ret);
+
                ret = mc_client_get_metadata(metadata, MC_META_MEDIA_TITLE, &metadata_value);
                if (ret != MEDIA_CONTROLLER_ERROR_NONE)
                        g_print("Fail to get infot");
 
                g_print("metadata title: %s", metadata_value);
 
-               ret = mc_client_destroy_metadata(metadata);
-               if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-                       g_print("Fail to destroy metadata");
-                       return FALSE;
-               }
                free(metadata_value);
+
+               ret = mc_client_destroy_metadata(metadata);
+               mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_destroy_metadata [%d]", ret);
+
                break;
        case 4:
                ret = mc_client_get_server_shuffle_mode(g_mc_client, g_server_name, &shuffle_mode);
-               if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-                       g_print("Fail to get infot");
-                       return FALSE;
-               }
+               mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_get_server_shuffle_mode [%d]", ret);
+
                g_print("shuffle mode: %d", shuffle_mode);
                break;
        case 5:
                ret = mc_client_get_server_repeat_mode(g_mc_client, g_server_name, &repeate_mode);
-               if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-                       g_print("Fail to get infot");
-                       return FALSE;
-               }
+               mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_get_server_repeat_mode [%d]", ret);
+
                g_print("repeate mode: %d", repeate_mode);
+               break;
+       case 6:
+               ret = mc_client_get_server_playlist(g_mc_client, g_server_name, &playlist_name, &playlist);
+               mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, FALSE, "Fail to mc_client_get_server_playlist [%d]", ret);
+
+               if (playlist != NULL) {
+                       bundle_cnt = bundle_get_count(playlist);
+
+                       g_print("playlist_name [%s] bundle_cnt [%d] \n", playlist_name, bundle_cnt);
+
+                       bundle_foreach(playlist, __playlist_get_info_cb, NULL);
+
+                       bundle_free(playlist);
+               } else {
+                       g_print("There is no playlist \n");
+               }
+
+               MC_SAFE_FREE(playlist_name);
+
                break;
        default:
                g_print("== unknown type!\n");
                return TRUE;
        }
 
-       g_print("== success get information \n");
+       mc_debug_fleave();
 
        return TRUE;
 }
@@ -414,8 +437,9 @@ static gboolean _send()
 
 static gboolean _destroy()
 {
-       g_print("== destroy \n");
-       int ret;
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+       mc_debug_fenter();
 
        ret = mc_client_destroy(g_mc_client);
        if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
@@ -423,8 +447,10 @@ static gboolean _destroy()
                return FALSE;
        }
 
-       g_print("== success destroy \n");
        g_mc_client = NULL;
+
+       mc_debug_fleave();
+
        return TRUE;
 }
 
@@ -462,7 +488,8 @@ static void display_information_menu(void)
        g_print("2. get latest server playback \n");
        g_print("3. get latest server metadata \n");
        g_print("4. get latest server shuffle mode \n");
-       g_print("5. get latest server repeate moder \n");
+       g_print("5. get latest server repeate mode \n");
+       g_print("6. get playlist \n");
        g_print("0. back \n");
        g_print("----------------------------------------------------\n");
        g_print("====================================================\n");
@@ -513,8 +540,12 @@ void _interpret_information_menu(char *cmd)
                        _get_info(4);
                else if (!strncmp(cmd, "5", len))
                        _get_info(5);
+               else if (!strncmp(cmd, "6", len))
+                       _get_info(6);
                else if (!strncmp(cmd, "0", len))
                        reset_current_menu_state();
+               else
+                       g_print("wrong command [%s] \n", cmd);
        } else {
                g_print("wrong command\n");
        }
@@ -530,9 +561,9 @@ void _interpret_main_menu(char *cmd)
                else if (!strncmp(cmd, "2", len))
                        _foreach();
                else if (!strncmp(cmd, "3", len))
-                       _set();
+                       _set_callback();
                else if (!strncmp(cmd, "4", len))
-                       _unset();
+                       _unset_callback();
                else if (!strncmp(cmd, "5", len))
                        g_menu_state = CURRENT_STATE_INFORMATION_GET_MENU;
                else if (!strncmp(cmd, "6", len))
index d978989e5966b927fe34e4c83931ccbaa3cecd8f..d6843f2b7d61fc6e725e468180a545089eb45a9d 100755 (executable)
 #include <glib.h>
 #include <glib/gprintf.h>
 
-#include <media_controller_client.h>
+#include <bundle.h>
+#include <media_controller_server.h>
 #include "media_controller_private.h"
 
 
-#define PACKAGE "media_controller_client_test"
-
 /*===========================================================================================
 |                                             |
 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                      |
@@ -40,6 +39,7 @@ static mc_client_h g_mc_server;
 static int g_metadata_type;
 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;
 
 GMainLoop *mainloop = NULL;
 
@@ -136,6 +136,74 @@ void __custom_command_received_cb(const char *client_name, const char *command,
                g_free(bundle_data);
 }
 
+static int __update_playlist(mc_server_h server, mc_playlist_update_mode_e mode)
+{
+       int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+       const char *playlist_name = "test_playlist";
+       bundle * bundle_data = NULL;
+
+       unsigned int meta_cnt = MC_META_MEDIA_PICTURE + 1;
+       const char *idx_1[meta_cnt];
+       const char *idx_2[meta_cnt];
+       const char *idx_3[meta_cnt];
+
+       memset(idx_1, 0, sizeof(idx_1));
+       memset(idx_2, 0, sizeof(idx_2));
+       memset(idx_3, 0, sizeof(idx_3));
+
+       g_print("== Start __update_playlist [%d] \n", meta_cnt);
+
+       idx_1[MC_META_MEDIA_TITLE] = "title_1";
+       idx_1[MC_META_MEDIA_ARTIST] = "artist_1";
+       idx_1[MC_META_MEDIA_ALBUM] = "album_1";
+       idx_1[MC_META_MEDIA_AUTHOR] = "author_1";
+       idx_1[MC_META_MEDIA_GENRE] = "genre_1";
+       idx_1[MC_META_MEDIA_DURATION] = "duration_1";
+       idx_1[MC_META_MEDIA_DATE] = "date_1";
+       idx_1[MC_META_MEDIA_COPYRIGHT] = "copyright_1";
+       idx_1[MC_META_MEDIA_DESCRIPTION] = "destription_1";
+       idx_1[MC_META_MEDIA_TRACK_NUM] = "track_num_1";
+       idx_1[MC_META_MEDIA_PICTURE] = "picture_1";
+
+       idx_2[MC_META_MEDIA_TITLE] = "title_2";
+       idx_2[MC_META_MEDIA_ARTIST] = "artist_2";
+       idx_2[MC_META_MEDIA_ALBUM] = "album_2";
+       idx_2[MC_META_MEDIA_AUTHOR] = "author_2";
+       idx_2[MC_META_MEDIA_GENRE] = "genre_2";
+       idx_2[MC_META_MEDIA_DURATION] = "duration_2";
+       idx_2[MC_META_MEDIA_DATE] = "date_2";
+       idx_2[MC_META_MEDIA_COPYRIGHT] = "copyright_2";
+//     idx_2[MC_META_MEDIA_DESCRIPTION] = NULL;
+       idx_2[MC_META_MEDIA_TRACK_NUM] = "track_num_2";
+//     idx_2[MC_META_MEDIA_PICTURE] = NULL;
+
+       idx_3[MC_META_MEDIA_TITLE] = "title_3";
+       idx_3[MC_META_MEDIA_ARTIST] = "artist_3";
+       idx_3[MC_META_MEDIA_ALBUM] = "album_3";
+       idx_3[MC_META_MEDIA_AUTHOR] = "author_3";
+       idx_3[MC_META_MEDIA_GENRE] = "genre_3";
+       idx_3[MC_META_MEDIA_DURATION] = "duration_3";
+       idx_3[MC_META_MEDIA_DATE] = NULL;
+       idx_3[MC_META_MEDIA_COPYRIGHT] = "copyright_3";
+       idx_3[MC_META_MEDIA_DESCRIPTION] = NULL;
+       idx_3[MC_META_MEDIA_TRACK_NUM] = "track_num_3";
+       idx_3[MC_META_MEDIA_PICTURE] = NULL;
+
+       bundle_data = bundle_create();
+       bundle_add_str_array(bundle_data, "idx1", idx_1, meta_cnt);
+       bundle_add_str_array(bundle_data, "idx2", idx_2, meta_cnt);
+       bundle_add_str_array(bundle_data, "idx3", idx_3, meta_cnt);
+
+       ret = mc_server_update_playlist(server, mode, playlist_name, bundle_data);
+
+       bundle_free(bundle_data);
+
+       g_print("== Success __update_playlist \n");
+
+       return ret;
+}
+
 static gboolean _create()
 {
        g_print("== create \n");
@@ -293,6 +361,18 @@ static gboolean _update_info(int type)
                        return FALSE;
                }
                break;
+       case 5:
+               if (g_playlist_mode == MC_PLAYLIST_UPDATED)
+                       g_playlist_mode = MC_PLAYLIST_REMOVED;
+               else
+                       g_playlist_mode = MC_PLAYLIST_UPDATED;
+
+               ret = __update_playlist(g_mc_server, g_playlist_mode);
+               if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+                       g_print("Fail to update playlist err=%d\n", ret);
+                       return FALSE;
+               }
+               break;
        default:
                g_print(" == unknown type!\n");
                return TRUE;
@@ -352,7 +432,8 @@ static void display_update_info_menu(void)
        g_print("1. update server playback \n");
        g_print("2. update server metadata \n");
        g_print("3. update server shuffle mode \n");
-       g_print("4. update server repeate moder \n");
+       g_print("4. update server repeate mode \n");
+       g_print("5. update playlist \n");
        g_print("0. back \n");
        g_print("----------------------------------------------------\n");
        g_print("====================================================\n");
@@ -418,6 +499,8 @@ void _interpret_update_info_menu(char *cmd)
                        _update_info(3);
                else if (!strncmp(cmd, "4", len))
                        _update_info(4);
+               else if (!strncmp(cmd, "5", len))
+                       _update_info(5);
                else if (!strncmp(cmd, "0", len))
                        reset_current_menu_state();
        } else {
@@ -464,6 +547,8 @@ void _interpret_main_menu(char *cmd)
                        _destroy();
                else if (!strncmp(cmd, "0", len))
                        quit();
+               else
+                       g_print("wrong command [%s]\n", cmd);
        } else {
                g_print("wrong command\n");
        }
@@ -587,6 +672,7 @@ int main(int argc, char **argv)
 
        g_shuffle_mode = MC_SHUFFLE_MODE_OFF;
        g_repeat_mode = MC_REPEAT_MODE_OFF;
+       g_playlist_mode = MC_PLAYLIST_REMOVED;
 
        mainloop = g_main_loop_new(NULL, FALSE);