From fd0fd0a0b88355398d7f57c34e30b47a94c8329f Mon Sep 17 00:00:00 2001
From: Farshid Monhaseri <monhaseri.f@gmail.com>
Date: Mon, 3 Feb 2020 17:38:27 +0330
Subject: mediascanner: Clustered media-list & Code unification

Bug-AGL: SPEC-3100

- Add clustered media-list view as an option when the user requests
it with 'view':'clustered' ARGS on event subscription or
'media_result' verb call. If no ARGS passed, the scanner has its
default media-list view.
- Unify event scans & verb-call scans codes as much as possible.
Now scan operation has single & transparent control flow.
- Add 'ScanFilter_t' data structure and a few other modifications
so managing new features and filters will be easier and clear.
- Fix a few bugs.
- Extract precise error messages from deeper functions and log & reply
fail message to the client.

Signed-off-by: Farshid Monhaseri <monhaseri.f@gmail.com>
Change-Id: Ia3629af75614359260eb7af0c0331d6ef9f3bcbe
---
 binding/media-api.c     | 253 ++++++++++++++++++++++++++++++++++++------------
 binding/media-manager.c | 166 ++++++++++++++++++++-----------
 binding/media-manager.h | 102 +++++++++++--------
 3 files changed, 361 insertions(+), 160 deletions(-)

