diff --git a/docs/json-api.md b/docs/json-api.md index 9ec50279da..7107a29c83 100644 --- a/docs/json-api.md +++ b/docs/json-api.md @@ -2037,12 +2037,12 @@ curl -X PUT "http://localhost:3689/api/library/backup" | Method | Endpoint | Description | | --------- | ----------------------------------------------------------- | ------------------------------------ | -| GET | [/api/search](#search-by-search-term) | Search for playlists, artists, albums, tracks, composers by a simple search term | +| GET | [/api/search](#search-by-search-term) | Search for playlists, artists, albums, tracks, genres, composers by a simple search term | | GET | [/api/search](#search-by-query-language) | Search by complex query expression | ### Search by search term -Search for playlists, artists, albums, tracks, composers that include the given query in their title (case insensitive matching). +Search for playlists, artists, albums, tracks, genres, composers that include the given query in their title (case insensitive matching). **Endpoint** @@ -2055,7 +2055,7 @@ GET /api/search | Parameter | Value | | --------------- | ----------------------------------------------------------- | | query | The search keyword | -| type | Comma separated list of the result types (`playlist`, `artist`, `album`, `track`, `composers`) | +| type | Comma separated list of the result types (`playlist`, `artist`, `album`, `track`, `genres`, `composers`) | | media_kind | *(Optional)* Filter results by media kind (`music`, `movie`, `podcast`, `audiobook`, `musicvideo`, `tvshow`). Filter only applies to artist, album and track result types. | | offset | *(Optional)* Offset of the first item to return for each type | | limit | *(Optional)* Maximum number of items to return for each type | @@ -2064,11 +2064,12 @@ GET /api/search | Key | Type | Value | | --------------- | -------- | ----------------------------------------- | -| tracks | object | [`paging`](#paging-object) object containing [`track`](#track-object) objects that matches the `query` | -| artists | object | [`paging`](#paging-object) object containing [`artist`](#artist-object) objects that matches the `query` | -| albums | object | [`paging`](#paging-object) object containing [`album`](#album-object) objects that matches the `query` | -| playlists | object | [`paging`](#paging-object) object containing [`playlist`](#playlist-object) objects that matches the `query` | -| composers | object | [`paging`](#paging-object) object containing `composers` objects that matches the `query` | +| tracks | object | [`paging`](#paging-object) object containing [`track`](#track-object) objects that match the `query` | +| artists | object | [`paging`](#paging-object) object containing [`artist`](#artist-object) objects that match the `query` | +| albums | object | [`paging`](#paging-object) object containing [`album`](#album-object) objects that match the `query` | +| playlists | object | [`paging`](#paging-object) object containing [`playlist`](#playlist-object) objects that match the `query` | +| genres | object | [`paging`](#paging-object) object containing [`browse-info`](#browse-info-object) objects that match the `query` | +| composers | object | [`paging`](#paging-object) object containing [`browse-info`](#browse-info-object) objects that match the `query` | **Example** diff --git a/src/httpd_jsonapi.c b/src/httpd_jsonapi.c index d38562be37..4626c5283c 100644 --- a/src/httpd_jsonapi.c +++ b/src/httpd_jsonapi.c @@ -4326,6 +4326,68 @@ search_composers(json_object *reply, struct httpd_request *hreq, const char *par return ret; } +static int +search_genres(json_object *reply, struct httpd_request *hreq, const char *param_query, struct smartpl *smartpl_expression, enum media_kind media_kind) +{ + json_object *type; + json_object *items; + struct query_params query_params; + int total; + int ret; + + memset(&query_params, 0, sizeof(struct query_params)); + + ret = query_params_limit_set(&query_params, hreq); + if (ret < 0) + goto out; + + type = json_object_new_object(); + json_object_object_add(reply, "genres", type); + items = json_object_new_array(); + json_object_object_add(type, "items", items); + + query_params.type = Q_BROWSE_GENRES; + query_params.sort = S_GENRE; + + ret = query_params_limit_set(&query_params, hreq); + if (ret < 0) + goto out; + + if (param_query) + { + if (media_kind) + query_params.filter = db_mprintf("(f.genre LIKE '%%%q%%' AND f.media_kind = %d)", param_query, media_kind); + else + query_params.filter = db_mprintf("(f.genre LIKE '%%%q%%')", param_query); + } + else + { + query_params.filter = strdup(smartpl_expression->query_where); + query_params.having = safe_strdup(smartpl_expression->having); + query_params.order = safe_strdup(smartpl_expression->order); + + if (smartpl_expression->limit > 0) + { + query_params.idx_type = I_SUB; + query_params.limit = smartpl_expression->limit; + query_params.offset = 0; + } + } + + ret = fetch_browse_info(&query_params, items, &total); + if (ret < 0) + goto out; + + json_object_object_add(type, "total", json_object_new_int(total)); + json_object_object_add(type, "offset", json_object_new_int(query_params.offset)); + json_object_object_add(type, "limit", json_object_new_int(query_params.limit)); + + out: + free_query_params(&query_params, 1); + + return ret; +} + static int search_playlists(json_object *reply, struct httpd_request *hreq, const char *param_query) { @@ -4448,6 +4510,13 @@ jsonapi_reply_search(struct httpd_request *hreq) goto error; } + if (strstr(param_type, "genre")) + { + ret = search_genres(reply, hreq, param_query, &smartpl_expression, media_kind); + if (ret < 0) + goto error; + } + if (strstr(param_type, "playlist") && param_query) { ret = search_playlists(reply, hreq, param_query);