mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-26 07:05:57 -05:00
Merge pull request #637 from chme/jsonapi_files
New JSON API endpoint for files view
This commit is contained in:
commit
0eae6d710c
@ -587,7 +587,12 @@ POST /api/queue/items/add
|
||||
|
||||
**Response**
|
||||
|
||||
On success returns the HTTP `204 No Content` success status response code.
|
||||
On success returns the HTTP `200 OK` success status response code.
|
||||
|
||||
| Key | Type | Value |
|
||||
| --------------- | -------- | ----------------------------------------- |
|
||||
| count | integer | number of tracks added to the queue |
|
||||
|
||||
|
||||
**Example**
|
||||
|
||||
@ -595,6 +600,12 @@ On success returns the HTTP `204 No Content` success status response code.
|
||||
curl -X POST "http://localhost:3689/api/queue/items/add?uris=library:playlist:68,library:artist:2932599850102967727"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"count": 42
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Moving a queue item
|
||||
|
||||
@ -673,6 +684,7 @@ curl -X PUT "http://localhost:3689/api/queue/items/2"
|
||||
| GET | [/api/library/albums/{id}/tracks](#list-album-tracks) | Get list of tracks for an album |
|
||||
| GET | [/api/library/genres](#list-genres) | Get list of genres |
|
||||
| GET | [/api/library/count](#get-count-of-tracks-artists-and-albums) | Get count of tracks, artists and albums |
|
||||
| GET | [/api/library/files](#list-local-directories) | Get list of directories in the local library |
|
||||
| GET | [/api/update](#trigger-rescan) | Trigger a library rescan |
|
||||
|
||||
|
||||
@ -1205,7 +1217,7 @@ curl -X GET "http://localhost:3689/api/library/albums/1/tracks"
|
||||
```
|
||||
|
||||
|
||||
### list genres
|
||||
### List genres
|
||||
|
||||
Get list of genres
|
||||
|
||||
@ -1377,6 +1389,105 @@ curl -X GET "http://localhost:3689/api/library/count?expression=data_kind+is+fil
|
||||
```
|
||||
|
||||
|
||||
### List local directories
|
||||
|
||||
List the local directories and the directory contents (tracks and playlists)
|
||||
|
||||
|
||||
**Endpoint**
|
||||
|
||||
```http
|
||||
GET /api/library/files
|
||||
```
|
||||
|
||||
**Query parameters**
|
||||
|
||||
| Parameter | Value |
|
||||
| --------------- | ----------------------------------------------------------- |
|
||||
| directory | *(Optional)* A path to a directory in your local library. |
|
||||
|
||||
**Response**
|
||||
|
||||
| Key | Type | Value |
|
||||
| --------------- | -------- | ----------------------------------------- |
|
||||
| directories | array | Array of [`directory`](#directory-object) objects containing the sub directories |
|
||||
| tracks | object | [`paging`](#paging-object) object containing [`track`](#track-object) objects that matches the `directory` |
|
||||
| playlists | object | [`paging`](#paging-object) object containing [`playlist`](#playlist-object) objects that matches the `directory` |
|
||||
|
||||
|
||||
**Example**
|
||||
|
||||
```shell
|
||||
curl -X GET "http://localhost:3689/api/library/files?directory=/music/srv"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"directories": [
|
||||
{
|
||||
"path": "/music/srv/Audiobooks"
|
||||
},
|
||||
{
|
||||
"path": "/music/srv/Music"
|
||||
},
|
||||
{
|
||||
"path": "/music/srv/Playlists"
|
||||
},
|
||||
{
|
||||
"path": "/music/srv/Podcasts"
|
||||
}
|
||||
],
|
||||
"tracks": {
|
||||
"items": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "input.pipe",
|
||||
"artist": "Unknown artist",
|
||||
"artist_sort": "Unknown artist",
|
||||
"album": "Unknown album",
|
||||
"album_sort": "Unknown album",
|
||||
"album_id": "4201163758598356043",
|
||||
"album_artist": "Unknown artist",
|
||||
"album_artist_sort": "Unknown artist",
|
||||
"album_artist_id": "4187901437947843388",
|
||||
"genre": "Unknown genre",
|
||||
"year": 0,
|
||||
"track_number": 0,
|
||||
"disc_number": 0,
|
||||
"length_ms": 0,
|
||||
"play_count": 0,
|
||||
"skip_count": 0,
|
||||
"time_added": "2018-11-24T08:41:35Z",
|
||||
"seek_ms": 0,
|
||||
"media_kind": "music",
|
||||
"data_kind": "pipe",
|
||||
"path": "/music/srv/input.pipe",
|
||||
"uri": "library:track:1",
|
||||
"artwork_url": "/artwork/item/1"
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"offset": 0,
|
||||
"limit": -1
|
||||
},
|
||||
"playlists": {
|
||||
"items": [
|
||||
{
|
||||
"id": 8,
|
||||
"name": "radio",
|
||||
"path": "/music/srv/radio.m3u",
|
||||
"smart_playlist": true,
|
||||
"uri": "library:playlist:8"
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"offset": 0,
|
||||
"limit": -1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Trigger rescan
|
||||
|
||||
Trigger a library rescan
|
||||
@ -1774,6 +1885,7 @@ curl --include \
|
||||
| ------------------ | -------- | ----------------------------------------- |
|
||||
| id | string | Track id |
|
||||
| title | string | Title |
|
||||
| title_sort | string | Sort title |
|
||||
| artist | string | Track artist name |
|
||||
| artist_sort | string | Track artist sort name |
|
||||
| album | string | Album name |
|
||||
@ -1788,8 +1900,11 @@ curl --include \
|
||||
| track_number | integer | Track number |
|
||||
| disc_number | integer | Disc number |
|
||||
| length_ms | integer | Track length in milliseconds |
|
||||
| rating | integer | Track rating (ranges from 0 to 100) |
|
||||
| play_count | integer | How many times the track was played |
|
||||
| skip_count | integer | How many times the track was skipped |
|
||||
| time_played | string | Timestamp in `ISO 8601` format |
|
||||
| time_skipped | string | Timestamp in `ISO 8601` format |
|
||||
| time_added | string | Timestamp in `ISO 8601` format |
|
||||
| date_released | string | Date in the format `yyyy-mm-dd` |
|
||||
| seek_ms | integer | Resume point in milliseconds (available only for podcasts and audiobooks) |
|
||||
@ -1817,6 +1932,12 @@ curl --include \
|
||||
| name | string | Name of genre |
|
||||
|
||||
|
||||
### `directory` object
|
||||
|
||||
| Key | Type | Value |
|
||||
| --------------- | -------- | ----------------------------------------- |
|
||||
| path | string | Directory path |
|
||||
|
||||
|
||||
### Artwork urls
|
||||
|
||||
@ -1825,4 +1946,4 @@ Absolute artwork urls are pointing to external artwork images (e. g. for radio s
|
||||
|
||||
It is possible to add the query parameters `maxwidth` and/or `maxheight` to relative artwork urls, in order to get a smaller image (forked-daapd only scales down never up).
|
||||
|
||||
Note that even if a relative artwork url attribute is present, it is not guaranteed to exist.
|
||||
Note that even if a relative artwork url attribute is present, it is not guaranteed to exist.
|
||||
|
40
src/db.c
40
src/db.c
@ -3850,7 +3850,7 @@ db_group_persistentid_byid(int id, int64_t *persistentid)
|
||||
|
||||
/* Directories */
|
||||
int
|
||||
db_directory_id_byvirtualpath(char *virtual_path)
|
||||
db_directory_id_byvirtualpath(const char *virtual_path)
|
||||
{
|
||||
#define Q_TMPL "SELECT d.id FROM directories d WHERE d.virtual_path = '%q';"
|
||||
char *query;
|
||||
@ -3873,6 +3873,30 @@ db_directory_id_byvirtualpath(char *virtual_path)
|
||||
#undef Q_TMPL
|
||||
}
|
||||
|
||||
int
|
||||
db_directory_id_bypath(const char *path)
|
||||
{
|
||||
#define Q_TMPL "SELECT d.id FROM directories d WHERE d.path = '%q';"
|
||||
char *query;
|
||||
int ret;
|
||||
|
||||
query = sqlite3_mprintf(Q_TMPL, path);
|
||||
if (!query)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = db_file_id_byquery(query);
|
||||
|
||||
sqlite3_free(query);
|
||||
|
||||
return ret;
|
||||
|
||||
#undef Q_TMPL
|
||||
}
|
||||
|
||||
int
|
||||
db_directory_enum_start(struct directory_enum *de)
|
||||
{
|
||||
@ -3944,6 +3968,7 @@ db_directory_enum_fetch(struct directory_enum *de, struct directory_info *di)
|
||||
disabled = sqlite3_column_int64(de->stmt, 3);
|
||||
di->disabled = (disabled != 0);
|
||||
di->parent_id = sqlite3_column_int(de->stmt, 4);
|
||||
di->path = (char *)sqlite3_column_text(de->stmt, 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3961,8 +3986,8 @@ db_directory_enum_end(struct directory_enum *de)
|
||||
static int
|
||||
db_directory_add(struct directory_info *di, int *id)
|
||||
{
|
||||
#define QADD_TMPL "INSERT INTO directories (virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (TRIM(%Q), %d, %d, %d);"
|
||||
#define QADD_TMPL "INSERT INTO directories (virtual_path, db_timestamp, disabled, parent_id, path)" \
|
||||
" VALUES (TRIM(%Q), %d, %d, %d, TRIM(%Q));"
|
||||
|
||||
char *query;
|
||||
char *errmsg;
|
||||
@ -3977,7 +4002,7 @@ db_directory_add(struct directory_info *di, int *id)
|
||||
DPRINTF(E_LOG, L_DB, "Directory name ends with space: '%s'\n", di->virtual_path);
|
||||
}
|
||||
|
||||
query = sqlite3_mprintf(QADD_TMPL, di->virtual_path, di->db_timestamp, di->disabled, di->parent_id);
|
||||
query = sqlite3_mprintf(QADD_TMPL, di->virtual_path, di->db_timestamp, di->disabled, di->parent_id, di->path);
|
||||
|
||||
if (!query)
|
||||
{
|
||||
@ -4016,14 +4041,14 @@ db_directory_add(struct directory_info *di, int *id)
|
||||
static int
|
||||
db_directory_update(struct directory_info *di)
|
||||
{
|
||||
#define QADD_TMPL "UPDATE directories SET virtual_path = TRIM(%Q), db_timestamp = %d, disabled = %d, parent_id = %d" \
|
||||
#define QADD_TMPL "UPDATE directories SET virtual_path = TRIM(%Q), db_timestamp = %d, disabled = %d, parent_id = %d, path = TRIM(%Q)" \
|
||||
" WHERE id = %d;"
|
||||
char *query;
|
||||
char *errmsg;
|
||||
int ret;
|
||||
|
||||
/* Add */
|
||||
query = sqlite3_mprintf(QADD_TMPL, di->virtual_path, di->db_timestamp, di->disabled, di->parent_id, di->id);
|
||||
query = sqlite3_mprintf(QADD_TMPL, di->virtual_path, di->db_timestamp, di->disabled, di->parent_id, di->path, di->id);
|
||||
|
||||
if (!query)
|
||||
{
|
||||
@ -4053,7 +4078,7 @@ db_directory_update(struct directory_info *di)
|
||||
}
|
||||
|
||||
int
|
||||
db_directory_addorupdate(char *virtual_path, int disabled, int parent_id)
|
||||
db_directory_addorupdate(char *virtual_path, char *path, int disabled, int parent_id)
|
||||
{
|
||||
struct directory_info di;
|
||||
int id;
|
||||
@ -4064,6 +4089,7 @@ db_directory_addorupdate(char *virtual_path, int disabled, int parent_id)
|
||||
di.id = id;
|
||||
di.parent_id = parent_id;
|
||||
di.virtual_path = virtual_path;
|
||||
di.path = path;
|
||||
di.disabled = disabled;
|
||||
di.db_timestamp = (uint64_t)time(NULL);
|
||||
|
||||
|
8
src/db.h
8
src/db.h
@ -412,6 +412,7 @@ enum directory_ids {
|
||||
struct directory_info {
|
||||
uint32_t id;
|
||||
char *virtual_path;
|
||||
char *path;
|
||||
uint32_t db_timestamp;
|
||||
uint32_t disabled;
|
||||
uint32_t parent_id;
|
||||
@ -698,7 +699,10 @@ db_group_persistentid_byid(int id, int64_t *persistentid);
|
||||
|
||||
/* Directories */
|
||||
int
|
||||
db_directory_id_byvirtualpath(char *virtual_path);
|
||||
db_directory_id_byvirtualpath(const char *virtual_path);
|
||||
|
||||
int
|
||||
db_directory_id_bypath(const char *path);
|
||||
|
||||
int
|
||||
db_directory_enum_start(struct directory_enum *de);
|
||||
@ -710,7 +714,7 @@ void
|
||||
db_directory_enum_end(struct directory_enum *de);
|
||||
|
||||
int
|
||||
db_directory_addorupdate(char *virtual_path, int disabled, int parent_id);
|
||||
db_directory_addorupdate(char *virtual_path, char *path, int disabled, int parent_id);
|
||||
|
||||
void
|
||||
db_directory_ping_bymatch(char *virtual_path);
|
||||
|
@ -161,7 +161,8 @@
|
||||
" virtual_path VARCHAR(4096) NOT NULL," \
|
||||
" db_timestamp INTEGER DEFAULT 0," \
|
||||
" disabled INTEGER DEFAULT 0," \
|
||||
" parent_id INTEGER DEFAULT 0" \
|
||||
" parent_id INTEGER DEFAULT 0," \
|
||||
" path VARCHAR(4096) DEFAULT NULL" \
|
||||
");"
|
||||
|
||||
#define T_QUEUE \
|
||||
@ -239,17 +240,17 @@
|
||||
|
||||
|
||||
#define Q_DIR1 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (1, '/', 0, 0, 0);"
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id, path)" \
|
||||
" VALUES (1, '/', 0, 0, 0, NULL);"
|
||||
#define Q_DIR2 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (2, '/file:', 0, 0, 1);"
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id, path)" \
|
||||
" VALUES (2, '/file:', 0, 0, 1, '/');"
|
||||
#define Q_DIR3 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (3, '/http:', 0, 0, 1);"
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id, path)" \
|
||||
" VALUES (3, '/http:', 0, 0, 1, NULL);"
|
||||
#define Q_DIR4 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (4, '/spotify:', 0, 4294967296, 1);"
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id, path)" \
|
||||
" VALUES (4, '/spotify:', 0, 4294967296, 1, NULL);"
|
||||
|
||||
#define Q_QUEUE_VERSION \
|
||||
"INSERT INTO admin (key, value) VALUES ('queue_version', '0');"
|
||||
|
@ -26,7 +26,7 @@
|
||||
* is a major upgrade. In other words minor version upgrades permit downgrading
|
||||
* forked-daapd after the database was upgraded. */
|
||||
#define SCHEMA_VERSION_MAJOR 19
|
||||
#define SCHEMA_VERSION_MINOR 11
|
||||
#define SCHEMA_VERSION_MINOR 12
|
||||
|
||||
int
|
||||
db_init_indices(sqlite3 *hdl);
|
||||
|
@ -1698,6 +1698,27 @@ static const struct db_upgrade_query db_upgrade_v1911_queries[] =
|
||||
};
|
||||
|
||||
|
||||
#define U_V1912_ALTER_DIRECTORIES_ADD_PATH \
|
||||
"ALTER TABLE directories ADD COLUMN path VARCHAR(4096) DEFAULT NULL;"
|
||||
|
||||
#define U_V1912_UPDATE_FILE_DIRECTORIES_PATH \
|
||||
"UPDATE directories SET path = SUBSTR(path, 7) WHERE virtual_path like '/file:/%';"
|
||||
#define U_V1912_UPDATE_FILE_ROOT_PATH \
|
||||
"UPDATE directories SET path = '/' WHERE virtual_path = '/file:';"
|
||||
|
||||
#define U_V1912_SCVER_MINOR \
|
||||
"UPDATE admin SET value = '12' WHERE key = 'schema_version_minor';"
|
||||
|
||||
static const struct db_upgrade_query db_upgrade_v1912_queries[] =
|
||||
{
|
||||
{ U_V1912_ALTER_DIRECTORIES_ADD_PATH, "alter table directories add column path" },
|
||||
{ U_V1912_UPDATE_FILE_DIRECTORIES_PATH, "set paths for '/file:' directories" },
|
||||
{ U_V1912_UPDATE_FILE_ROOT_PATH, "set path for '/file:' directory" },
|
||||
|
||||
{ U_V1912_SCVER_MINOR, "set schema_version_minor to 12" },
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
db_upgrade(sqlite3 *hdl, int db_ver)
|
||||
{
|
||||
@ -1884,6 +1905,14 @@ db_upgrade(sqlite3 *hdl, int db_ver)
|
||||
ret = db_generic_upgrade(hdl, db_upgrade_v1911_queries, ARRAY_SIZE(db_upgrade_v1911_queries));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 1911:
|
||||
ret = db_generic_upgrade(hdl, db_upgrade_v1912_queries, ARRAY_SIZE(db_upgrade_v1912_queries));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -182,6 +182,7 @@ track_to_json(struct db_media_file_info *dbmfi)
|
||||
|
||||
safe_json_add_int_from_string(item, "id", dbmfi->id);
|
||||
safe_json_add_string(item, "title", dbmfi->title);
|
||||
safe_json_add_string(item, "title_sort", dbmfi->title_sort);
|
||||
safe_json_add_string(item, "artist", dbmfi->artist);
|
||||
safe_json_add_string(item, "artist_sort", dbmfi->artist_sort);
|
||||
safe_json_add_string(item, "album", dbmfi->album);
|
||||
@ -197,6 +198,7 @@ track_to_json(struct db_media_file_info *dbmfi)
|
||||
safe_json_add_int_from_string(item, "disc_number", dbmfi->disc);
|
||||
safe_json_add_int_from_string(item, "length_ms", dbmfi->song_length);
|
||||
|
||||
safe_json_add_int_from_string(item, "rating", dbmfi->rating);
|
||||
safe_json_add_int_from_string(item, "play_count", dbmfi->play_count);
|
||||
safe_json_add_int_from_string(item, "skip_count", dbmfi->skip_count);
|
||||
safe_json_add_time_from_string(item, "time_played", dbmfi->time_played, true);
|
||||
@ -266,6 +268,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 +549,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)
|
||||
@ -1275,6 +1327,7 @@ static int
|
||||
play_item_at_position(const char *param)
|
||||
{
|
||||
uint32_t position;
|
||||
struct player_status status;
|
||||
struct db_queue_item *queue_item;
|
||||
int ret;
|
||||
|
||||
@ -1286,7 +1339,9 @@ play_item_at_position(const char *param)
|
||||
return HTTP_BADREQUEST;
|
||||
}
|
||||
|
||||
queue_item = db_queue_fetch_bypos(position, 0);
|
||||
player_get_status(&status);
|
||||
|
||||
queue_item = db_queue_fetch_bypos(position, status.shuffle);
|
||||
if (!queue_item)
|
||||
{
|
||||
DPRINTF(E_LOG, L_WEB, "No queue item at position '%d'\n", position);
|
||||
@ -1690,6 +1745,7 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq)
|
||||
const char *id;
|
||||
int pos = -1;
|
||||
int count = 0;
|
||||
json_object *reply;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
@ -1759,10 +1815,19 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq)
|
||||
|
||||
free(uris);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
reply = json_object_new_object();
|
||||
json_object_object_add(reply, "count", json_object_new_int(count));
|
||||
|
||||
ret = evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(reply));
|
||||
jparse_free(reply);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return HTTP_INTERNAL;
|
||||
|
||||
return HTTP_NOCONTENT;
|
||||
return HTTP_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2609,6 +2674,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 +3143,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 },
|
||||
|
||||
|
@ -749,7 +749,7 @@ process_directory(char *path, int parent_id, int flags)
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
dir_id = db_directory_addorupdate(virtual_path, 0, parent_id);
|
||||
dir_id = db_directory_addorupdate(virtual_path, path, 0, parent_id);
|
||||
if (dir_id <= 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SCAN, "Insert or update of directory failed '%s'\n", virtual_path);
|
||||
@ -876,7 +876,7 @@ process_parent_directories(char *path)
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
dir_id = db_directory_addorupdate(virtual_path, 0, dir_id);
|
||||
dir_id = db_directory_addorupdate(virtual_path, buf, 0, dir_id);
|
||||
if (dir_id <= 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SCAN, "Insert or update of directory failed '%s'\n", virtual_path);
|
||||
|
@ -1250,7 +1250,7 @@ prepare_directories(const char *artist, const char *album)
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Virtual path exceeds PATH_MAX (/spotify:/%s)\n", artist);
|
||||
return -1;
|
||||
}
|
||||
dir_id = db_directory_addorupdate(virtual_path, 0, DIR_SPOTIFY);
|
||||
dir_id = db_directory_addorupdate(virtual_path, NULL, 0, DIR_SPOTIFY);
|
||||
if (dir_id <= 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not add or update directory '%s'\n", virtual_path);
|
||||
@ -1262,7 +1262,7 @@ prepare_directories(const char *artist, const char *album)
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Virtual path exceeds PATH_MAX (/spotify:/%s/%s)\n", artist, album);
|
||||
return -1;
|
||||
}
|
||||
dir_id = db_directory_addorupdate(virtual_path, 0, dir_id);
|
||||
dir_id = db_directory_addorupdate(virtual_path, NULL, 0, dir_id);
|
||||
if (dir_id <= 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not add or update directory '%s'\n", virtual_path);
|
||||
|
Loading…
Reference in New Issue
Block a user