diff --git a/binding/media-api.c b/binding/media-api.c
index 0365b49..bd0f7db 100644
--- a/binding/media-api.c
+++ b/binding/media-api.c
@@ -31,7 +31,7 @@ static afb_event_t media_removed_event;
 
 static gint get_scan_type(afb_req_t request, json_object *jtype) {
     gint ret = 0;
-    const *stype = NULL;
+    const char *stype = NULL;
     if(!json_object_is_type(jtype,json_type_string)) {
         afb_req_fail(request,"failed", "invalid scan-type type");
         return ret;
@@ -64,9 +64,9 @@ static gint get_scan_types(afb_req_t request) {
 
     if(!json_object_object_get_ex(afb_req_json(request),"types",&jtypes)) {
         /*
-         * Considering 'audio' & 'video' scan types as default
-         * if the user doesn't provide 'types' property,
-         * for sake of compability with previeus versions
+         * Considered 'audio' & 'video' scan types as default types,
+         * if the user doesn't provide 'types' property.
+         * (for sake of backward compatibility)
          */
         ret = (LMS_AUDIO_SCAN | LMS_VIDEO_SCAN);
         return ret;
@@ -83,18 +83,46 @@ static gint get_scan_types(afb_req_t request) {
 
         for(i=0; i<len; ++i){
             gint t = get_scan_type(request, json_object_array_get_idx(jtypes,i));
-            if(t != 0) { ret |= t; } else { return -1;}
+            if(t != 0) { ret |= t; } else { return -1; }
         }
         return ret;
     } else if(json_object_is_type(jtypes,json_type_string)) {
         gint t = get_scan_type(request,jtypes);
-        if(t != 0) {return t;} else {return -1;}
+        if(t != 0) { return t; } else { return -1; }
     } else {
         afb_req_fail(request, "failed", "invalid scan-types format");
         return -1;
     }
 }
 
+static int get_scan_view(afb_req_t request) {
+    json_object *jview = NULL;
+    const char* sview = NULL;
+
+    if(!afb_req_is_valid(request)) {
+        afb_req_fail(request, "failed", "invalid request");
+        return -1;
+    }
+
+    if(!json_object_object_get_ex(afb_req_json(request),"view",&jview)){
+        return MEDIA_LIST_VIEW_DEFAULT;
+    }
+
+    if(!json_object_is_type(jview,json_type_string)) {
+        afb_req_fail(request,"failed", "invalid media-list-view value");
+        return -1;
+    }
+    sview = json_object_get_string(jview);
+
+    if(!strcasecmp(sview,"clustered")) {
+        return MEDIA_LIST_VIEW_CLUSTERD;
+    } else if(!strcasecmp(sview,"default")){
+        return MEDIA_LIST_VIEW_DEFAULT;
+    } else {
+        afb_req_fail(request,"failed","Unknown media-list-view type");
+        return -1;
+    }
+}
 /*
  * @brief Subscribe for an event
  *
@@ -103,25 +131,30 @@ static gint get_scan_types(afb_req_t request) {
  */
 static void subscribe(afb_req_t request)
 {
-	const char *value = afb_req_value(request, "value");
-    gint scantype = 0;
-
-	if(value) {
-		if(!strcasecmp(value, "media_added")) {
-			afb_req_subscribe(request, media_added_event);
-		} else if(!strcasecmp(value, "media_removed")) {
-			afb_req_subscribe(request, media_removed_event);
-		} else {
-			afb_req_fail(request, "failed", "Invalid event");
-			return;
-		}
-	}
+    const char *value = afb_req_value(request, "value");
 
-    //Get scan types & append them to scan config
-    scantype = get_scan_types(request);
-    if(scantype < 0) return;
+    if(value) {
+        if(!strcasecmp(value, "media_added")) {
+            gint scan_type = 0;
+            gint view_type = 0;
 
-    ScanTypeAppend(scantype);
+            afb_req_subscribe(request, media_added_event);
+            //Get scan types & append them to mediascan config
+            scan_type = get_scan_types(request);
+            if(scan_type < 0)
+            return;
+            ScanTypeAppend(scan_type);
+            view_type = get_scan_view(request);
+            if(view_type < 1)
+            return;
+            setAPIMediaListView(view_type);
+        } else if(!strcasecmp(value, "media_removed")) {
+            afb_req_subscribe(request, media_removed_event);
+        } else {
+            afb_req_fail(request, "failed", "Invalid event");
+            return;
+        }
+    }
     afb_req_success(request, NULL, NULL);
 }
 
@@ -139,14 +172,15 @@ static void unsubscribe(afb_req_t request)
     if( json_object_object_get_ex(jrequest,"value",NULL) &&
         json_object_object_get_ex(jrequest,"types",NULL) ) {
         //If 'types' is provided, We just remove the specified types.
-        gint scantype = get_scan_types(request);
-        if(scantype < 0) return;
+        gint scan_type = get_scan_types(request);
+        if(scan_type < 0)
+            return;
 
         /*
-         * If any scan type remained, we escape unsubscribe the event
+         * If any scan type remained, we escape unsubscribing the event
          * otherwise continue to unsubscribe the event
          */
-        if(ScanTypeRemove(scantype)) {
+        if(ScanTypeRemove(scan_type)) {
             afb_req_success(request, NULL, NULL);
             return;
         }
@@ -166,23 +200,26 @@ static void unsubscribe(afb_req_t request)
 	afb_req_success(request, NULL, NULL);
 }
 
-static json_object *new_json_object_from_device(GList *list)
+static gint
+media_jlist_from_media_list(MediaList_t *mlist, const gint view, json_object *jarray)
 {
-    json_object *jarray = json_object_new_array();
-    json_object *jresp = json_object_new_object();
     json_object *jstring = NULL;
     GList *l;
+    gint num = 0;
+    const GList *list = mlist->list;
+    const char *scan_type = mlist->scan_type_str;
 
     for (l = list; l; l = l->next)
     {
-        struct Media_Item *item = l->data;
+        MediaItem_t *item = l->data;
         json_object *jdict = json_object_new_object();
 
         jstring = json_object_new_string(item->path);
         json_object_object_add(jdict, "path", jstring);
-
-        jstring = json_object_new_string(item->type);
-        json_object_object_add(jdict, "type", jstring);
+        if(view == MEDIA_LIST_VIEW_DEFAULT) {
+            jstring = json_object_new_string(scan_type);
+            json_object_object_add(jdict, "type", jstring);
+        }
 
         if (item->metadata.title) {
             jstring = json_object_new_string(item->metadata.title);
@@ -210,59 +247,153 @@ static json_object *new_json_object_from_device(GList *list)
         }
 
         json_object_array_add(jarray, jdict);
+        num++;
     }
 
     if (jstring == NULL)
+        return -1;
+
+    return num;
+}
+
+static json_object* media_device_scan(ScanFilter_t *filter, gchar **error)
+{
+    json_object *jresp = NULL;
+    json_object *jlist = NULL;
+    MediaList_t *mlist = NULL;
+    MediaDevice_t *mdev = NULL;
+    gint res = -1;
+    gint num = 0;
+    gint i;
+
+    if(!filter){
+        *error = g_strdup("NULL filter!");
+        return NULL;
+    }
+    if(!filter->scan_types)
+        return NULL;
+
+    mdev = g_malloc0(sizeof(*mdev));
+    if(!mdev){
+        *error = g_strdup("Cannot allocate memory.");
+        return NULL;
+    }
+
+    for( i = LMS_MIN_ID; i < LMS_SCAN_COUNT; ++i)
+    {
+        if(filter->scan_types & (1 << i))
+        {
+            mdev->lists[i] = g_malloc0(sizeof(MediaList_t));
+            if(!mdev->lists[i]){
+                media_device_free(mdev);
+                *error = g_strdup("Cannot allocate memory to media-list object");
+                return NULL;
+            }
+        }
+    }
+    mdev->filters = filter;
+
+    res = media_lists_get(mdev,error);
+    if(res < 0)
+    {
+        media_device_free(mdev);
         return NULL;
+    }
 
-    json_object_object_add(jresp, "Media", jarray);
+    if(filter->listview_type == MEDIA_LIST_VIEW_CLUSTERD)
+    {
+        jlist = json_object_new_object();
+        for(i = LMS_MIN_ID; i < LMS_SCAN_COUNT; ++i)
+        {
+            json_object *typed_arr = json_object_new_array();
+            mlist = mdev->lists[i];
+            if(mlist != NULL)
+            {
+                res = media_jlist_from_media_list(mlist,MEDIA_LIST_VIEW_CLUSTERD,typed_arr);
+                if(res < 0)
+                {
+                    *error = g_strdup("media parsing error");
+                    media_device_free(mdev);
+                    json_object_put(jlist);
+                    return NULL;
+                }
+                json_object_object_add(jlist,lms_scan_types[i],typed_arr);
+                num += res;
+            }
+        }
+    }
+    else
+    {
+        jlist = json_object_new_array();
+        for(i = LMS_MIN_ID; i < LMS_SCAN_COUNT; ++i)
+        {
+            mlist = mdev->lists[i];
+            if(mlist != NULL)
+            {
+                res = media_jlist_from_media_list(mlist,MEDIA_LIST_VIEW_DEFAULT,jlist);
+                if(res < 0)
+                {
+                    *error = g_strdup("media parsing error");
+                    media_device_free(mdev);
+                    json_object_put(jlist);
+                    return NULL;
+                }
+                num += res;
+            }
+        }
+    }
+    media_device_free(mdev);
 
+    jresp = json_object_new_object();
+    json_object_object_add(jresp, "Media", jlist);
     return jresp;
 }
 
 static void media_results_get (afb_req_t request)
 {
-    GList *list = NULL;
     json_object *jresp = NULL;
-    gint scan_type = 0;
-
-    scan_type = get_scan_types(request);
-    if(scan_type < 0) return;
+    gchar *error = NULL;
+    gint scan_types = 0;
+    ScanFilter_t filter;
 
-    ListLock();
-
-    if(scan_type & LMS_AUDIO_SCAN)
-        list = media_lightmediascanner_scan(list, NULL, LMS_AUDIO_SCAN);
-    if(scan_type & LMS_VIDEO_SCAN)
-        list = media_lightmediascanner_scan(list, NULL, LMS_VIDEO_SCAN);
-    if(scan_type & LMS_IMAGE_SCAN)
-        list = media_lightmediascanner_scan(list, NULL, LMS_IMAGE_SCAN);
-
-    if (list == NULL) {
-        afb_req_fail(request, "failed", "media scan error");
-        ListUnlock();
+    filter.scan_types = get_scan_types(request);
+    if(filter.scan_types < 0)
         return;
-    }
+    filter.listview_type = get_scan_view(request);
+    filter.scan_uri = SCAN_URI_DEFAULT;
 
-    jresp = new_json_object_from_device(list);
-    g_list_free_full(list,free_media_item);
+    ListLock();
+    jresp = media_device_scan(&filter,&error);
     ListUnlock();
 
-    if (jresp == NULL) {
-        afb_req_fail(request, "failed", "media parsing error");
+    if (jresp == NULL)
+    {
+        afb_req_fail(request, "failed", error);
+        LOGE(" %s",error);
+        g_free(error);
         return;
     }
 
     afb_req_success(request, jresp, "Media Results Displayed");
 }
 
-static void media_broadcast_device_added (GList *list)
+static void media_broadcast_device_added (ScanFilter_t *filters)
 {
-    json_object *jresp = new_json_object_from_device(list);
+    json_object *jresp = NULL;
+    gchar *error = NULL;
 
-    if (jresp != NULL) {
-        afb_event_push(media_added_event, jresp);
+    ListLock();
+    jresp = media_device_scan(filters,&error);
+    ListUnlock();
+
+    if (jresp == NULL)
+    {
+        LOGE("ERROR:%s\n",error);
+        g_free(error);
+        return;
     }
+
+    afb_event_push(media_added_event, jresp);
 }
 
 static void media_broadcast_device_removed (const char *obj_path)
diff --git a/binding/media-manager.c b/binding/media-manager.c
index 283692c..8e1ac69 100644
--- a/binding/media-manager.c
+++ b/binding/media-manager.c
@@ -48,6 +48,7 @@ static stMediaPlayerManage MediaPlayerManage = { 0 };
 static scannerDB scanDB = { 0 };
 
 /* ------ LOCAL  FUNCTIONS --------- */
+
 void ListLock() {
     g_mutex_lock(&(MediaPlayerManage.m));
 }
@@ -95,59 +96,67 @@ void DebugTraceSendMsg(int level, gchar* message)
 
 }
 
-GList* media_lightmediascanner_scan(GList *list, gchar *uri, int scan_type)
+static void media_item_free(gpointer data)
+{
+    MediaItem_t *item = data;
+
+	g_free(item->metadata.title);
+	g_free(item->metadata.artist);
+	g_free(item->metadata.album);
+	g_free(item->metadata.genre);
+	g_free(item->path);
+	g_free(item);
+}
+
+gint media_lightmediascanner_scan(MediaList_t *mlist, gchar* uri, gchar **error)
 {
-    sqlite3 *conn;
     sqlite3_stmt *res;
     const char *tail;
     const gchar *db_path;
     gchar *query;
-    gchar *media_type;
     int ret = 0;
+    gint num = 0;
 
     if(!scanDB.is_open) {
         db_path = scanner1_get_data_base_path(MediaPlayerManage.lms_proxy);
 
         ret = sqlite3_open(db_path, &scanDB.db);
         if (ret != SQLITE_OK) {
-            LOGE("Cannot open SQLITE database: '%s'\n", db_path);
+            LOGD("Cannot open SQLITE database: '%s'\n", db_path);
             scanDB.is_open = FALSE;
-            g_list_free_full(list,free_media_item);
-            return NULL;
+            g_list_free_full(mlist,media_item_free);
+            return -1;
         }
         scanDB.is_open = TRUE;
     }
 
-    switch (scan_type) {
-        case LMS_VIDEO_SCAN:
+    switch (mlist->scan_type_id) {
+        case LMS_VIDEO_ID:
             query = g_strdup_printf(VIDEO_SQL_QUERY, uri ? uri : "");
-            media_type = lms_scan_types[LMS_VIDEO_ID];
             break;
-        case LMS_IMAGE_SCAN:
+        case LMS_IMAGE_ID:
             query = g_strdup_printf(IMAGE_SQL_QUERY, uri ? uri : "");
-            media_type = lms_scan_types[LMS_IMAGE_ID];
             break;
-        case LMS_AUDIO_SCAN:
+        case LMS_AUDIO_ID:
         default:
             query = g_strdup_printf(AUDIO_SQL_QUERY, uri ? uri : "");
-            media_type = lms_scan_types[LMS_AUDIO_ID];
     }
 
     if (!query) {
-        LOGE("Cannot allocate memory for query\n");
-        return NULL;
+        *error = g_strdup_printf("Cannot allocate memory for query");
+        return -1;
     }
 
     ret = sqlite3_prepare_v2(scanDB.db, query, (int) strlen(query), &res, &tail);
     if (ret) {
-        LOGE("Cannot execute query '%s'\n", query);
+        *error = g_strdup("Cannot execute query");
         g_free(query);
-        return NULL;
+        return -1;
     }
 
     while (sqlite3_step(res) == SQLITE_ROW) {
         struct stat buf;
-        struct Media_Item *item;
+        MediaItem_t *item = NULL;
         const char *path = (const char *) sqlite3_column_text(res, 0);
         gchar *tmp;
 
@@ -155,35 +164,42 @@ GList* media_lightmediascanner_scan(GList *list, gchar *uri, int scan_type)
         if (ret)
             continue;
 
-        //We may check the allocation result ... but It may be a bit expensive in such a loop
+        //We may check the allocation result ... but It maybe a bit expensive in such a loop
         item = g_malloc0(sizeof(*item));
+
         tmp = g_uri_escape_string(path, "/", TRUE);
         item->path = g_strdup_printf("file://%s", tmp);
         g_free(tmp);
 
-        item->type = media_type;
         item->metadata.title = g_strdup((gchar *) sqlite3_column_text(res, 1));
         item->metadata.artist = g_strdup((gchar *) sqlite3_column_text(res, 2));
         item->metadata.album = g_strdup((gchar *) sqlite3_column_text(res, 3));
         item->metadata.genre = g_strdup((gchar *) sqlite3_column_text(res, 4));
         item->metadata.duration = sqlite3_column_int(res, 5) * 1000;
-        list = g_list_append(list, item);
+        mlist->list = g_list_append(mlist->list, item);
+        num++;
     }
     g_free(query);
 
-    return list;
+    return num;
 }
 
-void free_media_item(void *data)
+void media_device_free(MediaDevice_t *mdev)
 {
-    struct Media_Item *item = data;
+    gint i;
 
-	g_free(item->metadata.title);
-	g_free(item->metadata.artist);
-	g_free(item->metadata.album);
-	g_free(item->metadata.genre);
-	g_free(item->path);
-	g_free(item);
+    if(mdev){
+        for(i = LMS_MIN_ID; i < LMS_SCAN_COUNT; ++i)
+        {
+            if(mdev->lists[i] != NULL) {
+                g_list_free_full(mdev->lists[i]->list,media_item_free);
+                g_free(mdev->lists[i]);
+            }
+        }
+        g_free(mdev->filters->scan_uri);
+        mdev->filters->scan_uri = NULL;
+        g_free(mdev);
+    }
 }
 
 static void
@@ -191,15 +207,13 @@ on_interface_proxy_properties_changed (GDBusProxy *proxy,
                                     GVariant *changed_properties,
                                     const gchar* const  *invalidated_properties)
 {
-    if(!(MediaPlayerManage.type_filter & LMS_ALL_SCAN))
-        return;
-
     GVariantIter iter;
     gchar *key = NULL;
     GVariant *subValue = NULL;
-    gchar *pInterface = NULL;
-    GList *list = NULL;
+    const gchar *pInterface;
+    ScanFilter_t *filter = &MediaPlayerManage.filters;
     gboolean br = FALSE;
+
     pInterface = g_dbus_proxy_get_interface_name (proxy);
 
     if (0 != g_strcmp0(pInterface, LIGHTMEDIASCANNER_INTERFACE))
@@ -219,33 +233,20 @@ on_interface_proxy_properties_changed (GDBusProxy *proxy,
                 br = TRUE;
         }
     }
-
     if(br)
         return;
 
-    ListLock();
-    if(MediaPlayerManage.type_filter & LMS_AUDIO_SCAN)
-        list = media_lightmediascanner_scan(list, MediaPlayerManage.uri_filter, LMS_AUDIO_SCAN);
-    if(MediaPlayerManage.type_filter & LMS_VIDEO_SCAN)
-        list = media_lightmediascanner_scan(list, MediaPlayerManage.uri_filter, LMS_VIDEO_SCAN);
-    if(MediaPlayerManage.type_filter & LMS_IMAGE_SCAN)
-        list = media_lightmediascanner_scan(list, MediaPlayerManage.uri_filter, LMS_IMAGE_SCAN);
-
-    g_free(MediaPlayerManage.uri_filter);
-    MediaPlayerManage.uri_filter = NULL;
-
-    if (list != NULL && g_RegisterCallback.binding_device_added)
-        g_RegisterCallback.binding_device_added(list);
-
-    g_list_free_full(list, free_media_item);
-
-    ListUnlock();
+    if (filter->scan_types &&
+        filter->scan_uri &&
+        g_RegisterCallback.binding_device_added)
+        g_RegisterCallback.binding_device_added(filter);
 }
 
 static int MediaPlayerDBusInit(void)
 {
     GError *error = NULL;
 
+    MediaPlayerManage.lms_proxy = NULL;
     MediaPlayerManage.lms_proxy = scanner1_proxy_new_for_bus_sync(
         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, LIGHTMEDIASCANNER_SERVICE,
         LIGHTMEDIASCANNER_PATH, NULL, &error);
@@ -288,7 +289,6 @@ unmount_cb (GFileMonitor      *mon,
     gint ret = 0;
 
     ListLock();
-
     if (g_RegisterCallback.binding_device_removed &&
         event == G_FILE_MONITOR_EVENT_DELETED) {
 
@@ -309,7 +309,7 @@ unmount_cb (GFileMonitor      *mon,
         }
         g_free(path);
     } else if (event == G_FILE_MONITOR_EVENT_CREATED) {
-        MediaPlayerManage.uri_filter = path;
+        MediaPlayerManage.filters.scan_uri = path;
     } else {
         g_free(path);
     }
@@ -348,7 +348,6 @@ int MediaPlayerManagerInit() {
     ret = MediaPlayerDBusInit();
     if (ret == 0)
         pthread_create(&thread_id, NULL, media_event_loop_thread, NULL);
-
     return ret;
 }
 
@@ -373,13 +372,62 @@ void BindingAPIRegister(const Binding_RegisterCallback_t* pstRegisterCallback)
     }
 }
 
+void setAPIMediaListView(gint view) {
+    MediaPlayerManage.filters.listview_type = view;
+}
+
 gint ScanTypeAppend(gint type)
 {
-    return MediaPlayerManage.type_filter |= (type & LMS_ALL_SCAN);
+    return MediaPlayerManage.filters.scan_types |= (type & LMS_ALL_SCAN);
 }
 
 gint ScanTypeRemove(gint type)
 {
-    MediaPlayerManage.type_filter = (MediaPlayerManage.type_filter & (~type)) & LMS_ALL_SCAN;
-    return MediaPlayerManage.type_filter;
+    MediaPlayerManage.filters.scan_types =
+        ( MediaPlayerManage.filters.scan_types & (~type)) & LMS_ALL_SCAN;
+    return MediaPlayerManage.filters.scan_types;
+}
+
+gint media_lists_get(MediaDevice_t* mdev, gchar **error)
+{
+    MediaList_t *mlist = NULL;
+    ScanFilter_t *filters = NULL;
+    gint ret = -1;
+    gint scaned_media = 0;
+    gint i = 0;
+
+    if(!mdev)
+    {
+        *error = g_strdup("'MediaDevice' object is NULL!");
+        return -1;
+    }
+    filters = mdev->filters;
+
+    for( i = LMS_MIN_ID; i < LMS_SCAN_COUNT; ++i)
+    {
+        if(filters->scan_types & (1 << i))
+        {
+            mlist = mdev->lists[i];
+            mlist->scan_type_str = lms_scan_types[i];
+            mlist->scan_type_id = i;
+
+            ret = media_lightmediascanner_scan(mlist,filters->scan_uri,error);
+            if(ret < 0){
+                return ret;
+            } else if(ret == 0){
+                free(mdev->lists[i]);
+                mdev->lists[i] = NULL;
+            } else {
+                scaned_media += ret;
+            }
+        }
+    }
+
+    if(scaned_media == 0)
+    {
+        *error = g_strdup("No media found!");
+        return -1;
+    }
+    LOGD("\n\tscanned media: %d\n",scaned_media);
+    return scaned_media;
 }
\ No newline at end of file
diff --git a/binding/media-manager.h b/binding/media-manager.h
index 65ee831..864e552 100644
--- a/binding/media-manager.h
+++ b/binding/media-manager.h
@@ -105,64 +105,86 @@ void DebugTraceSendMsg(int level, gchar* message);
                 "ORDER BY " \
                 "images.title"
 
+enum {
+    LMS_MIN_ID = 0,
+    LMS_AUDIO_ID = 0,
+    LMS_VIDEO_ID,
+    LMS_IMAGE_ID,
+    LMS_SCAN_COUNT
+};
+
+#define MEDIA_LIST_VIEW_DEFAULT  1u
+#define MEDIA_LIST_VIEW_CLUSTERD 2u
+
+#define LMS_AUDIO_SCAN (1 << LMS_AUDIO_ID)
+#define LMS_VIDEO_SCAN (1 << LMS_VIDEO_ID)
+#define LMS_IMAGE_SCAN (1 << LMS_IMAGE_ID)
+
+#define LMS_ALL_SCAN   ( LMS_AUDIO_SCAN | LMS_VIDEO_SCAN | LMS_IMAGE_SCAN )
+
+#define MEDIA_AUDIO "audio"
+#define MEDIA_VIDEO "video"
+#define MEDIA_IMAGE "image"
+#define MEDIA_ALL   "all"
+
+extern const char *lms_scan_types[LMS_SCAN_COUNT];
+
+#define SCAN_URI_DEFAULT NULL
+
 typedef struct {
-    GList *list;
-    gchar *uri_filter;
-    gint  type_filter;
+    gint listview_type;
+    gint scan_types;
+    gchar *scan_uri;
+}ScanFilter_t;
+
+typedef struct {
+    ScanFilter_t filters;
     GMutex m;
-    Scanner1 *lms_proxy;
     GFileMonitor *mon;
+    Scanner1 *lms_proxy;
 } stMediaPlayerManage;
 
+
+typedef struct {
+    gchar *path;
+    struct {
+        gchar *title;
+        gchar *artist;
+        gchar *album;
+        gchar *genre;
+        gint  duration;
+    } metadata;
+}MediaItem_t;
+
+typedef struct {
+    GList *list;
+    gchar* scan_type_str;
+    gint scan_type_id;
+} MediaList_t;
+
+typedef struct {
+    MediaList_t *lists[LMS_SCAN_COUNT];
+    ScanFilter_t *filters;
+} MediaDevice_t;
+
 typedef struct tagBinding_RegisterCallback
 {
-    void (*binding_device_added)(GList *list);
+    void (*binding_device_added)(ScanFilter_t *filters);
     void (*binding_device_removed)(const char *obj_path);
 } Binding_RegisterCallback_t;
 
 /* ------ PUBLIC PLUGIN FUNCTIONS --------- */
-void free_media_item(void *data);
 void BindingAPIRegister(const Binding_RegisterCallback_t* pstRegisterCallback);
 int MediaPlayerManagerInit(void);
 
 gint ScanTypeAppend(gint);
 gint ScanTypeRemove(gint);
+void setAPIMediaListView(gint view);
 
 void ListLock();
 void ListUnlock();
 
-GList* media_lightmediascanner_scan(GList *list, gchar *uri, int scan_type);
-
-struct Media_Item {
-    gchar *path;
-    gchar *type;
-    struct {
-        gchar *title;
-        gchar *artist;
-        gchar *album;
-        gchar *genre;
-        gint  duration;
-    } metadata;
-};
-
-enum {
-    LMS_AUDIO_ID,
-    LMS_VIDEO_ID,
-    LMS_IMAGE_ID,
-    LMS_SCAN_COUNT
-};
-
-#define LMS_AUDIO_SCAN (1 << LMS_AUDIO_ID)
-#define LMS_VIDEO_SCAN (1 << LMS_VIDEO_ID)
-#define LMS_IMAGE_SCAN (1 << LMS_IMAGE_ID)
-
-#define LMS_ALL_SCAN   ( LMS_AUDIO_SCAN | LMS_VIDEO_SCAN | LMS_IMAGE_SCAN )
+gint media_lists_get(MediaDevice_t* mdev, gchar **error);
+void media_device_free(MediaDevice_t *mdev);
 
-#define MEDIA_AUDIO "audio"
-#define MEDIA_VIDEO "video"
-#define MEDIA_IMAGE "image"
-#define MEDIA_ALL   "all"
-
-extern const char *lms_scan_types[LMS_SCAN_COUNT];
-
-#endif
+#endif
\ No newline at end of file
-- 
cgit