Skip to content

Commit

Permalink
[jsonapi] Support /api/search?type=genre like type=composers is suppo…
Browse files Browse the repository at this point in the history
…rted

Ref. #1735
  • Loading branch information
ejurgensen committed Mar 30, 2024
1 parent 39f5df8 commit 3e7e03b
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 8 deletions.
17 changes: 9 additions & 8 deletions docs/json-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**

Expand All @@ -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 |
Expand All @@ -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**

Expand Down
69 changes: 69 additions & 0 deletions src/httpd_jsonapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 3e7e03b

Please sign in to comment.