d5624e4b62bfe6dbd7a05b66cf4a22d71d425601
[apps/mediaplayer.git] / binding / mediaplayer-manager.c
1 /*
2  *  Copyright 2017 Konsulko Group
3  *
4  *  Based on bluetooth-manager.c
5  *   Copyright 2016 ALPS ELECTRIC CO., LTD.
6  *
7  *   Licensed under the Apache License, Version 2.0 (the "License");
8  *   you may not use this file except in compliance with the License.
9  *   You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *   Unless required by applicable law or agreed to in writing, software
14  *   distributed under the License is distributed on an "AS IS" BASIS,
15  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *   See the License for the specific language governing permissions and
17  *   limitations under the License.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26
27 #include <pthread.h>
28 #include <glib.h>
29 #include <gio/gio.h>
30 #include <glib-object.h>
31 #include <sqlite3.h>
32
33 #include "mediaplayer-manager.h"
34
35 static Binding_RegisterCallback_t g_RegisterCallback = { 0 };
36 static stMediaPlayerManage MediaPlayerManage = { 0 };
37
38 /* ------ LOCAL  FUNCTIONS --------- */
39 void ListLock() {
40     g_mutex_lock(&(MediaPlayerManage.m));
41 }
42
43 void ListUnlock() {
44     g_mutex_unlock(&(MediaPlayerManage.m));
45 }
46
47 void DebugTraceSendMsg(int level, gchar* message)
48 {
49 #ifdef LOCAL_PRINT_DEBUG
50     switch (level)
51     {
52             case DT_LEVEL_ERROR:
53                 g_print("[E]");
54                 break;
55
56             case DT_LEVEL_WARNING:
57                 g_print("[W]");
58                 break;
59
60             case DT_LEVEL_NOTICE:
61                 g_print("[N]");
62                 break;
63
64             case DT_LEVEL_INFO:
65                 g_print("[I]");
66                 break;
67
68             case DT_LEVEL_DEBUG:
69                 g_print("[D]");
70                 break;
71
72             default:
73                 g_print("[-]");
74                 break;
75     }
76
77     g_print("%s",message);
78 #endif
79
80     if (message) {
81         g_free(message);
82     }
83
84 }
85
86 GList* media_lightmediascanner_scan(void)
87 {
88     sqlite3 *conn;
89     sqlite3_stmt *res;
90     GList *list;
91     const char *tail;
92     const gchar *db_path;
93     int ret = 0;
94
95     list = MediaPlayerManage.list;
96
97     // Returned cached result
98     if (list)
99         return list;
100
101     db_path = scanner1_get_data_base_path(MediaPlayerManage.lms_proxy);
102
103     ret = sqlite3_open(db_path, &conn);
104     if (ret) {
105         LOGE("Cannot open SQLITE database: '%s'\n", db_path);
106         return NULL;
107     }
108
109     ret = sqlite3_prepare_v2(conn, SQL_QUERY, strlen(SQL_QUERY) + 1, &res, &tail);
110     if (ret) {
111         LOGE("Cannot execute query '%s'\n", SQL_QUERY);
112         return NULL;
113     }
114
115     while (sqlite3_step(res) == SQLITE_ROW) {
116         struct stat buf;
117         const char *path = (const char *) sqlite3_column_text(res, 0);
118
119         ret = stat(path, &buf);
120         if (ret)
121             continue;
122
123         list = g_list_append(list, g_strdup_printf("file://%s", path));
124     }
125
126     MediaPlayerManage.list = list;
127
128     return list;
129 }
130
131
132 static void
133 on_interface_proxy_properties_changed (GDBusProxy *proxy,
134                                     GVariant *changed_properties,
135                                     const gchar* const  *invalidated_properties)
136 {
137     GVariantIter iter;
138     const gchar *key;
139     GVariant *subValue;
140     const gchar *pInterface;
141     GList *list;
142
143     pInterface = g_dbus_proxy_get_interface_name (proxy);
144
145     if (0 != g_strcmp0(pInterface, LIGHTMEDIASCANNER_INTERFACE))
146         return;
147
148     g_variant_iter_init (&iter, changed_properties);
149     while (g_variant_iter_next (&iter, "{&sv}", &key, &subValue))
150     {
151         gboolean val;
152         if (0 == g_strcmp0(key,"IsScanning")) {
153             g_variant_get(subValue, "b", &val);
154             if (val == TRUE)
155                 return;
156         } else if (0 == g_strcmp0(key, "WriteLocked")) {
157             g_variant_get(subValue, "b", &val);
158             if (val == TRUE)
159                 return;
160         }
161     }
162
163     ListLock();
164
165     list = media_lightmediascanner_scan();
166
167     if (list != NULL && g_RegisterCallback.binding_device_added)
168         g_RegisterCallback.binding_device_added(list);
169
170     ListUnlock();
171 }
172
173 static void
174 on_device_removed (GDBusProxy *proxy, gpointer user_data)
175 {
176     ListLock();
177
178     g_list_free(MediaPlayerManage.list);
179     MediaPlayerManage.list = NULL;
180
181     if (g_RegisterCallback.binding_device_removed)
182         g_RegisterCallback.binding_device_removed((const char *) user_data);
183
184     ListUnlock();
185 }
186
187 static int MediaPlayerDBusInit(void)
188 {
189     GError *error = NULL;
190
191     MediaPlayerManage.lms_proxy = scanner1_proxy_new_for_bus_sync(
192         G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, LIGHTMEDIASCANNER_SERVICE,
193         LIGHTMEDIASCANNER_PATH, NULL, &error);
194
195     if (MediaPlayerManage.lms_proxy == NULL) {
196         LOGE("Create LightMediaScanner Proxy failed\n");
197         return -1;
198     }
199
200     MediaPlayerManage.udisks_proxy = org_freedesktop_udisks_proxy_new_for_bus_sync(
201         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, UDISKS_SERVICE,
202         UDISKS_PATH, NULL, &error);
203
204     if (MediaPlayerManage.udisks_proxy == NULL) {
205         LOGE("Create UDisks Proxy failed\n");
206         return -1;
207     }
208
209     g_signal_connect (MediaPlayerManage.lms_proxy,
210                       "g-properties-changed",
211                       G_CALLBACK (on_interface_proxy_properties_changed),
212                       NULL);
213
214     g_signal_connect (MediaPlayerManage.udisks_proxy,
215                       "device-removed",
216                       G_CALLBACK (on_device_removed),
217                       NULL);
218
219     return 0;
220 }
221
222 static void *media_event_loop_thread(void *unused)
223 {
224     GMainLoop *loop = g_main_loop_new(NULL, FALSE);
225     int ret;
226
227     ret = MediaPlayerDBusInit();
228     if (ret == 0) {
229         LOGD("g_main_loop_run\n");
230         g_main_loop_run(loop);
231     }
232
233     g_main_loop_unref(loop);
234
235     return NULL;
236 }
237
238 /*
239  * Create MediaPlayer Manager Thread
240  * Note: mediaplayer-api should do MediaPlayerManagerInit() before any other 
241  *       API calls
242  * Returns: 0 - success or error conditions
243  */
244 int MediaPlayerManagerInit() {
245     pthread_t thread_id;
246
247     g_mutex_init(&(MediaPlayerManage.m));
248
249     pthread_create(&thread_id, NULL, media_event_loop_thread, NULL);
250
251     return 0;
252 }
253
254 /*
255  * Register MediaPlayer Manager Callback functions
256  */
257 void BindingAPIRegister(const Binding_RegisterCallback_t* pstRegisterCallback)
258 {
259     if (NULL != pstRegisterCallback)
260     {
261         if (NULL != pstRegisterCallback->binding_device_added)
262         {
263             g_RegisterCallback.binding_device_added =
264                 pstRegisterCallback->binding_device_added;
265         }
266
267         if (NULL != pstRegisterCallback->binding_device_removed)
268         {
269             g_RegisterCallback.binding_device_removed =
270                 pstRegisterCallback->binding_device_removed;
271         }
272     }
273 }