diff options
author | Ji Yong Min <jiyong.min@samsung.com> | 2015-09-23 14:23:32 +0900 |
---|---|---|
committer | Ji Yong Min <jiyong.min@samsung.com> | 2015-09-23 16:02:40 +0900 |
commit | 109147a8c9173467a69a9a084ad2788316e795ed (patch) | |
tree | 398e2fb7175abaa226a8ddd65ff01dbb408f7697 | |
parent | cec086ed5856b854f09c504b3c4bd26c1a151af5 (diff) | |
download | media-controller-109147a8c9173467a69a9a084ad2788316e795ed.tar.gz media-controller-109147a8c9173467a69a9a084ad2788316e795ed.tar.bz2 media-controller-109147a8c9173467a69a9a084ad2788316e795ed.zip |
Fix some bugssubmit/tizen/20150924.023407submit/tizen/20150923.081917accepted/tizen/wearable/20150924.051059accepted/tizen/tv/20150924.051049accepted/tizen/mobile/20150924.051033
- Add to remove & create db table when service is started
- Add new subscribe APIs
- Modify enum value
- Fix bugs for service list
- Add to get uid via dbus
Change-Id: I43a07dc1ec194b3d222bb1a3635136c75c2edcac
Signed-off-by: Jiyong Min <jiyong.min@samsung.com>
-rwxr-xr-x | capi-media-controller.manifest | 3 | ||||
-rwxr-xr-x | include/media_controller_client.h | 97 | ||||
-rwxr-xr-x | include/media_controller_db.h | 1 | ||||
-rwxr-xr-x | include/media_controller_private.h | 35 | ||||
-rwxr-xr-x | include/media_controller_type.h | 58 | ||||
-rwxr-xr-x | packaging/capi-media-controller.spec | 3 | ||||
-rwxr-xr-x | src/media_controller_client.c | 340 | ||||
-rwxr-xr-x | src/media_controller_db.c | 54 | ||||
-rwxr-xr-x | src/media_controller_ipc.c | 10 | ||||
-rwxr-xr-x | src/media_controller_server.c | 59 | ||||
-rwxr-xr-x | src/media_controller_util.c | 25 | ||||
-rwxr-xr-x | svc/CMakeLists.txt | 2 | ||||
-rwxr-xr-x | svc/media_controller_db_util.c | 162 | ||||
-rwxr-xr-x | svc/media_controller_db_util.h | 9 | ||||
-rwxr-xr-x | svc/media_controller_socket.c | 2 | ||||
-rwxr-xr-x | svc/media_controller_svc.c | 145 | ||||
-rwxr-xr-x | test/client_test/media_controller_client_test.c | 27 | ||||
-rwxr-xr-x | test/server_test/media_controller_server_test.c | 53 |
18 files changed, 870 insertions, 215 deletions
diff --git a/capi-media-controller.manifest b/capi-media-controller.manifest index b1ebd13..c00c25b 100755 --- a/capi-media-controller.manifest +++ b/capi-media-controller.manifest @@ -2,7 +2,4 @@ <request> <domain name="_" /> </request> - <assign> - <filesystem path="/usr/bin/media-controller_create_db.sh" exec_label="System" /> - </assign> </manifest> diff --git a/include/media_controller_client.h b/include/media_controller_client.h index dbdc53d..3ddaf87 100755 --- a/include/media_controller_client.h +++ b/include/media_controller_client.h @@ -135,6 +135,21 @@ typedef bool (*mc_activated_server_cb)(const char *server_name, void *user_data) */ typedef void (*mc_command_reply_received_cb)(const char *server_name, int result_code, bundle *data, void *user_data); +/** + * @brief Called when requesting the list of subscribed servers. + * @since_tizen 2.4 + * + * @param[in] server_name, The app_id of the subscribed media controller server + * @param[in] user_data The user data passed from the mc_client_foreach_server_subscribed() fuction + * + * @return @c true to continue with the next iteration of the loop, + * otherwise @c false to break out of the loop + * + * @pre mc_client_foreach_server_subscribed() + * + * @see mc_client_foreach_server_subscribed() + */ +typedef bool (*mc_subscribed_server_cb)(const char *server_name, void *user_data); /** * @brief Creates a media controller client. @@ -160,6 +175,7 @@ int mc_client_create(mc_client_h *client); /** * @brief Sets the callback for monitoring status of the media controller server. * @since_tizen 2.4 + * @details If media controller client call this function, basically the media controller client recieve the callback from all media controller servers. * * @privlevel public * @privilege %http://tizen.org/privilege/mediacontroller.client @@ -200,6 +216,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. * @since_tizen 2.4 + * @details If media controller client call this function, basically the media controller client recieve the callback from all media controller servers. \n * * @privlevel public * @privilege %http://tizen.org/privilege/mediacontroller.client @@ -240,6 +257,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. * @since_tizen 2.4 + * @details If media controller client call this function, basically the media controller client recieve the callback from all media controller servers. * * @privlevel public * @privilege %http://tizen.org/privilege/mediacontroller.client @@ -280,6 +298,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. * @since_tizen 2.4 + * @details If media controller client call this function, basically the media controller client recieve the callback from all media controller servers. * * @privlevel public * @privilege %http://tizen.org/privilege/mediacontroller.client @@ -320,6 +339,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. * @since_tizen 2.4 + * @details If media controller client call this function, basically the media controller client recieve the callback from all media controller servers. * * @privlevel public * @privilege %http://tizen.org/privilege/mediacontroller.client @@ -358,6 +378,82 @@ 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 Subscribes media controller server for monitoring status. + * @since_tizen 2.4 + * @details If media controller client subscribe media controller server, \n + * the media controller client recieve callback from subscribed media controller server. \n + * If media controller client subscribe media controller server one or more, \n + * the media controller client can recieve callback from only subscribed media controller server. \n + * If you want to subscribe for the all media controller server again, \n + * unset mode update callback and set the callback for the monitoring status again. \n + * + * @privlevel public + * @privilege %http://tizen.org/privilege/mediacontroller.client + * + * @param [in] client The handle to the media controller client + * @param [in] subscription_type The subscription type + * @param [in] server_name The app_id of the media controller server + * @return @c 0 on success, + * otherwise a negative error value + * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful + * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre Create a media controller client handle by calling mc_client_create() + * @pre Set the callback for monitoring status of the media controller server + * @post Unsubscribe the media controller server for monitoring status by calling mc_client_unsubscribe() + * @see mc_client_create() + * @see mc_client_unsubscribe() + */ +int mc_client_subscribe(mc_client_h client, mc_subscription_type_e subscription_type, const char *server_name); + +/** + * @brief Unsubscribes media controller server for monitoring status. + * @since_tizen 2.4 + * @details If media controller client unsubscribe media controller server, \n + * the media controller client don't recieve callback from unsubscribed media controller server. \n + * If media controller client unsubscribe all subscibed media controller server, \n + * the media controller client don't recieve callback from all media controller server. \n + * After unset and set update callback function is called again, the media controller client can recieve callback from all media controller servers. \n + * + * @privlevel public + * @privilege %http://tizen.org/privilege/mediacontroller.client + * + * @param [in] client The handle to the media controller client + * @param [in] subscription_type The subscription type + * @param [in] server_name The app_id of the media controller server + * @return @c 0 on success, + * otherwise a negative error value + * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful + * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre Create a media controller client handle by calling mc_client_create() + * @pre Subscribe the media controller server for monitoring status by calling mc_client_subscribe() + * @see mc_client_create() + * @see mc_client_subscribe() + */ +int mc_client_unsubscribe(mc_client_h client, mc_subscription_type_e subscription_type, const char *server_name); + +/** + * @brief Retrieves all subscribed Server. + * @since_tizen 2.4 + * + * @privlevel public + * @privilege %http://tizen.org/privilege/mediacontroller.client + * + * @param [in] client The handle to the media controller client + * @param [in] subscription_type The subscription type + * @param [in] callback The callback to be invoked when the list of the subscribed media controller server. + * @param [in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful + * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre Create a media controller client handle by calling mc_client_create() + * @pre Subscribe the media controller server for monitoring status by calling mc_client_subscribe() + * @see mc_client_create() + * @see mc_client_subscribe() + */ +int mc_client_foreach_server_subscribed(mc_client_h client, mc_subscription_type_e subscription_type, mc_subscribed_server_cb callback, void *user_data); + +/** * @brief Gets the playback state. * @since_tizen 2.4 * @@ -412,6 +508,7 @@ int mc_client_destroy_playback(mc_playback_h playback); * @since_tizen 2.4 * * @remarks You must release @a metadata using @c mc_client_destroy_metadata(). \n + * And also You must release @a value using free(). * If the attribute value of the metadata is empty, return value is NULL. * * @param [in] metadata The handle to metadata diff --git a/include/media_controller_db.h b/include/media_controller_db.h index 245f71a..35a585f 100755 --- a/include/media_controller_db.h +++ b/include/media_controller_db.h @@ -61,7 +61,6 @@ int mc_db_connect(void **db_handle, bool need_write); int mc_db_disconnect(void *db_handle); -int mc_db_create_tables(void *handle); int mc_db_create_server_table(void *handle, const char *server_name); int mc_db_delete_server_table(void *handle, const char *server_name); int mc_db_check_server_table_exist(void *handle, const char *server_name, bool *exist); diff --git a/include/media_controller_private.h b/include/media_controller_private.h index f9b860d..1eb3dfc 100755 --- a/include/media_controller_private.h +++ b/include/media_controller_private.h @@ -132,10 +132,26 @@ extern "C" { #define MC_COMMAND_PLAYBACKSTATE "_playback_command_" #define MC_COMMAND_CUSTOM "_custom_command_" +#define MC_MILLISEC_SLEEP(msec) \ + do { \ + if(msec) { \ + unsigned long sec_t = 0; \ + unsigned long nsec_t = 0; \ + unsigned long cal_time = msec * 1000000; \ + sec_t = cal_time / 1000000000; \ + nsec_t = cal_time % 1000000000; \ + struct timespec reqtime; \ + reqtime.tv_sec = sec_t; \ + reqtime.tv_nsec = nsec_t; \ + nanosleep(&reqtime, NULL); \ + } \ + } while (0) + typedef struct { void *callback; void *user_data; -}media_controller_reciever_s; + GList *filter_list; +}media_controller_receiver_s; typedef struct { mc_playback_states_e state; @@ -169,8 +185,8 @@ typedef struct { media_controller_playback_s playback; media_controller_metadata_s *metadata; - media_controller_reciever_s playback_state_reciever; - media_controller_reciever_s custom_cmd_reciever; + media_controller_receiver_s playback_state_reciever; + media_controller_receiver_s custom_cmd_reciever; }media_controller_server_s; typedef struct { @@ -182,12 +198,12 @@ typedef struct { GList *listeners; - media_controller_reciever_s playback_cb; - media_controller_reciever_s metadata_cb; - media_controller_reciever_s server_state_cb; - media_controller_reciever_s shuffle_cb; - media_controller_reciever_s repeat_cb; - media_controller_reciever_s reply_cb; + media_controller_receiver_s playback_cb; + media_controller_receiver_s metadata_cb; + media_controller_receiver_s server_state_cb; + media_controller_receiver_s shuffle_cb; + media_controller_receiver_s repeat_cb; + media_controller_receiver_s reply_cb; }media_controller_client_s; /* formal callback to receive signal */ @@ -206,6 +222,7 @@ typedef struct { /* util */ int mc_util_get_own_name(char **name); char* mc_util_get_interface_name(const char *type, const char *name); +int mc_util_make_filter_interface_name(const char *prefix, const char *filter, char **interface_name); int mc_util_set_command_availabe(const char *name, const char *command_type, const char *command); int mc_util_get_command_availabe(const char *name, const char *command_type, const char *command); diff --git a/include/media_controller_type.h b/include/media_controller_type.h index e966525..93001d9 100755 --- a/include/media_controller_type.h +++ b/include/media_controller_type.h @@ -87,17 +87,17 @@ typedef enum { * @since_tizen 2.4 */ typedef enum { - MEDIA_TITLE = 0, /**< Title */ - MEDIA_ARTIST, /**< Artist */ - MEDIA_ALBUM, /**< Album */ - MEDIA_AUTHOR, /**< Author */ - MEDIA_GENRE, /**< Genre */ - MEDIA_DURATION, /**< Duration */ - MEDIA_DATE, /**< Date */ - MEDIA_COPYRIGHT, /**< Copyright */ - MEDIA_DESCRIPTION, /**< Description */ - MEDIA_TRACK_NUM, /**< Track Number */ - MEDIA_PICTURE, /**< Picture. Album Art */ + MC_META_MEDIA_TITLE = 0, /**< Title */ + MC_META_MEDIA_ARTIST, /**< Artist */ + MC_META_MEDIA_ALBUM, /**< Album */ + MC_META_MEDIA_AUTHOR, /**< Author */ + MC_META_MEDIA_GENRE, /**< Genre */ + MC_META_MEDIA_DURATION, /**< Duration */ + MC_META_MEDIA_DATE, /**< Date */ + MC_META_MEDIA_COPYRIGHT, /**< Copyright */ + MC_META_MEDIA_DESCRIPTION, /**< Description */ + MC_META_MEDIA_TRACK_NUM, /**< Track Number */ + MC_META_MEDIA_PICTURE, /**< Picture. Album Art */ } mc_meta_e; /** @@ -105,14 +105,14 @@ typedef enum { * @since_tizen 2.4 */ typedef enum { - MEDIA_PLAYBACK_STATE_NONE = 0, /**< None */ - MEDIA_PLAYBACK_STATE_PLAYING, /**< Play */ - MEDIA_PLAYBACK_STATE_PAUSED, /**< Pause */ - MEDIA_PLAYBACK_STATE_STOPPED, /**< Stop */ - MEDIA_PLAYBACK_STATE_NEXT_FILE, /**< Next file */ - MEDIA_PLAYBACK_STATE_PREV_FILE, /**< Previous file */ - MEDIA_PLAYBACK_STATE_FAST_FORWARD, /**< Fast forward */ - MEDIA_PLAYBACK_STATE_REWIND, /**< Rewind */ + MC_PLAYBACK_STATE_NONE = 0, /**< None */ + MC_PLAYBACK_STATE_PLAYING, /**< Play */ + MC_PLAYBACK_STATE_PAUSED, /**< Pause */ + MC_PLAYBACK_STATE_STOPPED, /**< Stop */ + MC_PLAYBACK_STATE_NEXT_FILE, /**< Next file */ + MC_PLAYBACK_STATE_PREV_FILE, /**< Previous file */ + MC_PLAYBACK_STATE_FAST_FORWARD, /**< Fast forward */ + MC_PLAYBACK_STATE_REWIND, /**< Rewind */ } mc_playback_states_e; /** @@ -120,8 +120,8 @@ typedef enum { * @since_tizen 2.4 */ typedef enum { - SHUFFLE_MODE_ON = 0, /**< Shuffle mode on */ - SHUFFLE_MODE_OFF, /**< Shuffle mode off */ + MC_SHUFFLE_MODE_ON = 0, /**< Shuffle mode on */ + MC_SHUFFLE_MODE_OFF, /**< Shuffle mode off */ } mc_shuffle_mode_e; /** @@ -129,11 +129,23 @@ typedef enum { * @since_tizen 2.4 */ typedef enum { - REPEAT_MODE_ON = 0, /**< Repeat mode on */ - REPEAT_MODE_OFF, /**< Repeat mode off */ + MC_REPEAT_MODE_ON = 0, /**< Repeat mode on */ + MC_REPEAT_MODE_OFF, /**< Repeat mode off */ } mc_repeat_mode_e; /** + * @brief Enumeration for the subscription type. + * @since_tizen 2.4 + */ +typedef enum { + MC_SUBSCRIPTION_TYPE_SERVER_STATE = 0, /**< Server state */ + MC_SUBSCRIPTION_TYPE_PLAYBACK, /**< Playback */ + MC_SUBSCRIPTION_TYPE_METADATA, /**< Metadata */ + MC_SUBSCRIPTION_TYPE_SHUFFLE_MODE, /**< Shuffle mode */ + MC_SUBSCRIPTION_TYPE_REPEAT_MODE, /**< Repeat mode */ +} mc_subscription_type_e; + +/** * @} */ diff --git a/packaging/capi-media-controller.spec b/packaging/capi-media-controller.spec index e2f94de..d71e2ac 100755 --- a/packaging/capi-media-controller.spec +++ b/packaging/capi-media-controller.spec @@ -1,6 +1,6 @@ Name: capi-media-controller Summary: Multimedia Controller for player application -Version: 0.0.8 +Version: 0.0.9 Release: 1 Group: System/Libraries License: Apache-2.0 @@ -13,6 +13,7 @@ BuildRequires: cmake BuildRequires: sqlite BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(dbus-glib-1) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(sqlite3) diff --git a/src/media_controller_client.c b/src/media_controller_client.c index b875441..42ced89 100755 --- a/src/media_controller_client.c +++ b/src/media_controller_client.c @@ -22,7 +22,7 @@ static void __client_server_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data) { gchar **params = NULL; - media_controller_reciever_s *reciever = (media_controller_reciever_s *)user_data; + media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data; mc_server_state_updated_cb callback = (mc_server_state_updated_cb)reciever->callback; mc_retm_if(reciever == NULL, "reciever is NULL"); @@ -42,7 +42,7 @@ static void __client_server_cb(const char *interface_name, const char *signal_na static void __client_playback_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data) { gchar **params = NULL; - media_controller_reciever_s *reciever = (media_controller_reciever_s *)user_data; + media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data; mc_playback_updated_cb callback = (mc_playback_updated_cb)reciever->callback; media_controller_playback_s *playback = NULL; @@ -91,7 +91,7 @@ static void __client_metadata_cb(const char *interface_name, const char *signal_ static void __client_shuffle_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data) { gchar **params = NULL; - media_controller_reciever_s *reciever = (media_controller_reciever_s *)user_data; + media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data; mc_shuffle_mode_changed_cb callback = (mc_shuffle_mode_changed_cb)reciever->callback; mc_retm_if(reciever == NULL, "reciever is NULL"); @@ -110,7 +110,7 @@ static void __client_shuffle_cb(const char *interface_name, const char *signal_n static void __client_repeat_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data) { gchar **params = NULL; - media_controller_reciever_s *reciever = (media_controller_reciever_s *)user_data; + media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data; mc_repeat_mode_changed_cb callback = (mc_repeat_mode_changed_cb)reciever->callback; mc_retm_if(reciever == NULL, "reciever is NULL"); @@ -132,7 +132,7 @@ static void __client_reply_cb(const char *interface_name, const char *signal_nam int enc_size = 0; bundle *bundle_data = NULL; - media_controller_reciever_s *reciever = (media_controller_reciever_s *)user_data; + media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data; mc_retm_if(reciever == NULL, "reciever is NULL"); mc_command_reply_received_cb callback = (mc_command_reply_received_cb)reciever->callback; @@ -234,12 +234,116 @@ static int __mc_client_destroy(media_controller_client_s *mc_client) return ret; } +static int __mc_client_register_filter_listener(media_controller_client_s *mc_client, GList **filter_list, const char *server_name, const char *signal_name, mc_signal_received_cb callback, void *user_data) +{ + int ret = MEDIA_CONTROLLER_ERROR_NONE; + char *filter_interface_name = NULL; + + mc_debug("signal = [%s]", signal_name); + + ret = mc_util_make_filter_interface_name(MC_DBUS_UPDATE_INTERFACE, server_name, &filter_interface_name); + mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Fail mc_util_make_filter_interface_name"); + + ret = mc_ipc_register_listener(mc_client->listeners, mc_client->dconn, filter_interface_name, signal_name, callback, user_data); + if (ret == MEDIA_CONTROLLER_ERROR_NONE) + *filter_list = g_list_append(*filter_list, strdup(filter_interface_name)); + + MC_SAFE_FREE(filter_interface_name); + + return ret; +} + +static int __mc_client_unregister_filter_listener(media_controller_client_s *mc_client, GList **filter_list, const char *server_name, const char *signal_name) +{ + int ret = MEDIA_CONTROLLER_ERROR_NONE; + int idx = 0; + int filter_cnt = 0; + + mc_retvm_if(filter_list == NULL, MEDIA_CONTROLLER_ERROR_NONE, "[No-Error] No filter list to unset"); + mc_retvm_if(!MC_STRING_VALID(signal_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid signal_name"); + + filter_cnt = g_list_length(*filter_list); + + mc_debug("signal [%s] cnt [%d]", signal_name, filter_cnt); + + if (MC_STRING_VALID(server_name)) { + + char *filter_interface_name = NULL; + + ret = mc_util_make_filter_interface_name(MC_DBUS_UPDATE_INTERFACE, server_name, &filter_interface_name); + mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Fail mc_util_make_filter_interface_name"); + if (!MC_STRING_VALID(filter_interface_name)) { + mc_error("filter_interface_name is NULL"); + MC_SAFE_FREE(filter_interface_name); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + /*Unregister listener*/ + ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, filter_interface_name, signal_name); + if (ret != MEDIA_CONTROLLER_ERROR_NONE) { + MC_SAFE_FREE(filter_interface_name); + return ret; + } + + /*Remove from filter_list*/ + for(idx = 0; idx < filter_cnt; idx++) { + char * interface_name = NULL; + interface_name = g_list_nth_data(*filter_list, idx); + + if (MC_STRING_VALID(interface_name)) { + if (strcmp(interface_name, filter_interface_name) == 0) { + mc_debug("Unset subscriber [%d][%s]", idx, interface_name); + *filter_list = g_list_remove(*filter_list, interface_name); + MC_SAFE_FREE(interface_name); + } + } + } + + MC_SAFE_FREE(filter_interface_name); + } else { + + /*Remove All filter listener*/ + for(idx = 0; idx < filter_cnt; idx++) { + char * interface_name = NULL; + interface_name = g_list_nth_data(*filter_list, idx); + + if (MC_STRING_VALID(interface_name)) { + mc_debug("[%d][%s]", idx, interface_name); + + /*Unregister listener*/ + ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, interface_name, signal_name); + if(ret != MEDIA_CONTROLLER_ERROR_NONE) + mc_error("Fail mc_ipc_unregister_listener"); + + /*Remove from filter_list*/ + *filter_list = g_list_remove(*filter_list, interface_name); + MC_SAFE_FREE(interface_name); + } + } + + g_list_free(*filter_list); + } + + return ret; +} + +static int __mc_parse_server_name(const char *interface_name, char **server_name) +{ + mc_retvm_if(interface_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "interface_name is NULL"); + mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "server_name is NULL"); + + *server_name = strdup(interface_name + strlen(MC_DBUS_UPDATE_INTERFACE) + 1); + + return MEDIA_CONTROLLER_ERROR_NONE; +} int mc_client_create(mc_client_h *client) { int ret = MEDIA_CONTROLLER_ERROR_NONE; media_controller_client_s *mc_client = NULL; + mc_debug_fenter(); + mc_retvm_if(client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); /*Try Socket Activation by systemd*/ @@ -255,15 +359,10 @@ int mc_client_create(mc_client_h *client) return ret; } - ret = mc_db_create_tables(mc_client->db_handle); - if (ret != MEDIA_CONTROLLER_ERROR_NONE) { - mc_error("mc_db_create_tables failed %d", ret); - __mc_client_destroy(mc_client); - return ret; - } - *client = (mc_client_h)mc_client; + mc_debug_fleave(); + return MEDIA_CONTROLLER_ERROR_NONE; } @@ -274,6 +373,7 @@ int mc_client_set_server_update_cb(mc_client_h client, mc_server_state_updated_c 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->server_state_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set"); mc_client->server_state_cb.callback = callback; mc_client->server_state_cb.user_data = user_data; @@ -293,8 +393,11 @@ int mc_client_unset_server_update_cb(mc_client_h client) ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SERVER_STATE); + ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->server_state_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_SERVER_STATE); + mc_client->server_state_cb.callback = NULL; mc_client->server_state_cb.user_data = NULL; + mc_client->server_state_cb.filter_list = NULL; return ret; } @@ -306,11 +409,12 @@ int mc_client_set_playback_update_cb(mc_client_h client, mc_playback_updated_cb 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->playback_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set"); mc_client->playback_cb.callback = callback; mc_client->playback_cb.user_data = user_data; - ret = mc_ipc_register_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAY_BACK , + ret = mc_ipc_register_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAY_BACK, __client_playback_cb, (void *)&(mc_client->playback_cb)); return ret; @@ -325,8 +429,11 @@ int mc_client_unset_playback_update_cb(mc_client_h client) ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAY_BACK); + ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->playback_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAY_BACK); + mc_client->playback_cb.callback = NULL; mc_client->playback_cb.user_data = NULL; + mc_client->playback_cb.filter_list = NULL; return ret; } @@ -338,6 +445,7 @@ int mc_client_set_metadata_update_cb(mc_client_h client, mc_metadata_updated_cb 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->metadata_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set"); mc_client->metadata_cb.callback = callback; mc_client->metadata_cb.user_data = user_data; @@ -357,8 +465,11 @@ int mc_client_unset_metadata_update_cb(mc_client_h client) ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_METADATA); + ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->metadata_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_METADATA); + mc_client->metadata_cb.callback = NULL; mc_client->metadata_cb.user_data = NULL; + mc_client->metadata_cb.filter_list = NULL; return ret; } @@ -370,6 +481,7 @@ int mc_client_set_shuffle_mode_update_cb(mc_client_h client, mc_shuffle_mode_cha 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->shuffle_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set"); mc_client->shuffle_cb.callback = callback; mc_client->shuffle_cb.user_data = user_data; @@ -389,8 +501,12 @@ int mc_client_unset_shuffle_mode_update_cb(mc_client_h client) ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE); + ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->shuffle_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE); + mc_client->shuffle_cb.callback = NULL; mc_client->shuffle_cb.user_data = NULL; + mc_client->shuffle_cb.filter_list = NULL; + return ret; } @@ -402,6 +518,7 @@ int mc_client_set_repeat_mode_update_cb(mc_client_h client, mc_repeat_mode_chang 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->repeat_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set"); mc_client->repeat_cb.callback = callback; mc_client->repeat_cb.user_data = user_data; @@ -421,8 +538,169 @@ int mc_client_unset_repeat_mode_update_cb(mc_client_h client) ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT); + ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->repeat_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT); + mc_client->repeat_cb.callback = NULL; mc_client->repeat_cb.user_data = NULL; + mc_client->repeat_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; + media_controller_client_s *mc_client = (media_controller_client_s *)client; + + mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); + mc_retvm_if(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name"); + + switch(subscription_type) { + case MC_SUBSCRIPTION_TYPE_SERVER_STATE: + mc_retvm_if(mc_client->server_state_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_SERVER_STATE); + ret = __mc_client_register_filter_listener(mc_client, &mc_client->server_state_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_SERVER_STATE, + __client_server_cb, (void *)&(mc_client->server_state_cb)); + break; + case MC_SUBSCRIPTION_TYPE_PLAYBACK: + mc_retvm_if(mc_client->playback_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_PLAY_BACK); + ret = __mc_client_register_filter_listener(mc_client, &mc_client->playback_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAY_BACK, + __client_playback_cb, (void *)&(mc_client->playback_cb)); + break; + case MC_SUBSCRIPTION_TYPE_METADATA: + mc_retvm_if(mc_client->metadata_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_METADATA); + ret = __mc_client_register_filter_listener(mc_client, &mc_client->metadata_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_METADATA, + __client_metadata_cb, (void *)(mc_client)); + break; + case MC_SUBSCRIPTION_TYPE_SHUFFLE_MODE: + mc_retvm_if(mc_client->shuffle_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_PLAYBACK_SHUFFLE); + ret = __mc_client_register_filter_listener(mc_client, &mc_client->shuffle_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE, + __client_shuffle_cb, (void *)&(mc_client->shuffle_cb)); + break; + case MC_SUBSCRIPTION_TYPE_REPEAT_MODE: + mc_retvm_if(mc_client->repeat_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_PLAYBACK_REPEAT); + 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; + default: + mc_error("Invalid subscription_type [%d]", subscription_type); + return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER; + } + + return ret; +} + +int mc_client_unsubscribe(mc_client_h client, const mc_subscription_type_e subscription_type, const char *server_name) +{ + 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(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name"); + + switch(subscription_type) { + case MC_SUBSCRIPTION_TYPE_SERVER_STATE: + mc_retvm_if(mc_client->server_state_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe"); + mc_retvm_if(mc_client->server_state_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->server_state_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_SERVER_STATE); + break; + case MC_SUBSCRIPTION_TYPE_PLAYBACK: + mc_retvm_if(mc_client->playback_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe"); + mc_retvm_if(mc_client->playback_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->playback_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAY_BACK); + break; + case MC_SUBSCRIPTION_TYPE_METADATA: + mc_retvm_if(mc_client->metadata_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe"); + mc_retvm_if(mc_client->metadata_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->metadata_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_METADATA); + break; + case MC_SUBSCRIPTION_TYPE_SHUFFLE_MODE: + mc_retvm_if(mc_client->shuffle_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe"); + mc_retvm_if(mc_client->shuffle_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->shuffle_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE); + break; + case MC_SUBSCRIPTION_TYPE_REPEAT_MODE: + mc_retvm_if(mc_client->repeat_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe"); + mc_retvm_if(mc_client->repeat_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->repeat_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT); + break; + default: + mc_error("Invalid subscription_type [%d]", subscription_type); + return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER; + } + + return ret; +} + +int mc_client_foreach_server_subscribed(mc_client_h client, const mc_subscription_type_e subscription_type, mc_subscribed_server_cb callback, void *user_data) +{ + int ret = MEDIA_CONTROLLER_ERROR_NONE; + media_controller_client_s *mc_client = (media_controller_client_s *)client; + int idx = 0; + char *server_name = NULL; + GList *filter_list = NULL; + char *filter_data = NULL; + int filter_cnt = 0; + + 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"); + + switch(subscription_type) { + case MC_SUBSCRIPTION_TYPE_SERVER_STATE: + filter_list = mc_client->server_state_cb.filter_list; + break; + case MC_SUBSCRIPTION_TYPE_PLAYBACK: + filter_list = mc_client->playback_cb.filter_list; + break; + case MC_SUBSCRIPTION_TYPE_METADATA: + filter_list = mc_client->metadata_cb.filter_list; + break; + case MC_SUBSCRIPTION_TYPE_SHUFFLE_MODE: + filter_list = mc_client->shuffle_cb.filter_list; + break; + case MC_SUBSCRIPTION_TYPE_REPEAT_MODE: + filter_list = mc_client->repeat_cb.filter_list; + break; + default: + mc_error("Invalid subscription_type [%d]", subscription_type); + return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER; + } + + if (filter_list == NULL) { + mc_debug("No filter list for the subscription_type [%d]", subscription_type); + return MEDIA_CONTROLLER_ERROR_NONE; + } + + filter_cnt = g_list_length(filter_list); + + for(idx = 0; idx < filter_cnt; idx++) { + filter_data = (char*)g_list_nth_data(filter_list, idx); + ret = __mc_parse_server_name(filter_data, &server_name); + mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail __mc_parse_server_name"); + + if (MC_STRING_VALID(server_name)) { + if (callback(server_name, user_data) == false) { + MC_SAFE_FREE(server_name); + break; + } + } + + MC_SAFE_FREE(server_name); + } return ret; } @@ -464,47 +742,47 @@ int mc_client_get_metadata(mc_metadata_h metadata, mc_meta_e attribute, char **v mc_debug("attribute[%d]", attribute); switch (attribute) { - case MEDIA_TITLE: + case MC_META_MEDIA_TITLE: if (mc_metadata->title != NULL) meta_val = strdup(mc_metadata->title); break; - case MEDIA_ARTIST: + case MC_META_MEDIA_ARTIST: if (mc_metadata->artist != NULL) meta_val = strdup(mc_metadata->artist); break; - case MEDIA_ALBUM: + case MC_META_MEDIA_ALBUM: if (mc_metadata->album != NULL) meta_val = strdup(mc_metadata->album); break; - case MEDIA_AUTHOR: + case MC_META_MEDIA_AUTHOR: if (mc_metadata->author != NULL) meta_val = strdup(mc_metadata->author); break; - case MEDIA_GENRE: + case MC_META_MEDIA_GENRE: if (mc_metadata->genre != NULL) meta_val = strdup(mc_metadata->genre); break; - case MEDIA_DURATION: + case MC_META_MEDIA_DURATION: if (mc_metadata->duration != NULL) meta_val = strdup(mc_metadata->duration); break; - case MEDIA_DATE: + case MC_META_MEDIA_DATE: if (mc_metadata->date != NULL) meta_val = strdup(mc_metadata->date); break; - case MEDIA_COPYRIGHT: + case MC_META_MEDIA_COPYRIGHT: if (mc_metadata->copyright != NULL) meta_val = strdup(mc_metadata->copyright); break; - case MEDIA_DESCRIPTION: + case MC_META_MEDIA_DESCRIPTION: if (mc_metadata->description != NULL) meta_val = strdup(mc_metadata->description); break; - case MEDIA_TRACK_NUM: + case MC_META_MEDIA_TRACK_NUM: if (mc_metadata->track_num != NULL) meta_val = strdup(mc_metadata->track_num); break; - case MEDIA_PICTURE: + case MC_META_MEDIA_PICTURE: if (mc_metadata->picture != NULL) meta_val = strdup(mc_metadata->picture); break; @@ -664,7 +942,7 @@ int mc_client_send_playback_state_command(mc_client_h client, const char *server 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(((state < MEDIA_PLAYBACK_STATE_PLAYING) || (state > MEDIA_PLAYBACK_STATE_REWIND)), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "state is invalid"); + mc_retvm_if(((state < MC_PLAYBACK_STATE_PLAYING) || (state > MC_PLAYBACK_STATE_REWIND)), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "state is invalid"); message = g_strdup_printf("%s%s%d", mc_client->client_name, MC_STRING_DELIMITER, state); mc_retvm_if(message == NULL, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "fail making message [%d]", ret); @@ -744,8 +1022,18 @@ int mc_client_destroy(mc_client_h client) int ret = MEDIA_CONTROLLER_ERROR_NONE; media_controller_client_s *mc_client = (media_controller_client_s *)client; + mc_debug_fenter(); + mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); + /*Unregister all filter listener*/ + ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->server_state_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_SERVER_STATE); + ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->playback_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAY_BACK); + 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); + + /*Unregister all listener*/ ret = mc_ipc_unregister_all_listener(mc_client->listeners, mc_client->dconn); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { mc_error("Error mc_ipc_unregister_all_listener [%d]", ret); @@ -759,5 +1047,7 @@ int mc_client_destroy(mc_client_h client) ret = __mc_client_destroy(mc_client); + mc_debug_fleave(); + return ret; } diff --git a/src/media_controller_db.c b/src/media_controller_db.c index 97f7133..64d7252 100755 --- a/src/media_controller_db.c +++ b/src/media_controller_db.c @@ -46,12 +46,9 @@ typedef enum { MC_SERVER_FIELD_REPEAT_MODE, } server_table_field_e; -#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 */ - static int __mc_db_busy_handler(void *pData, int count) { - usleep(50000); + MC_MILLISEC_SLEEP(50); mc_debug("mc_db_busy_handler called : %d", count); @@ -72,35 +69,6 @@ static int __mc_db_update_db(void *handle, const char *sql_str) return ret; } -static int __mc_db_create_latest_server_table(sqlite3 *handle) -{ - int ret = MEDIA_CONTROLLER_ERROR_NONE; - char *sql_str = NULL; - - sql_str = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %q (server_name TEXT PRIMARY KEY);", MC_DB_TABLE_LATEST_SERVER); - - ret = __mc_db_update_db(handle, sql_str); - - SQLITE3_SAFE_FREE(sql_str); - - return ret; -} - -static int __mc_db_create_server_list_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);", - MC_DB_TABLE_SERVER_LIST); - - ret = __mc_db_update_db(handle, sql_str); - - SQLITE3_SAFE_FREE(sql_str); - return ret; -} - static int __mc_db_get_int_value_of_key(void *handle, const char *server_name, const char *key, int *value) { int ret = MEDIA_CONTROLLER_ERROR_NONE; @@ -182,7 +150,7 @@ int mc_db_connect(void **handle, bool need_write) int ret = MEDIA_CONTROLLER_ERROR_NONE; sqlite3 *db_handle = NULL; - mc_error("mc_db_connect"); + mc_debug("mc_db_connect"); mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); @@ -337,7 +305,7 @@ int mc_db_get_latest_server_name(void *handle, char **latest_server_name) int mc_db_get_playback_info(void *handle, const char *server_name, mc_playback_h *playback) { int ret = MEDIA_CONTROLLER_ERROR_NONE; - mc_playback_states_e playback_state = MEDIA_PLAYBACK_STATE_PLAYING; + mc_playback_states_e playback_state = MC_PLAYBACK_STATE_PLAYING; unsigned long long position = 0; media_controller_playback_s *_playback = NULL; @@ -509,22 +477,6 @@ int mc_db_disconnect(void *handle) return MEDIA_CONTROLLER_ERROR_NONE; } -int mc_db_create_tables(void *handle) -{ - int ret = MEDIA_CONTROLLER_ERROR_NONE; - sqlite3 *db_handle = (sqlite3 *)handle; - - mc_retvm_if(db_handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); - - ret = __mc_db_create_latest_server_table(db_handle); - mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "create latest_server table failed!err= [%d]", ret); - - ret = __mc_db_create_server_list_table(db_handle); - mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "create server_list table failed!err= [%d]", ret); - - return MEDIA_CONTROLLER_ERROR_NONE; -} - int mc_db_create_server_table(void *handle, const char *server_name) { int ret = MEDIA_CONTROLLER_ERROR_NONE; diff --git a/src/media_controller_ipc.c b/src/media_controller_ipc.c index d21eba8..2615bb3 100755 --- a/src/media_controller_ipc.c +++ b/src/media_controller_ipc.c @@ -183,7 +183,9 @@ int mc_ipc_register_listener(GList *listener_list, GDBusConnection *connection, MC_SAFE_FREE(key); return MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY; } + handler = _mc_ipc_signal_subscribe(connection, interface_name, signal_name, listener_list); + listener->dbus_conn = connection; listener->interface_name = g_strdup(interface_name); listener->signal_name = g_strdup(signal_name); @@ -260,10 +262,10 @@ int mc_ipc_send_message(GDBusConnection *connection, const char *dbus_name, cons GError *error = NULL; mc_retvm_if(connection == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "connection is NULL"); - mc_retvm_if(signal_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "signal_name is NULL"); - mc_retvm_if(message == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "message is NULL"); + mc_retvm_if(!MC_STRING_VALID(signal_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid signal_name"); + mc_retvm_if(!MC_STRING_VALID(message), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid message"); - mc_debug("emit signal - interface: %s, signal: %s", interface_name, signal_name); + mc_debug("emit signal - interface_name [%s], signal_name [%s]", interface_name, signal_name); gboolean emmiting = g_dbus_connection_emit_signal( connection, @@ -409,7 +411,7 @@ int mc_ipc_service_connect(void) mc_ipc_delete_client_socket(&sock_info); while((__is_service_activated() == FALSE) && (retrycount++ < MAX_WAIT_COUNT)) { - usleep(200000); + MC_MILLISEC_SLEEP(200); mc_error("[No-Error] retry count [%d]", retrycount); } diff --git a/src/media_controller_server.c b/src/media_controller_server.c index baefc59..7262137 100755 --- a/src/media_controller_server.c +++ b/src/media_controller_server.c @@ -127,7 +127,7 @@ static int __mc_server_destoy(media_controller_server_s *mc_server) static void __server_playback_state_command_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data) { gchar **params = NULL; - media_controller_reciever_s *receiver = (media_controller_reciever_s *)user_data; + media_controller_receiver_s *receiver = (media_controller_receiver_s *)user_data; mc_retm_if(receiver == NULL, "reciever is NULL"); mc_retm_if(message == NULL, "message is NULL"); @@ -157,7 +157,7 @@ static void __server_custom_command_cb(const char *interface_name, const char *s char *command = NULL; bundle *bundle_data = NULL; - media_controller_reciever_s *receiver = (media_controller_reciever_s *)user_data; + media_controller_receiver_s *receiver = (media_controller_receiver_s *)user_data; mc_retm_if(receiver == NULL, "reciever is NULL"); mc_server_custom_command_received_cb callback = receiver->callback; @@ -175,7 +175,7 @@ static void __server_custom_command_cb(const char *interface_name, const char *s mc_error("Error permission denied"); MC_SAFE_FREE(sender); g_strfreev(params); - return ; + return; } command = strdup(params[1]); @@ -239,6 +239,19 @@ static int __mc_server_send_message(media_controller_server_s *mc_server, const mc_debug("interface_name[%s] signal_name[%s] message[%s]", interface_name, signal_name, message); + /*Send again for the subscriber which receive filtered msg with server_name*/ + char *filter_interface_name = NULL; + ret = mc_util_make_filter_interface_name(interface_name, mc_server->server_name, &filter_interface_name); + if (ret != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("Error mc_util_make_interface_name [%d]", ret); + } else { + ret = mc_ipc_send_message(mc_server->dconn, NULL, filter_interface_name, signal_name, message, 0); + if (ret != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("Error mc_ipc_send_message [%d]", ret); + } + } + + MC_SAFE_FREE(filter_interface_name); MC_SAFE_FREE(message); return ret; @@ -249,7 +262,7 @@ int mc_server_set_playback_state(mc_server_h server, mc_playback_states_e state) media_controller_server_s *mc_server = (media_controller_server_s *)server; mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); - mc_retvm_if(((state < MEDIA_PLAYBACK_STATE_PLAYING) || (state > MEDIA_PLAYBACK_STATE_REWIND)), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "state is invalid"); + mc_retvm_if(((state < MC_PLAYBACK_STATE_PLAYING) || (state > MC_PLAYBACK_STATE_REWIND)), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "state is invalid"); mc_debug("playback state update [%d]", state); @@ -291,7 +304,7 @@ int mc_server_update_playback_info(mc_server_h server) mc_error("Error __mc_server_send_message [%d]", ret); } - if (mc_server->playback.state == MEDIA_PLAYBACK_STATE_PLAYING) { + if (mc_server->playback.state == MC_PLAYBACK_STATE_PLAYING) { ret = mc_db_update_latest_server_table(mc_server->db_handle, mc_server->server_name); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { mc_error("fail mc_db_update_playback_info [%d]", ret); @@ -309,7 +322,7 @@ int mc_server_update_shuffle_mode(mc_server_h server, mc_shuffle_mode_e mode) mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); - if ((mode != SHUFFLE_MODE_ON) && (mode != SHUFFLE_MODE_OFF)) { + if ((mode != MC_SHUFFLE_MODE_ON) && (mode != MC_SHUFFLE_MODE_OFF)) { mc_error("Invalid shuffle mode [%d]", mode); return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER; } @@ -332,7 +345,7 @@ int mc_server_update_repeat_mode(mc_server_h server, mc_repeat_mode_e mode) mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); - if ((mode != REPEAT_MODE_ON) && (mode != REPEAT_MODE_OFF)) { + if ((mode != MC_REPEAT_MODE_ON) && (mode != MC_REPEAT_MODE_OFF)) { mc_error("Invalid repeat mode [%d]", mode); return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER; } @@ -357,57 +370,57 @@ int mc_server_set_metadata(mc_server_h server, mc_meta_e attribute, const char * mc_debug("meta data set attribute [%d] value [%s]", attribute, value); switch (attribute) { - case MEDIA_TITLE: + case MC_META_MEDIA_TITLE: MC_SAFE_FREE(mc_server->metadata->title); if (value != NULL) mc_server->metadata->title = strdup(value); break; - case MEDIA_ARTIST: + case MC_META_MEDIA_ARTIST: MC_SAFE_FREE(mc_server->metadata->artist); if (value != NULL) mc_server->metadata->artist = strdup(value); break; - case MEDIA_ALBUM: + case MC_META_MEDIA_ALBUM: MC_SAFE_FREE(mc_server->metadata->album); if (value != NULL) mc_server->metadata->album = strdup(value); break; - case MEDIA_AUTHOR: + case MC_META_MEDIA_AUTHOR: MC_SAFE_FREE(mc_server->metadata->author); if (value != NULL) mc_server->metadata->author = strdup(value); break; - case MEDIA_GENRE: + case MC_META_MEDIA_GENRE: MC_SAFE_FREE(mc_server->metadata->genre); if (value != NULL) mc_server->metadata->genre = strdup(value); break; - case MEDIA_DURATION: + case MC_META_MEDIA_DURATION: MC_SAFE_FREE(mc_server->metadata->duration); if (value != NULL) mc_server->metadata->duration = strdup(value); break; - case MEDIA_DATE: + case MC_META_MEDIA_DATE: MC_SAFE_FREE(mc_server->metadata->date); if (value != NULL) mc_server->metadata->date = strdup(value); break; - case MEDIA_COPYRIGHT: + case MC_META_MEDIA_COPYRIGHT: MC_SAFE_FREE(mc_server->metadata->copyright); if (value != NULL) mc_server->metadata->copyright = strdup(value); break; - case MEDIA_DESCRIPTION: + case MC_META_MEDIA_DESCRIPTION: MC_SAFE_FREE(mc_server->metadata->description); if (value != NULL) mc_server->metadata->description = strdup(value); break; - case MEDIA_TRACK_NUM: + case MC_META_MEDIA_TRACK_NUM: MC_SAFE_FREE(mc_server->metadata->track_num); if (value != NULL) mc_server->metadata->track_num = strdup(value); break; - case MEDIA_PICTURE: + case MC_META_MEDIA_PICTURE: MC_SAFE_FREE(mc_server->metadata->picture); if (value != NULL) mc_server->metadata->picture = strdup(value); @@ -525,7 +538,7 @@ int mc_server_send_command_reply(mc_server_h server, const char *client_name, in media_controller_server_s *mc_server = (media_controller_server_s *)server; mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); - mc_retvm_if(client_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "client_name is NULL"); + mc_retvm_if(!MC_STRING_VALID(client_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "client_name is NULL"); if (data) { ret = bundle_encode(data, &raw_data, &size_r); @@ -572,11 +585,6 @@ int mc_server_create(mc_server_h *server) return ret; } - ret = mc_db_create_tables(mc_server->db_handle); - if (ret != MEDIA_CONTROLLER_ERROR_NONE) { - mc_error("mc_db_create_tables failed [%d]", ret); - } - ret = mc_db_check_server_table_exist(mc_server->db_handle, mc_server->server_name, &table_exist); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { mc_error("mc_db_check_server_table_exist failed [%d]", ret); @@ -591,10 +599,9 @@ int mc_server_create(mc_server_h *server) __mc_server_destoy(mc_server); return ret; } - ret = mc_db_delete_server_address_from_table(mc_server->db_handle, MC_DB_TABLE_SERVER_LIST, mc_server->server_name); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { - mc_error("mc_db_delete_server_table failed [%d]", ret); + mc_error("mc_db_delete_server_address_from_table failed [%d]", ret); __mc_server_destoy(mc_server); return ret; } diff --git a/src/media_controller_util.c b/src/media_controller_util.c index 9d84274..f55f7bd 100755 --- a/src/media_controller_util.c +++ b/src/media_controller_util.c @@ -49,6 +49,7 @@ static void _mc_util_check_valid_name(const char *name, char **new_name) } (*new_name) = strdup(new_word); + mc_retm_if((*new_name) == NULL, "Error allocation memory."); } @@ -62,10 +63,13 @@ int mc_util_get_own_name(char **name) pid = getpid(); if (pid == -1) { mc_error("Error failed to get pid!"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; } if (AUL_R_OK != aul_app_get_appid_bypid(pid, temp, sizeof(temp))) { mc_error("Error failed to get appid!"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; } + _mc_util_check_valid_name(temp, name); return MEDIA_CONTROLLER_ERROR_NONE; @@ -86,6 +90,27 @@ char *mc_util_get_interface_name(const char *type, const char *name) return interface_name; } +int mc_util_make_filter_interface_name(const char *prefix, const char *filter, char **interface_name) +{ + char *temp = NULL; + + mc_retvm_if(prefix == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "prefix is NULL"); + mc_retvm_if(filter == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "filter is NULL"); + + temp = g_strdup_printf("%s.%s", prefix, filter); + + if (temp == NULL) { + mc_error("Fail to make interface_name"); + return MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY; + } + + _mc_util_check_valid_name(temp, interface_name); + + MC_SAFE_FREE(temp); + + return MEDIA_CONTROLLER_ERROR_NONE; +} + int mc_util_set_command_availabe(const char *name, const char *command_type, const char *command) { int ret = MEDIA_CONTROLLER_ERROR_NONE; diff --git a/svc/CMakeLists.txt b/svc/CMakeLists.txt index e967ced..1a8004e 100755 --- a/svc/CMakeLists.txt +++ b/svc/CMakeLists.txt @@ -1,5 +1,5 @@ # for package file -SET(dependents "capi-base-common glib-2.0 gio-2.0 dlog sqlite3 db-util libsystemd-daemon libtzplatform-config cynara-client cynara-session cynara-creds-socket") +SET(dependents "capi-base-common glib-2.0 gio-2.0 dlog dbus-glib-1 sqlite3 db-util libsystemd-daemon libtzplatform-config cynara-client cynara-session cynara-creds-socket") SET(fw_svc "media-controller-svc") PROJECT(${fw_svc}) diff --git a/svc/media_controller_db_util.c b/svc/media_controller_db_util.c index 5e24256..7601656 100755 --- a/svc/media_controller_db_util.c +++ b/svc/media_controller_db_util.c @@ -24,18 +24,107 @@ #include "media_controller_private.h" #include "media_controller_db_util.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 */ +#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 */ static int __mc_db_util_busy_handler(void *pData, int count) { - usleep(50000); + MC_MILLISEC_SLEEP(50); mc_debug("mc_db_busy_handler called : %d", count); return 100 - count; } +static int __mc_foreach_table_list(void *handle, GList **list) +{ + int ret = MEDIA_CONTROLLER_ERROR_NONE; + sqlite3 *db_handle = (sqlite3 *)handle; + char *sql_str = NULL; + sqlite3_stmt *stmt = NULL; + + mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); + + sql_str = sqlite3_mprintf(DB_SELECT_ALL_SERVER_LIST_EXCEPT_LATEST, MC_DB_TABLE_LATEST_SERVER); + + ret = sqlite3_prepare_v2(db_handle, sql_str, strlen(sql_str), &stmt, NULL); + if (SQLITE_OK != ret) { + mc_error("prepare error [%s]\n", sqlite3_errmsg(db_handle)); + SQLITE3_SAFE_FREE(sql_str); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + ret = sqlite3_step(stmt); + while (SQLITE_ROW == ret) { + char *table_name = NULL; + + if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, 0))) { + table_name = strdup((const char *)sqlite3_column_text(stmt, 0)); + mc_debug("table_name: %s", table_name); + + if (MC_STRING_VALID(table_name)) { + (*list) = g_list_append((*list), table_name); + } + } + + ret = sqlite3_step(stmt); + } + + SQLITE3_FINALIZE(stmt); + SQLITE3_SAFE_FREE(sql_str); + + return MEDIA_CONTROLLER_ERROR_NONE; +} + +static int __mc_db_util_delete_server_table(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("DROP TABLE IF EXISTS '%q'", server_name); + + ret = mc_db_util_update_db(handle, sql_str); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + mc_error("Error mc_db_util_update_db %d", ret); + } + + SQLITE3_SAFE_FREE(sql_str); + + return ret; +} + +static int __mc_create_latest_server_table(sqlite3 *handle) +{ + int ret = MEDIA_CONTROLLER_ERROR_NONE; + char *sql_str = NULL; + + sql_str = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %q (server_name TEXT PRIMARY KEY);", MC_DB_TABLE_LATEST_SERVER); + + ret = mc_db_util_update_db(handle, sql_str); + + SQLITE3_SAFE_FREE(sql_str); + + return ret; +} + +static int __mc_create_server_list_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);", + MC_DB_TABLE_SERVER_LIST); + + ret = mc_db_util_update_db(handle, sql_str); + + SQLITE3_SAFE_FREE(sql_str); + return ret; +} + static char* __mc_get_db_name(uid_t uid) { char result_psswd[MC_FILE_PATH_LEN_MAX]; @@ -133,11 +222,47 @@ int mc_db_util_connect(void **handle, uid_t uid, bool need_write) return MEDIA_CONTROLLER_ERROR_NONE; } +int mc_db_util_disconnect(void *handle) +{ + int ret = MEDIA_CONTROLLER_ERROR_NONE; + sqlite3 *db_handle = (sqlite3 *)handle; + + mc_retvm_if(db_handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); + + ret = db_util_close(db_handle); + if (SQLITE_OK != ret) { + mc_error("error when db close"); + mc_error("Error : %s", sqlite3_errmsg(db_handle)); + db_handle = NULL; + + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + return MEDIA_CONTROLLER_ERROR_NONE; +} + +int mc_db_util_create_tables(void *handle) +{ + int ret = MEDIA_CONTROLLER_ERROR_NONE; + sqlite3 *db_handle = (sqlite3 *)handle; + + mc_retvm_if(db_handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); + + ret = __mc_create_latest_server_table(db_handle); + mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "create latest_server table failed!err= [%d]", ret); + + 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); + + return MEDIA_CONTROLLER_ERROR_NONE; +} + int mc_db_util_update_db(void *handle, const char *sql_str) { int ret = MEDIA_CONTROLLER_ERROR_NONE; char *err_msg = NULL; sqlite3 *db_handle = (sqlite3 *)handle; + 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"); @@ -153,21 +278,32 @@ int mc_db_util_update_db(void *handle, const char *sql_str) return MEDIA_CONTROLLER_ERROR_NONE; } -int mc_db_util_disconnect(void *handle) +int mc_db_util_delete_whole_server_tables(void *handle) { int ret = MEDIA_CONTROLLER_ERROR_NONE; - sqlite3 *db_handle = (sqlite3 *)handle; + GList *table_list = NULL; + unsigned int idx = 0; - mc_retvm_if(db_handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); + mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL"); - ret = db_util_close(db_handle); - if (SQLITE_OK != ret) { - mc_error("error when db close"); - mc_error("Error : %s", sqlite3_errmsg(db_handle)); - db_handle = NULL; + ret = __mc_foreach_table_list(handle, &table_list); + if ( ret != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("Error __mc_foreach_table_list %d", ret); + return ret; + } - return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + if (table_list == NULL) { + mc_debug("No server list to delete"); + return ret; } - return MEDIA_CONTROLLER_ERROR_NONE; + for (idx = 0; idx < g_list_length(table_list); idx++) { + char *table_name = g_list_nth_data(table_list, idx); + __mc_db_util_delete_server_table(handle, table_name); + MC_SAFE_FREE(table_name); + } + + g_list_free(table_list); + + return ret; } diff --git a/svc/media_controller_db_util.h b/svc/media_controller_db_util.h index 7a6cad2..47918a5 100755 --- a/svc/media_controller_db_util.h +++ b/svc/media_controller_db_util.h @@ -23,11 +23,18 @@ #define MC_DB_NAME ".media_controller.db" +#define MC_DB_TABLE_SERVER_LIST "server_list" +#define MC_DB_TABLE_LATEST_SERVER "latest_server" + +#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 SQLITE3_SAFE_FREE(sql_string) {if(sql_string) { sqlite3_free(sql_string); sql_string = NULL;}} #define SQLITE3_FINALIZE(x) {if(x != NULL) {sqlite3_finalize(x);}} int mc_db_util_connect(void **handle, uid_t uid, bool need_write); -int mc_db_util_update_db(void *handle, const char *sql_str); int mc_db_util_disconnect(void *handle); +int mc_db_util_create_tables(void *handle); +int mc_db_util_update_db(void *handle, const char *sql_str); +int mc_db_util_delete_whole_server_tables(void *handle); #endif /*__TIZEN_MEDIA_CONTROLLER_DB_UTIL_H__*/ diff --git a/svc/media_controller_socket.c b/svc/media_controller_socket.c index 742d5c5..302a13d 100755 --- a/svc/media_controller_socket.c +++ b/svc/media_controller_socket.c @@ -97,7 +97,7 @@ int mc_ipc_create_server_socket(mc_msg_port_type_e port, int *sock_fd) break; } mc_debug("%d", i); - usleep(250000); + MC_MILLISEC_SLEEP(250); } if (bind_success == false) { diff --git a/svc/media_controller_svc.c b/svc/media_controller_svc.c index 0c7dcef..eeb2a40 100755 --- a/svc/media_controller_svc.c +++ b/svc/media_controller_svc.c @@ -14,7 +14,11 @@ * limitations under the License. */ +#include <dbus/dbus-glib.h> +#include <dbus/dbus.h> +#include <dbus/dbus-glib-lowlevel.h> #include <string.h> +#include <sys/stat.h> #include <systemd/sd-daemon.h> #include "media_controller_svc.h" @@ -26,6 +30,82 @@ static GMainLoop *g_mc_svc_mainloop = NULL; static int g_connection_cnt = -1; +////////////////////////////////////////////////////////////////////////////// +/// GET ACTIVATE USER ID +////////////////////////////////////////////////////////////////////////////// +#define UID_DBUS_NAME "org.freedesktop.login1" +#define UID_DBUS_PATH "/org/freedesktop/login1" +#define UID_DBUS_INTERFACE UID_DBUS_NAME".Manager" +#define UID_DBUS_METHOD "ListUsers" + +static int __mc_dbus_get_uid(const char *dest, const char *path, const char *interface, const char *method, uid_t *uid) +{ + DBusConnection *conn = NULL; + DBusMessage *msg = NULL; + DBusMessage *reply = NULL; + DBusError err; + DBusMessageIter iiiter; + DBusMessageIter iter; + DBusMessageIter aiter, piter; + int result = 0; + + int val_int = 0; + char *val_str = NULL; + + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + if (!conn) { + mc_error("dbus_bus_get error"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + msg = dbus_message_new_method_call(dest, path, interface, method); + if (!msg) { + mc_error("dbus_message_new_method_call(%s:%s-%s)", + path, interface, method); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + dbus_message_iter_init_append(msg, &iiiter); + + dbus_error_init(&err); + + reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); + dbus_message_unref(msg); + if (!reply) { + mc_error("dbus_connection_send error(%s:%s) %s %s:%s-%s", + err.name, err.message, dest, path, interface, method); + dbus_error_free(&err); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + dbus_message_iter_init(reply, &iter); + dbus_message_iter_recurse(&iter, &aiter); + + result = 0; + while (dbus_message_iter_get_arg_type(&aiter) != DBUS_TYPE_INVALID) { + result++; + mc_debug("(%d)th block device information", result); + + dbus_message_iter_recurse(&aiter, &piter); + dbus_message_iter_get_basic(&piter, &val_int); + mc_debug("\tType(%d)", val_int); + + dbus_message_iter_next(&piter); + dbus_message_iter_get_basic(&piter, &val_str); + mc_debug("\tdevnode(%s)", val_str); + + dbus_message_iter_next(&piter); + dbus_message_iter_get_basic(&piter, &val_str); + mc_debug("\tsyspath(%s)", val_str); + + dbus_message_iter_next(&aiter); + } + + *uid = (uid_t) val_int; + + return result; +} + static int __create_socket_activation(void) { int fd = -1; @@ -52,7 +132,7 @@ gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condi mc_comm_msg_s recv_msg; int ret = MEDIA_CONTROLLER_ERROR_NONE; int send_msg = MEDIA_CONTROLLER_ERROR_NONE; - unsigned int i = 0; + int i = 0; mc_svc_data_t *mc_svc_data = (mc_svc_data_t*)data; mc_peer_creds creds = {0, }; @@ -80,11 +160,6 @@ gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condi } if (recv_msg.msg_type == MC_MSG_DB_UPDATE) { - /* Connect media controller DB*/ - if(mc_db_util_connect(&(mc_svc_data->db_handle), recv_msg.uid, true) != MEDIA_CONTROLLER_ERROR_NONE) { - mc_error("Failed to connect DB"); - goto ERROR; - } sql_query = strndup(recv_msg.msg, recv_msg.msg_size); if (sql_query != NULL) { ret = mc_db_util_update_db(mc_svc_data->db_handle, sql_query); @@ -96,10 +171,6 @@ gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condi } else { send_msg = MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY; } - /* Disconnect DB*/ - if(mc_db_util_disconnect(mc_svc_data->db_handle) != MEDIA_CONTROLLER_ERROR_NONE) { - mc_error("Failed to disconnect DB"); - } } else if (recv_msg.msg_type == MC_MSG_CLIENT_SET) { /* check privileage */ ret = mc_cynara_check(&creds, MC_CLIENT_PRIVILEGE); @@ -117,11 +188,11 @@ gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condi set_data->data = strdup(recv_msg.msg); mc_svc_data->mc_svc_list = g_list_append(mc_svc_data->mc_svc_list, set_data); } else if (recv_msg.msg_type == MC_MSG_CLIENT_GET) { + send_msg = MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED; /* check privileage */ ret = mc_cynara_check(&creds, MC_SERVER_PRIVILEGE); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { mc_error("permission is denied![%d]", ret); - send_msg = MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED; goto ERROR; } @@ -129,14 +200,14 @@ gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condi MC_SAFE_FREE(creds.smack); mc_svc_list_t *set_data = NULL; - for (i = 0; i < g_list_length(mc_svc_data->mc_svc_list); i++) { - send_msg = MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED; + for (i = 0; i < (int)g_list_length(mc_svc_data->mc_svc_list); i++) { set_data = (mc_svc_list_t *)g_list_nth_data(mc_svc_data->mc_svc_list, i); if (set_data != NULL && set_data->data != NULL && strcmp(set_data->data, recv_msg.msg) == 0) { mc_svc_data->mc_svc_list = g_list_remove(mc_svc_data->mc_svc_list, set_data); MC_SAFE_FREE(set_data->data); MC_SAFE_FREE(set_data); send_msg = MEDIA_CONTROLLER_ERROR_NONE; + break; } } } else if (recv_msg.msg_type == MC_MSG_SERVER_CONNECTION) { @@ -166,7 +237,7 @@ gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condi // remove resource for disconnected process mc_svc_list_t *set_data = NULL; - for (i = 0; i < g_list_length(mc_svc_data->mc_svc_list); i++) { + for (i = (int)(g_list_length(mc_svc_data->mc_svc_list)) - 1; i >= 0; i--) { set_data = (mc_svc_list_t *)g_list_nth_data(mc_svc_data->mc_svc_list, i); if ((set_data != NULL) && (set_data->pid == recv_msg.pid)) { mc_svc_data->mc_svc_list = g_list_remove(mc_svc_data->mc_svc_list, set_data); @@ -218,6 +289,7 @@ gboolean mc_svc_thread(void *data) GIOChannel *channel = NULL; GMainContext *context = NULL; mc_svc_data_t *mc_svc_data = NULL; + uid_t uid = -1; mc_svc_data = (mc_svc_data_t *)g_malloc(sizeof(mc_svc_data_t)); if (mc_svc_data == NULL) { @@ -234,6 +306,31 @@ gboolean mc_svc_thread(void *data) return FALSE; } + ret = __mc_dbus_get_uid(UID_DBUS_NAME,UID_DBUS_PATH, UID_DBUS_INTERFACE, UID_DBUS_METHOD, &uid); + if (ret < 0) { + mc_debug("Failed to send dbus (%d)", ret); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } else { + mc_debug("%d get UID[%d]", ret, uid); + } + + /* Connect media controller DB*/ + if(mc_db_util_connect(&(mc_svc_data->db_handle), uid, true) != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("Failed to connect DB"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + /* Destroy tables */ + if (mc_db_util_delete_whole_server_tables(mc_svc_data->db_handle) != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("mc_db_util_delete_whole_server_tables failed [%d]", ret); + } + + /* Create tables */ + if (mc_db_util_create_tables(mc_svc_data->db_handle) != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("mc_db_util_create_tables failed [%d]", ret); + return FALSE; + } + ret = mc_cynara_enable_credentials_passing(sockfd); if(ret != MEDIA_CONTROLLER_ERROR_NONE) { mc_error("Failed to append socket options"); @@ -273,16 +370,26 @@ gboolean mc_svc_thread(void *data) if (mc_svc_data->mc_svc_list != NULL) { - int i = 0; - for (i = g_list_length(mc_svc_data->mc_svc_list) - 1; i >= 0; i--) { - char *nth_data = (char *)g_list_nth_data(mc_svc_data->mc_svc_list, i); - mc_svc_data->mc_svc_list = g_list_remove(mc_svc_data->mc_svc_list, nth_data); - MC_SAFE_FREE(nth_data); + unsigned int idx = 0; + + for (idx = 0; idx < g_list_length(mc_svc_data->mc_svc_list); idx++) { + mc_svc_list_t *set_data = NULL; + set_data = (mc_svc_list_t *)g_list_nth_data(mc_svc_data->mc_svc_list, idx); + MC_SAFE_FREE(set_data->data); + MC_SAFE_FREE(set_data); } + g_list_free(mc_svc_data->mc_svc_list); } + MC_SAFE_FREE(mc_svc_data); + /* Disconnect media controller DB*/ + if(mc_db_util_disconnect(mc_svc_data->db_handle) != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("Failed to connect DB"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + /*close socket*/ close(sockfd); diff --git a/test/client_test/media_controller_client_test.c b/test/client_test/media_controller_client_test.c index 1ae2bb8..c4a4646 100755 --- a/test/client_test/media_controller_client_test.c +++ b/test/client_test/media_controller_client_test.c @@ -80,7 +80,7 @@ void _mc_playback_updated_cb(const char *server_name, mc_playback_h playback, vo { media_controller_client_s *_client = (media_controller_client_s *)g_mc_client; unsigned long long position = 0; - mc_playback_states_e playback_state = MEDIA_PLAYBACK_STATE_NONE; + mc_playback_states_e playback_state = MC_PLAYBACK_STATE_NONE; mc_client_get_playback_position(playback, &position); mc_client_get_playback_state(playback, &playback_state); @@ -96,7 +96,7 @@ void _mc_metadata_updated_cb(const char *server_name, mc_metadata_h metadata, vo media_controller_client_s *_client = (media_controller_client_s *)g_mc_client; mc_debug("[Client:%s] Metadata updated from server[%s] ", _client->client_name, server_name); - for (idx = 0; idx <= MEDIA_PICTURE; idx++) { + for (idx = 0; idx <= MC_META_MEDIA_PICTURE; idx++) { ret = mc_client_get_metadata(metadata, idx, &str_val); if (ret != MEDIA_CONTROLLER_ERROR_NONE) mc_error("Fail to mc_client_get_metadata"); @@ -297,7 +297,7 @@ static gboolean _get_info(int type) g_print("Fail to get metadata"); return FALSE; } - ret = mc_client_get_metadata(metadata, MEDIA_TITLE, &metadata_value); + ret = mc_client_get_metadata(metadata, MC_META_MEDIA_TITLE, &metadata_value); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { g_print("Fail to get infot"); } @@ -341,17 +341,20 @@ static gboolean _send() g_print("== send command to latest server \n"); int ret; - if (g_playback_state == MEDIA_PLAYBACK_STATE_PLAYING) - g_playback_state = MEDIA_PLAYBACK_STATE_STOPPED; + if (g_playback_state == MC_PLAYBACK_STATE_PLAYING) + g_playback_state = MC_PLAYBACK_STATE_STOPPED; else - g_playback_state = MEDIA_PLAYBACK_STATE_PLAYING; + g_playback_state = MC_PLAYBACK_STATE_PLAYING; ret = mc_client_send_playback_state_command(g_mc_client, g_server_name, g_playback_state); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { g_print("Fail to send playback state command %d", ret); return FALSE; } - usleep(500000); + struct timespec reqtime; + reqtime.tv_sec = 0; + reqtime.tv_nsec = 500000000; + nanosleep(&reqtime, NULL); bundle *bundle_data = bundle_create(); bundle_add_str(bundle_data, "key1", "val1"); @@ -546,13 +549,13 @@ int client_sequential_test(void) int ret = MEDIA_CONTROLLER_ERROR_NONE; char *server_name = NULL; mc_server_state_e server_state = MC_SERVER_STATE_NONE; - mc_shuffle_mode_e shuffle_mode = SHUFFLE_MODE_OFF; - mc_repeat_mode_e repeat_mode = REPEAT_MODE_OFF; + mc_shuffle_mode_e shuffle_mode = MC_SHUFFLE_MODE_OFF; + mc_repeat_mode_e repeat_mode = MC_REPEAT_MODE_OFF; mc_metadata_h metadata = NULL; mc_playback_h playback = NULL; char *str_val = NULL; int idx = 0; - mc_playback_states_e playback_state = MEDIA_PLAYBACK_STATE_REWIND; + mc_playback_states_e playback_state = MC_PLAYBACK_STATE_REWIND; unsigned long long playback_position = 0; /*Create Client*/ @@ -603,7 +606,7 @@ int client_sequential_test(void) if (ret != MEDIA_CONTROLLER_ERROR_NONE) g_print("Fail to mc_client_get_server_metadata\n"); - for (idx = 0; idx <= MEDIA_PICTURE; idx++) { + for (idx = 0; idx <= MC_META_MEDIA_PICTURE; idx++) { ret = mc_client_get_metadata(metadata, idx, &str_val); if (ret != MEDIA_CONTROLLER_ERROR_NONE) g_print("Fail to mc_client_get_metadata\n"); @@ -645,7 +648,7 @@ int main(int argc, char **argv) g_io_channel_set_flags(stdin_channel, G_IO_FLAG_NONBLOCK, NULL); g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)input, NULL); - g_playback_state = MEDIA_PLAYBACK_STATE_PLAYING; + g_playback_state = MC_PLAYBACK_STATE_PLAYING; mainloop = g_main_loop_new(NULL, FALSE); diff --git a/test/server_test/media_controller_server_test.c b/test/server_test/media_controller_server_test.c index 2b2693d..083cd5d 100755 --- a/test/server_test/media_controller_server_test.c +++ b/test/server_test/media_controller_server_test.c @@ -156,10 +156,10 @@ static gboolean _set_cb() static gboolean _set_info(int type, char *cmd) { g_print("== get information \n"); - int ret; + int ret = MEDIA_CONTROLLER_ERROR_NONE; int playback_state = 0; unsigned long long playback_position; - char *metadata; + char *metadata = NULL; switch (type) { case CURRENT_STATE_SET_PLAYBACK_STATE: @@ -189,10 +189,13 @@ static gboolean _set_info(int type, char *cmd) ret = mc_server_set_metadata(g_mc_server, g_metadata_type, metadata); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { g_print("Fail to set metadata"); + if(metadata != NULL) + free(metadata); return FALSE; } g_print("set metadata value: %s", metadata); - free(metadata); + if(metadata != NULL) + free(metadata); break; default: g_print(" == unknown type!\n"); @@ -225,10 +228,10 @@ static gboolean _update_info(int type) } break; case 3: - if (g_shuffle_mode == SHUFFLE_MODE_OFF) - g_shuffle_mode = SHUFFLE_MODE_ON; + if (g_shuffle_mode == MC_SHUFFLE_MODE_OFF) + g_shuffle_mode = MC_SHUFFLE_MODE_ON; else - g_shuffle_mode = SHUFFLE_MODE_OFF; + g_shuffle_mode = MC_SHUFFLE_MODE_OFF; ret = mc_server_update_shuffle_mode(g_mc_server, g_shuffle_mode); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { g_print("Fail to update shuffle mode err=%d", ret); @@ -236,10 +239,10 @@ static gboolean _update_info(int type) } break; case 4: - if (g_repeat_mode == REPEAT_MODE_OFF) - g_repeat_mode = REPEAT_MODE_ON; + if (g_repeat_mode == MC_REPEAT_MODE_OFF) + g_repeat_mode = MC_REPEAT_MODE_ON; else - g_repeat_mode = REPEAT_MODE_OFF; + g_repeat_mode = MC_REPEAT_MODE_OFF; ret = mc_server_update_repeat_mode(g_mc_server, g_repeat_mode); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { g_print("Fail to update repeat mode err=%d", ret); @@ -482,7 +485,7 @@ int server_sequential_test(void) return ret; } - ret = mc_server_set_playback_state(g_mc_server, MEDIA_PLAYBACK_STATE_PLAYING); + ret = mc_server_set_playback_state(g_mc_server, MC_PLAYBACK_STATE_PLAYING); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { g_print("Fail to mc_server_set_playback_state\n"); return ret; @@ -500,25 +503,25 @@ int server_sequential_test(void) /*return ret; */ } - ret = mc_server_set_metadata(g_mc_server, MEDIA_TITLE, "media_title"); - ret = mc_server_set_metadata(g_mc_server, MEDIA_ARTIST, "media_artist"); - ret = mc_server_set_metadata(g_mc_server, MEDIA_ALBUM, "media_album"); - ret = mc_server_set_metadata(g_mc_server, MEDIA_AUTHOR, "media_author"); - ret = mc_server_set_metadata(g_mc_server, MEDIA_GENRE, "media_genre"); - ret = mc_server_set_metadata(g_mc_server, MEDIA_DURATION, "200"); - ret = mc_server_set_metadata(g_mc_server, MEDIA_DATE, "media_date"); - ret = mc_server_set_metadata(g_mc_server, MEDIA_COPYRIGHT, "media_copyright"); - ret = mc_server_set_metadata(g_mc_server, MEDIA_DESCRIPTION, "media_description"); - ret = mc_server_set_metadata(g_mc_server, MEDIA_TRACK_NUM, "media_track_num 3/10"); - ret = mc_server_set_metadata(g_mc_server, MEDIA_PICTURE, "media_picture_path"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_TITLE, "media_title"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_ARTIST, "media_artist"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_ALBUM, "media_album"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_AUTHOR, "media_author"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_GENRE, "media_genre"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_DURATION, "200"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_DATE, "media_date"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_COPYRIGHT, "media_copyright"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_DESCRIPTION, "media_description"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_TRACK_NUM, "media_track_num 3/10"); + ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_PICTURE, "media_picture_path"); ret = mc_server_update_metadata(g_mc_server); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { g_print("Fail to mc_server_update_metadata\n"); /*return ret; */ } - ret = mc_server_update_shuffle_mode(g_mc_server, SHUFFLE_MODE_ON); - ret = mc_server_update_repeat_mode(g_mc_server, REPEAT_MODE_ON); + ret = mc_server_update_shuffle_mode(g_mc_server, MC_SHUFFLE_MODE_ON); + ret = mc_server_update_repeat_mode(g_mc_server, MC_REPEAT_MODE_ON); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { g_print("Fail to mc_server_update_repeat_mode\n"); return ret; @@ -540,8 +543,8 @@ int main(int argc, char **argv) g_io_channel_set_flags(stdin_channel, G_IO_FLAG_NONBLOCK, NULL); g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)input, NULL); - g_shuffle_mode = SHUFFLE_MODE_OFF; - g_repeat_mode = REPEAT_MODE_OFF; + g_shuffle_mode = MC_SHUFFLE_MODE_OFF; + g_repeat_mode = MC_REPEAT_MODE_OFF; mainloop = g_main_loop_new(NULL, FALSE); |