From: hj kim Date: Thu, 29 Mar 2018 01:40:42 +0000 (+0900) Subject: [ACR-1190] Add new APIs to support playlist X-Git-Tag: submit/tizen/20180403.050213~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fead5afc48277e7bc5a902f14549d57cf80d22c7;p=platform%2Fcore%2Fapi%2Fmedia-controller.git [ACR-1190] Add new APIs to support playlist Change-Id: Iec9a08c93aa755d46fe3bb8bac48151ede42c55d --- diff --git a/include/media_controller_client.h b/include/media_controller_client.h index 1d88bef..6f4552f 100755 --- a/include/media_controller_client.h +++ b/include/media_controller_client.h @@ -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 diff --git a/include/media_controller_db.h b/include/media_controller_db.h index 81a05d3..7cc718b 100755 --- a/include/media_controller_db.h +++ b/include/media_controller_db.h @@ -20,6 +20,7 @@ #include #include #include +#include #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__*/ diff --git a/include/media_controller_private.h b/include/media_controller_private.h index b3606f5..1de3966 100755 --- a/include/media_controller_private.h +++ b/include/media_controller_private.h @@ -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 */ diff --git a/include/media_controller_server.h b/include/media_controller_server.h index 8586410..f993540 100755 --- a/include/media_controller_server.h +++ b/include/media_controller_server.h @@ -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 + #include + 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. diff --git a/include/media_controller_type.h b/include/media_controller_type.h index d0edab8..970b4e4 100755 --- a/include/media_controller_type.h +++ b/include/media_controller_type.h @@ -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; + /** * @} */ diff --git a/packaging/capi-media-controller.spec b/packaging/capi-media-controller.spec index 2aa589c..ec609f6 100755 --- a/packaging/capi-media-controller.spec +++ b/packaging/capi-media-controller.spec @@ -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 diff --git a/src/media_controller_client.c b/src/media_controller_client.c index 830236f..a7517ad 100755 --- a/src/media_controller_client.c +++ b/src/media_controller_client.c @@ -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); diff --git a/src/media_controller_db.c b/src/media_controller_db.c index c6eb60b..d2353f5 100755 --- a/src/media_controller_db.c +++ b/src/media_controller_db.c @@ -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; +} diff --git a/src/media_controller_ipc.c b/src/media_controller_ipc.c index 02931b7..22415ae 100755 --- a/src/media_controller_ipc.c +++ b/src/media_controller_ipc.c @@ -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)); diff --git a/src/media_controller_server.c b/src/media_controller_server.c index 326ad89..f5abcc1 100755 --- a/src/media_controller_server.c +++ b/src/media_controller_server.c @@ -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); diff --git a/svc/media_controller_db_util.c b/svc/media_controller_db_util.c index ec9f0cb..d6b2fd8 100755 --- a/svc/media_controller_db_util.c +++ b/svc/media_controller_db_util.c @@ -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) { diff --git a/test/client_test/media_controller_client_test.c b/test/client_test/media_controller_client_test.c index cb69a67..61b9fb7 100755 --- a/test/client_test/media_controller_client_test.c +++ b/test/client_test/media_controller_client_test.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -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)) diff --git a/test/server_test/media_controller_server_test.c b/test/server_test/media_controller_server_test.c index d978989..d6843f2 100755 --- a/test/server_test/media_controller_server_test.c +++ b/test/server_test/media_controller_server_test.c @@ -21,12 +21,11 @@ #include #include -#include +#include +#include #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);