mirror of
https://github.com/owntone/owntone-server.git
synced 2025-03-20 12:34:18 -04:00
Merge branch 'whatdoineed2do-db-files-review-flag'
This commit is contained in:
commit
d6dc92359e
@ -791,7 +791,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/albums/{id}/tracks](#list-album-tracks) | Get list of tracks for an album |
|
||||||
| GET | [/api/library/tracks/{id}](#get-a-track) | Get a track |
|
| GET | [/api/library/tracks/{id}](#get-a-track) | Get a track |
|
||||||
| GET | [/api/library/tracks/{id}/playlists](#list-playlists-for-a-track) | Get list of playlists for a track |
|
| GET | [/api/library/tracks/{id}/playlists](#list-playlists-for-a-track) | Get list of playlists for a track |
|
||||||
| PUT | [/api/library/tracks/{id}](#update-track-properties) | Update a tracks properties (rating, play_count) |
|
| PUT | [/api/library/tracks/{id}](#update-track-properties) | Update track properties |
|
||||||
| GET | [/api/library/genres](#list-genres) | Get list of genres |
|
| 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/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/library/files](#list-local-directories) | Get list of directories in the local library |
|
||||||
@ -1528,6 +1528,7 @@ curl -X GET "http://localhost:3689/api/library/track/1"
|
|||||||
"disc_number": 1,
|
"disc_number": 1,
|
||||||
"length_ms": 223170,
|
"length_ms": 223170,
|
||||||
"rating": 0,
|
"rating": 0,
|
||||||
|
"usermark": 0,
|
||||||
"play_count": 0,
|
"play_count": 0,
|
||||||
"skip_count": 0,
|
"skip_count": 0,
|
||||||
"time_added": "2019-01-20T11:58:29Z",
|
"time_added": "2019-01-20T11:58:29Z",
|
||||||
@ -1601,7 +1602,7 @@ curl -X GET "http://localhost:3689/api/library/tracks/27/playlists"
|
|||||||
|
|
||||||
### Update track properties
|
### Update track properties
|
||||||
|
|
||||||
Change properties of a specific track (supported properties are "rating" and "play_count")
|
Change properties of a specific track (supported properties are "rating", "play_count" and "usermark")
|
||||||
|
|
||||||
**Endpoint**
|
**Endpoint**
|
||||||
|
|
||||||
@ -1621,6 +1622,7 @@ PUT /api/library/tracks/{id}
|
|||||||
| --------------- | ----------------------------------------------------------- |
|
| --------------- | ----------------------------------------------------------- |
|
||||||
| rating | The new rating (0 - 100) |
|
| rating | The new rating (0 - 100) |
|
||||||
| play_count | Either `increment` or `reset`. `increment` will increment `play_count` and update `time_played`, `reset` will set `play_count` and `skip_count` to zero and delete `time_played` and `time_skipped` |
|
| play_count | Either `increment` or `reset`. `increment` will increment `play_count` and update `time_played`, `reset` will set `play_count` and `skip_count` to zero and delete `time_played` and `time_skipped` |
|
||||||
|
| usermark | The new usermark (>= 0) |
|
||||||
|
|
||||||
|
|
||||||
**Response**
|
**Response**
|
||||||
@ -2565,6 +2567,7 @@ curl --include \
|
|||||||
| path | string | Path |
|
| path | string | Path |
|
||||||
| uri | string | Resource identifier |
|
| uri | string | Resource identifier |
|
||||||
| artwork_url | string | *(optional)* [Artwork url](#artwork-urls) |
|
| artwork_url | string | *(optional)* [Artwork url](#artwork-urls) |
|
||||||
|
| usermark | integer | User review marking of track (ranges from 0) |
|
||||||
|
|
||||||
|
|
||||||
### `paging` object
|
### `paging` object
|
||||||
|
@ -102,6 +102,7 @@ INTTAG : 'play_count'
|
|||||||
| 'bits_per_sample'
|
| 'bits_per_sample'
|
||||||
| 'samplerate'
|
| 'samplerate'
|
||||||
| 'song_length'
|
| 'song_length'
|
||||||
|
| 'usermark'
|
||||||
;
|
;
|
||||||
|
|
||||||
DATETAG : 'time_added'
|
DATETAG : 'time_added'
|
||||||
|
23
src/db.c
23
src/db.c
@ -227,6 +227,7 @@ static const struct col_type_map mfi_cols_map[] =
|
|||||||
{ "album_artist_sort", mfi_offsetof(album_artist_sort), DB_TYPE_STRING, DB_FIXUP_ALBUM_ARTIST_SORT },
|
{ "album_artist_sort", mfi_offsetof(album_artist_sort), DB_TYPE_STRING, DB_FIXUP_ALBUM_ARTIST_SORT },
|
||||||
{ "composer_sort", mfi_offsetof(composer_sort), DB_TYPE_STRING, DB_FIXUP_COMPOSER_SORT },
|
{ "composer_sort", mfi_offsetof(composer_sort), DB_TYPE_STRING, DB_FIXUP_COMPOSER_SORT },
|
||||||
{ "channels", mfi_offsetof(channels), DB_TYPE_INT },
|
{ "channels", mfi_offsetof(channels), DB_TYPE_INT },
|
||||||
|
{ "usermark", mfi_offsetof(usermark), DB_TYPE_INT },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This list must be kept in sync with
|
/* This list must be kept in sync with
|
||||||
@ -365,6 +366,7 @@ static const ssize_t dbmfi_cols_map[] =
|
|||||||
dbmfi_offsetof(album_artist_sort),
|
dbmfi_offsetof(album_artist_sort),
|
||||||
dbmfi_offsetof(composer_sort),
|
dbmfi_offsetof(composer_sort),
|
||||||
dbmfi_offsetof(channels),
|
dbmfi_offsetof(channels),
|
||||||
|
dbmfi_offsetof(usermark),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This list must be kept in sync with
|
/* This list must be kept in sync with
|
||||||
@ -3320,6 +3322,27 @@ db_file_rating_update_byvirtualpath(const char *virtual_path, uint32_t rating)
|
|||||||
#undef Q_TMPL
|
#undef Q_TMPL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
db_file_usermark_update_byid(uint32_t id, uint32_t usermark)
|
||||||
|
{
|
||||||
|
#define Q_TMPL "UPDATE files SET usermark = %d WHERE id = %d;"
|
||||||
|
char *query;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
query = sqlite3_mprintf(Q_TMPL, usermark, id);
|
||||||
|
|
||||||
|
ret = db_query_run(query, 1, 0);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
db_admin_setint64(DB_ADMIN_DB_MODIFIED, (int64_t) time(NULL));
|
||||||
|
listener_notify(LISTENER_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((ret < 0) ? -1 : sqlite3_changes(hdl));
|
||||||
|
#undef Q_TMPL
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
db_file_delete_bypath(const char *path)
|
db_file_delete_bypath(const char *path)
|
||||||
{
|
{
|
||||||
|
15
src/db.h
15
src/db.h
@ -141,6 +141,16 @@ enum data_kind {
|
|||||||
const char *
|
const char *
|
||||||
db_data_kind_label(enum data_kind data_kind);
|
db_data_kind_label(enum data_kind data_kind);
|
||||||
|
|
||||||
|
|
||||||
|
/* Indicates user marked status on a track - values can be bitwise enumerated */
|
||||||
|
enum usermark {
|
||||||
|
USERMARK_NA = 0,
|
||||||
|
USERMARK_DELETE = 1,
|
||||||
|
USERMARK_REXCODE = 2,
|
||||||
|
USERMARK_REVIEW = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Note that fields marked as integers in the metadata map in filescanner_ffmpeg must be uint32_t here */
|
/* Note that fields marked as integers in the metadata map in filescanner_ffmpeg must be uint32_t here */
|
||||||
struct media_file_info {
|
struct media_file_info {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
@ -198,6 +208,7 @@ struct media_file_info {
|
|||||||
uint32_t time_skipped;
|
uint32_t time_skipped;
|
||||||
|
|
||||||
int64_t disabled; // Long because it stores up to INOTIFY_FAKE_COOKIE
|
int64_t disabled; // Long because it stores up to INOTIFY_FAKE_COOKIE
|
||||||
|
uint32_t usermark; // See enum user_mark { }
|
||||||
|
|
||||||
uint64_t sample_count; //TODO [unused] sample count is never set and therefor always 0
|
uint64_t sample_count; //TODO [unused] sample count is never set and therefor always 0
|
||||||
char *codectype; /* song.codectype, 4 chars max (32 bits) */
|
char *codectype; /* song.codectype, 4 chars max (32 bits) */
|
||||||
@ -393,6 +404,7 @@ struct db_media_file_info {
|
|||||||
char *album_artist_sort;
|
char *album_artist_sort;
|
||||||
char *composer_sort;
|
char *composer_sort;
|
||||||
char *channels;
|
char *channels;
|
||||||
|
char *usermark;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define dbmfi_offsetof(field) offsetof(struct db_media_file_info, field)
|
#define dbmfi_offsetof(field) offsetof(struct db_media_file_info, field)
|
||||||
@ -651,6 +663,9 @@ db_file_seek_update(int id, uint32_t seek);
|
|||||||
int
|
int
|
||||||
db_file_rating_update_byid(uint32_t id, uint32_t rating);
|
db_file_rating_update_byid(uint32_t id, uint32_t rating);
|
||||||
|
|
||||||
|
int
|
||||||
|
db_file_usermark_update_byid(uint32_t id, uint32_t usermark);
|
||||||
|
|
||||||
int
|
int
|
||||||
db_file_rating_update_byvirtualpath(const char *virtual_path, uint32_t rating);
|
db_file_rating_update_byvirtualpath(const char *virtual_path, uint32_t rating);
|
||||||
|
|
||||||
|
@ -96,7 +96,8 @@
|
|||||||
" album_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
" album_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||||
" album_artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
" album_artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||||
" composer_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
" composer_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||||
" channels INTEGER DEFAULT 0" \
|
" channels INTEGER DEFAULT 0," \
|
||||||
|
" usermark INTEGER DEFAULT 0" \
|
||||||
");"
|
");"
|
||||||
|
|
||||||
#define T_PL \
|
#define T_PL \
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* is a major upgrade. In other words minor version upgrades permit downgrading
|
* is a major upgrade. In other words minor version upgrades permit downgrading
|
||||||
* the server after the database was upgraded. */
|
* the server after the database was upgraded. */
|
||||||
#define SCHEMA_VERSION_MAJOR 21
|
#define SCHEMA_VERSION_MAJOR 21
|
||||||
#define SCHEMA_VERSION_MINOR 06
|
#define SCHEMA_VERSION_MINOR 07
|
||||||
|
|
||||||
int
|
int
|
||||||
db_init_indices(sqlite3 *hdl);
|
db_init_indices(sqlite3 *hdl);
|
||||||
|
@ -1160,6 +1160,19 @@ static const struct db_upgrade_query db_upgrade_v2106_queries[] =
|
|||||||
{ U_v2106_SCVER_MINOR, "set schema_version_minor to 06" },
|
{ U_v2106_SCVER_MINOR, "set schema_version_minor to 06" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ---------------------------- 21.06 -> 21.07 ------------------------------ */
|
||||||
|
#define U_v2107_ALTER_FILES_USERMARK \
|
||||||
|
"ALTER TABLE files ADD COLUMN usermark INTEGER DEFAULT 0;"
|
||||||
|
#define U_v2107_SCVER_MINOR \
|
||||||
|
"UPDATE admin SET value = '07' WHERE key = 'schema_version_minor';"
|
||||||
|
|
||||||
|
static const struct db_upgrade_query db_upgrade_v2107_queries[] =
|
||||||
|
{
|
||||||
|
{ U_v2107_ALTER_FILES_USERMARK, "update files adding usermark" },
|
||||||
|
|
||||||
|
{ U_v2107_SCVER_MINOR, "set schema_version_minor to 07" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------- Main upgrade handler -------------------------- */
|
/* -------------------------- Main upgrade handler -------------------------- */
|
||||||
|
|
||||||
@ -1357,6 +1370,13 @@ db_upgrade(sqlite3 *hdl, int db_ver)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
case 2106:
|
||||||
|
ret = db_generic_upgrade(hdl, db_upgrade_v2107_queries, ARRAY_SIZE(db_upgrade_v2107_queries));
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
/* Last case statement is the only one that ends with a break statement! */
|
/* Last case statement is the only one that ends with a break statement! */
|
||||||
break;
|
break;
|
||||||
|
@ -311,6 +311,7 @@ track_to_json(struct db_media_file_info *dbmfi)
|
|||||||
safe_json_add_int_from_string(item, "samplerate", dbmfi->samplerate);
|
safe_json_add_int_from_string(item, "samplerate", dbmfi->samplerate);
|
||||||
safe_json_add_int_from_string(item, "bitrate", dbmfi->bitrate);
|
safe_json_add_int_from_string(item, "bitrate", dbmfi->bitrate);
|
||||||
safe_json_add_int_from_string(item, "channels", dbmfi->channels);
|
safe_json_add_int_from_string(item, "channels", dbmfi->channels);
|
||||||
|
safe_json_add_int_from_string(item, "usermark", dbmfi->usermark);
|
||||||
|
|
||||||
ret = safe_atoi32(dbmfi->media_kind, &intval);
|
ret = safe_atoi32(dbmfi->media_kind, &intval);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
@ -3297,14 +3298,13 @@ jsonapi_reply_library_tracks_put_byid(struct httpd_request *hreq)
|
|||||||
{
|
{
|
||||||
int track_id;
|
int track_id;
|
||||||
const char *param;
|
const char *param;
|
||||||
int val;
|
uint32_t val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = safe_atoi32(hreq->uri_parsed->path_parts[3], &track_id);
|
ret = safe_atoi32(hreq->uri_parsed->path_parts[3], &track_id);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return HTTP_INTERNAL;
|
return HTTP_INTERNAL;
|
||||||
|
|
||||||
// Update play_count/skip_count
|
|
||||||
param = evhttp_find_header(hreq->query, "play_count");
|
param = evhttp_find_header(hreq->query, "play_count");
|
||||||
if (param)
|
if (param)
|
||||||
{
|
{
|
||||||
@ -3319,22 +3319,37 @@ jsonapi_reply_library_tracks_put_byid(struct httpd_request *hreq)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_WEB, "Ignoring invalid play_count value '%s' for track '%d'.\n", param, track_id);
|
DPRINTF(E_WARN, L_WEB, "Ignoring invalid play_count value '%s' for track '%d'.\n", param, track_id);
|
||||||
|
return HTTP_BADREQUEST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update rating
|
|
||||||
param = evhttp_find_header(hreq->query, "rating");
|
param = evhttp_find_header(hreq->query, "rating");
|
||||||
if (param)
|
if (param)
|
||||||
{
|
{
|
||||||
ret = safe_atoi32(param, &val);
|
ret = safe_atou32(param, &val);
|
||||||
if (ret < 0)
|
if (ret < 0 || val > DB_FILES_RATING_MAX)
|
||||||
|
{
|
||||||
|
DPRINTF(E_WARN, L_WEB, "Invalid rating value '%s' for track '%d'.\n", param, track_id);
|
||||||
return HTTP_BADREQUEST;
|
return HTTP_BADREQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
if (val >= 0 && val <= DB_FILES_RATING_MAX)
|
|
||||||
ret = db_file_rating_update_byid(track_id, val);
|
ret = db_file_rating_update_byid(track_id, val);
|
||||||
else
|
if (ret < 0)
|
||||||
DPRINTF(E_WARN, L_WEB, "Ignoring invalid rating value '%d' for track '%d'.\n", val, track_id);
|
return HTTP_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retreive marked tracks via "/api/search?type=tracks&expression=usermark+=+1"
|
||||||
|
param = evhttp_find_header(hreq->query, "usermark");
|
||||||
|
if (param)
|
||||||
|
{
|
||||||
|
ret = safe_atou32(param, &val);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_WARN, L_WEB, "Invalid usermark value '%s' for track '%d'.\n", param, track_id);
|
||||||
|
return HTTP_BADREQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = db_file_usermark_update_byid(track_id, val);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return HTTP_INTERNAL;
|
return HTTP_INTERNAL;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user