Update path replacement function
[platform/core/multimedia/media-server.git] / lib / media-util-noti.c
1 /*
2  * Media Utility
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Yong Yeon Kim <yy9875.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <glib.h>
23 #include <gio/gio.h>
24
25 #include "media-util-internal.h"
26 #include "media-util-dbg.h"
27 #include "media-util.h"
28
29 #include "private.h"
30
31 static GDBusConnection *g_bus = NULL;
32 static guint g_handler = 0;
33 static void *g_data_store = NULL;
34 static GMutex noti_mutex;
35 static int ref_count = 0;
36
37 #define MS_MEDIA_DBUS_NAME "ms_db_updated"
38
39 typedef struct noti_callback_data {
40         db_update_cb user_callback;
41         void *user_data;
42 } noti_callback_data;
43
44 static bool __gdbus_message_is_signal(const char *iface, const char *signal)
45 {
46         if ((strcmp(iface, MS_MEDIA_DBUS_INTERFACE) == 0) && (strcmp(signal, MS_MEDIA_DBUS_NAME) == 0))
47                 return TRUE;
48
49         return FALSE;
50 }
51
52 static void __get_message(GVariant *message, db_update_cb user_cb, void *userdata)
53 {
54         gint32 item = -1;
55         gint32 pid = 0;
56         gint32 update_type = MS_MEDIA_UNKNOWN;
57         gint32 content_type = -1;
58         char *update_path = NULL;
59         char *uuid = NULL;
60         char *mime_type = NULL;
61
62         int item_number = g_variant_n_children(message);
63
64         if (item_number == 7)
65                 g_variant_get(message, "(iiissis)", &item, &pid, &update_type, &update_path, &uuid, &content_type, &mime_type);
66         else if (item_number == 5)
67                 g_variant_get(message, "(iiiss)", &item, &pid, &update_type, &update_path, &uuid);
68         else if (item_number == 4)
69                 g_variant_get(message, "(iiis)", &item, &pid, &update_type, &update_path);
70
71         if (item == MS_MEDIA_ITEM_DIRECTORY)
72                 content_type = MS_MEDIA_UNKNOWN;
73
74         /* getting data complete */
75         user_cb(pid,
76                         item,
77                         update_type,
78                         update_path,
79                         uuid,
80                         content_type,
81                         mime_type,
82                         userdata);
83
84         MS_SAFE_FREE(update_path);
85         MS_SAFE_FREE(uuid);
86         MS_SAFE_FREE(mime_type);
87 }
88
89 static void __message_filter(GDBusConnection* connection,
90                                         const gchar* sender_name,
91                                         const gchar* object_path,
92                                         const gchar* interface_name,
93                                         const gchar* signal_name,
94                                         GVariant* parameters,
95                                         gpointer user_data)
96 {
97         if (__gdbus_message_is_signal(interface_name, signal_name)) {
98                 db_update_cb user_cb = ((noti_callback_data*)user_data)->user_callback;
99                 void *userdata = ((noti_callback_data*)user_data)->user_data;
100
101                 __get_message(parameters, user_cb, userdata);
102         }
103 }
104
105 int media_db_update_subscribe(db_update_cb user_cb, void *user_data)
106 {
107         int ret = MS_MEDIA_ERR_NONE;
108         GError *error = NULL;
109         noti_callback_data *callback_data = NULL;
110
111         g_mutex_lock(&noti_mutex);
112
113         if (g_bus == NULL) {
114                 g_bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
115                 if (!g_bus) {
116                         MSAPI_DBG("Failed to connect to the g D-BUS daemon: %s", error->message);
117                         g_error_free(error);
118                         ret = MS_MEDIA_ERR_INTERNAL;
119                         goto ERROR;
120                 }
121
122                 MS_MALLOC(callback_data, sizeof(noti_callback_data));
123                 if (callback_data == NULL) {
124                         MSAPI_DBG_ERR("MS_MALLOC failed");
125                         ret = MS_MEDIA_ERR_OUT_OF_MEMORY;
126                         goto ERROR;
127                 }
128                 callback_data->user_callback = user_cb;
129                 callback_data->user_data = user_data;
130
131                 /* listening to messages from all objects as no path is specified */
132                 g_handler = g_dbus_connection_signal_subscribe(
133                                                 g_bus,
134                                                 NULL,
135                                                 MS_MEDIA_DBUS_INTERFACE,
136                                                 MS_MEDIA_DBUS_NAME,
137                                                 MS_MEDIA_DBUS_PATH,
138                                                 NULL,
139                                                 G_DBUS_SIGNAL_FLAGS_NONE,
140                                                 __message_filter,
141                                                 callback_data,
142                                                 NULL);
143                 g_data_store = (void *)callback_data;
144         }
145
146         ref_count++;
147
148         g_mutex_unlock(&noti_mutex);
149
150         return MS_MEDIA_ERR_NONE;
151
152 ERROR:
153
154         if (g_bus != NULL) {
155                 g_object_unref(g_bus);
156                 g_bus = NULL;
157         }
158         MS_SAFE_FREE(callback_data);
159
160         g_mutex_unlock(&noti_mutex);
161
162         return ret;
163 }
164
165 int media_db_update_unsubscribe(void)
166 {
167         if (g_bus == NULL)
168                 return MS_MEDIA_ERR_NONE;
169
170         g_mutex_lock(&noti_mutex);
171
172         if (ref_count == 1) {
173                 g_dbus_connection_signal_unsubscribe(g_bus, g_handler);
174                 g_object_unref(g_bus);
175                 g_bus = NULL;
176
177                 /*Release Callback*/
178                 MS_SAFE_FREE(g_data_store);
179                 g_data_store = NULL;
180         }
181
182         ref_count--;
183
184         g_mutex_unlock(&noti_mutex);
185
186         return MS_MEDIA_ERR_NONE;
187 }
188
189 int media_db_update_send(int pid, /* mandatory */
190                                                         media_item_type_e item, /* mandatory */
191                                                         media_item_update_type_e update_type, /* mandatory */
192                                                         char* path, /* mandatory */
193                                                         char* uuid, /* optional */
194                                                         media_type_e media_type, /* optional */
195                                                         char *mime_type /* optional */
196                                                         )
197 {
198         GVariant *message = NULL;
199         GDBusConnection *bus = NULL;
200         GError *error = NULL;
201
202         bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
203         if (!bus) {
204                 MSAPI_DBG("Failed to get gdbus connection: %s", error->message);
205                 g_error_free(error);
206                 return MS_MEDIA_ERR_INTERNAL;
207         }
208
209         if (item == MS_MEDIA_ITEM_FILE) {
210                 MSAPI_DBG("FILE CHANGED");
211                 if (uuid != NULL && mime_type != NULL) {
212                         /* fill all datas */
213                         message = g_variant_new("(iiissis)", item, pid, update_type, path, uuid, media_type, mime_type);
214                 } else {
215                         MSAPI_DBG_ERR("uuid or mime_type is NULL");
216                         g_object_unref(bus);
217                         return MS_MEDIA_ERR_INVALID_PARAMETER;
218                 }
219         } else if (item == MS_MEDIA_ITEM_DIRECTORY) {
220                 MSAPI_DBG("DIRECTORY CHANGED");
221                 /* fill all datas */
222                 if (uuid != NULL)
223                         message = g_variant_new("(iiiss)", item, pid, update_type, path, uuid);
224                 else
225                         message = g_variant_new("(iiis)", item, pid, update_type, path);
226         } else {
227                 MSAPI_DBG("this request is wrong");
228         }
229
230         gboolean emmiting = g_dbus_connection_emit_signal(
231                                         bus,
232                                         NULL,
233                                         MS_MEDIA_DBUS_PATH,
234                                         MS_MEDIA_DBUS_INTERFACE,
235                                         MS_MEDIA_DBUS_NAME,
236                                         message,
237                                         &error);
238         if (!emmiting) {
239                 MSAPI_DBG_ERR("g_dbus_connection_emit_signal failed : %s", error ? error->message : "none");
240                 if (error) {
241                         MSAPI_DBG_ERR("Error in g_dbus_connection_emit_signal");
242                         g_object_unref(bus);
243                         g_error_free(error);
244                 }
245                 return MS_MEDIA_ERR_INTERNAL;
246         }
247         MSAPI_DBG("success send notification");
248
249         gboolean flush = FALSE;
250         flush = g_dbus_connection_flush_sync(bus, NULL, &error);
251         if (!flush) {
252                 MSAPI_DBG_ERR("g_dbus_connection_flush_sync failed");
253                 if (error) {
254                         MSAPI_DBG_ERR("error : [%s]", error->message);
255                         g_object_unref(bus);
256                         g_error_free(error);
257                         return MS_MEDIA_ERR_INTERNAL;
258                 }
259         }
260
261         g_object_unref(bus);
262
263         /* Return TRUE to tell the event loop we want to be called again */
264         return MS_MEDIA_ERR_NONE;
265 }