From e6dc2a5845ce9bdb07cdcbde305e064b9d1ce2e7 Mon Sep 17 00:00:00 2001 From: chme Date: Sat, 24 Nov 2018 12:15:31 +0100 Subject: [PATCH] [jsonapi] Add new endpoint "api/library/files" This endpoint allows traversing the directory tree of the local library. --- src/httpd_jsonapi.c | 152 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/src/httpd_jsonapi.c b/src/httpd_jsonapi.c index ae0e84ce..91d0cfa7 100644 --- a/src/httpd_jsonapi.c +++ b/src/httpd_jsonapi.c @@ -266,6 +266,24 @@ genre_to_json(const char *genre) return item; } +static json_object * +directory_to_json(struct directory_info *directory_info) +{ + json_object *item; + + if (directory_info == NULL) + { + return NULL; + } + + item = json_object_new_object(); + safe_json_add_string(item, "path", directory_info->path); +// json_object_object_add(item, "id", json_object_new_int(directory_info->id)); +// json_object_object_add(item, "parent_id", json_object_new_int(directory_info->parent_id)); + + return item; +} + static int fetch_tracks(struct query_params *query_params, json_object *items, int *total) @@ -529,6 +547,38 @@ fetch_genres(struct query_params *query_params, json_object *items, int *total) return ret; } +static int +fetch_directories(int parent_id, json_object *items) +{ + json_object *item; + int ret; + struct directory_info subdir; + struct directory_enum dir_enum; + + memset(&dir_enum, 0, sizeof(struct directory_enum)); + dir_enum.parent_id = parent_id; + ret = db_directory_enum_start(&dir_enum); + if (ret < 0) + goto error; + + while ((ret = db_directory_enum_fetch(&dir_enum, &subdir)) == 0 && subdir.id > 0) + { + item = directory_to_json(&subdir); + if (!item) + { + ret = -1; + goto error; + } + + json_object_array_add(items, item); + } + + error: + db_directory_enum_end(&dir_enum); + + return ret; +} + static int query_params_limit_set(struct query_params *query_params, struct httpd_request *hreq) @@ -2609,6 +2659,107 @@ jsonapi_reply_library_count(struct httpd_request *hreq) return HTTP_OK; } +static int +jsonapi_reply_library_files(struct httpd_request *hreq) +{ + const char *param; + int directory_id; + json_object *reply; + json_object *directories; + struct query_params query_params; + json_object *tracks; + json_object *tracks_items; + json_object *playlists; + json_object *playlists_items; + int total; + int ret; + + param = evhttp_find_header(hreq->query, "directory"); + + directory_id = DIR_FILE; + if (param) + { + directory_id = db_directory_id_bypath(param); + if (directory_id <= 0) + return HTTP_INTERNAL; + } + + reply = json_object_new_object(); + + // Add sub directories to response + directories = json_object_new_array(); + json_object_object_add(reply, "directories", directories); + + ret = fetch_directories(directory_id, directories); + if (ret < 0) + { + goto error; + } + + // Add tracks to response + tracks = json_object_new_object(); + json_object_object_add(reply, "tracks", tracks); + tracks_items = json_object_new_array(); + json_object_object_add(tracks, "items", tracks_items); + memset(&query_params, 0, sizeof(struct query_params)); + + ret = query_params_limit_set(&query_params, hreq); + if (ret < 0) + goto error; + + query_params.type = Q_ITEMS; + query_params.sort = S_NAME; + query_params.filter = db_mprintf("(f.directory_id = %d)", directory_id); + + ret = fetch_tracks(&query_params, tracks_items, &total); + free(query_params.filter); + + if (ret < 0) + goto error; + + json_object_object_add(tracks, "total", json_object_new_int(total)); + json_object_object_add(tracks, "offset", json_object_new_int(query_params.offset)); + json_object_object_add(tracks, "limit", json_object_new_int(query_params.limit)); + + // Add playlists + playlists = json_object_new_object(); + json_object_object_add(reply, "playlists", playlists); + playlists_items = json_object_new_array(); + json_object_object_add(playlists, "items", playlists_items); + memset(&query_params, 0, sizeof(struct query_params)); + + ret = query_params_limit_set(&query_params, hreq); + if (ret < 0) + goto error; + + query_params.type = Q_PL; + query_params.sort = S_PLAYLIST; + query_params.filter = db_mprintf("(f.directory_id = %d)", directory_id); + + ret = fetch_playlists(&query_params, playlists_items, &total); + free(query_params.filter); + + if (ret < 0) + goto error; + + json_object_object_add(playlists, "total", json_object_new_int(total)); + json_object_object_add(playlists, "offset", json_object_new_int(query_params.offset)); + json_object_object_add(playlists, "limit", json_object_new_int(query_params.limit)); + + // Build JSON response + ret = evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(reply)); + if (ret < 0) + DPRINTF(E_LOG, L_WEB, "browse: Couldn't add directories to response buffer.\n"); + + error: + jparse_free(reply); + + if (ret < 0) + return HTTP_INTERNAL; + + return HTTP_OK; +} + static int search_tracks(json_object *reply, struct httpd_request *hreq, const char *param_query, struct smartpl *smartpl_expression, enum media_kind media_kind) { @@ -2977,6 +3128,7 @@ static struct httpd_uri_map adm_handlers[] = { EVHTTP_REQ_GET, "^/api/library/albums/[[:digit:]]+/tracks$", jsonapi_reply_library_album_tracks }, { EVHTTP_REQ_GET, "^/api/library/genres$", jsonapi_reply_library_genres}, { EVHTTP_REQ_GET, "^/api/library/count$", jsonapi_reply_library_count }, + { EVHTTP_REQ_GET, "^/api/library/files$", jsonapi_reply_library_files }, { EVHTTP_REQ_GET, "^/api/search$", jsonapi_reply_search },