mirror of
https://github.com/owntone/owntone-server.git
synced 2025-03-31 09:43:45 -04:00
Change db_pl_add/db_pl_update so input is playlist struct
- so they work like db_file_add/update and can accept all the struct data (incl. parent_id)
This commit is contained in:
parent
9fdb8a5247
commit
e68c6c4932
38
src/db.c
38
src/db.c
@ -158,8 +158,8 @@ static const struct col_type_map pli_cols_map[] =
|
|||||||
{ pli_offsetof(path), DB_TYPE_STRING },
|
{ pli_offsetof(path), DB_TYPE_STRING },
|
||||||
{ pli_offsetof(index), DB_TYPE_INT },
|
{ pli_offsetof(index), DB_TYPE_INT },
|
||||||
{ pli_offsetof(special_id), DB_TYPE_INT },
|
{ pli_offsetof(special_id), DB_TYPE_INT },
|
||||||
{ pli_offsetof(virtual_path), DB_TYPE_STRING },
|
|
||||||
{ pli_offsetof(parent_id), DB_TYPE_INT },
|
{ pli_offsetof(parent_id), DB_TYPE_INT },
|
||||||
|
{ pli_offsetof(virtual_path), DB_TYPE_STRING },
|
||||||
|
|
||||||
/* items is computed on the fly */
|
/* items is computed on the fly */
|
||||||
};
|
};
|
||||||
@ -245,8 +245,8 @@ static const ssize_t dbpli_cols_map[] =
|
|||||||
dbpli_offsetof(path),
|
dbpli_offsetof(path),
|
||||||
dbpli_offsetof(index),
|
dbpli_offsetof(index),
|
||||||
dbpli_offsetof(special_id),
|
dbpli_offsetof(special_id),
|
||||||
dbpli_offsetof(virtual_path),
|
|
||||||
dbpli_offsetof(parent_id),
|
dbpli_offsetof(parent_id),
|
||||||
|
dbpli_offsetof(virtual_path),
|
||||||
|
|
||||||
/* items is computed on the fly */
|
/* items is computed on the fly */
|
||||||
};
|
};
|
||||||
@ -3127,17 +3127,17 @@ db_pl_fetch_bytitlepath(char *title, char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
db_pl_add(char *title, char *path, char *virtual_path, int *id)
|
db_pl_add(struct playlist_info *pli, int *id)
|
||||||
{
|
{
|
||||||
#define QDUP_TMPL "SELECT COUNT(*) FROM playlists p WHERE p.title = '%q' AND p.path = '%q';"
|
#define QDUP_TMPL "SELECT COUNT(*) FROM playlists p WHERE p.title = TRIM(%Q) AND p.path = '%q';"
|
||||||
#define QADD_TMPL "INSERT INTO playlists (title, type, query, db_timestamp, disabled, path, idx, special_id, virtual_path)" \
|
#define QADD_TMPL "INSERT INTO playlists (title, type, query, db_timestamp, disabled, path, idx, special_id, parent_id, virtual_path)" \
|
||||||
" VALUES ('%q', 0, NULL, %" PRIi64 ", 0, '%q', 0, 0, '%q');"
|
" VALUES (TRIM(%Q), %d, NULL, %" PRIi64 ", %d, '%q', %d, %d, %d, '%q');"
|
||||||
char *query;
|
char *query;
|
||||||
char *errmsg;
|
char *errmsg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Check duplicates */
|
/* Check duplicates */
|
||||||
query = sqlite3_mprintf(QDUP_TMPL, title, path);
|
query = sqlite3_mprintf(QDUP_TMPL, pli->title, STR(pli->path));
|
||||||
if (!query)
|
if (!query)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
||||||
@ -3150,12 +3150,15 @@ db_pl_add(char *title, char *path, char *virtual_path, int *id)
|
|||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_DB, "Duplicate playlist with title '%s' path '%s'\n", title, path);
|
DPRINTF(E_WARN, L_DB, "Duplicate playlist with title '%s' path '%s'\n", pli->title, pli->path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add */
|
/* Add */
|
||||||
query = sqlite3_mprintf(QADD_TMPL, title, (int64_t)time(NULL), path, virtual_path);
|
query = sqlite3_mprintf(QADD_TMPL,
|
||||||
|
pli->title, pli->type, (int64_t)time(NULL), pli->disabled, STR(pli->path),
|
||||||
|
pli->index, pli->special_id, pli->parent_id, pli->virtual_path);
|
||||||
|
|
||||||
if (!query)
|
if (!query)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
||||||
@ -3183,7 +3186,7 @@ db_pl_add(char *title, char *path, char *virtual_path, int *id)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_DB, "Added playlist %s (path %s) with id %d\n", title, path, *id);
|
DPRINTF(E_DBG, L_DB, "Added playlist %s (path %s) with id %d\n", pli->title, pli->path, *id);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -3216,13 +3219,17 @@ db_pl_add_item_byid(int plid, int fileid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
db_pl_update(char *title, char *path, char *virtual_path, int id)
|
db_pl_update(struct playlist_info *pli)
|
||||||
{
|
{
|
||||||
#define Q_TMPL "UPDATE playlists SET title = '%q', db_timestamp = %" PRIi64 ", disabled = 0, path = '%q', virtual_path = '%q' WHERE id = %d;"
|
#define Q_TMPL "UPDATE playlists SET title = TRIM(%Q), type = %d, db_timestamp = %" PRIi64 ", disabled = %d, path = '%q', " \
|
||||||
|
" idx = %d, special_id = %d, parent_id = %d, virtual_path = '%q' " \
|
||||||
|
" WHERE id = %d;"
|
||||||
char *query;
|
char *query;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
query = sqlite3_mprintf(Q_TMPL, title, (int64_t)time(NULL), path, virtual_path, id);
|
query = sqlite3_mprintf(Q_TMPL,
|
||||||
|
pli->title, pli->type, (int64_t)time(NULL), pli->disabled, STR(pli->path),
|
||||||
|
pli->index, pli->special_id, pli->parent_id, pli->virtual_path, pli->id);
|
||||||
|
|
||||||
ret = db_query_run(query, 1, 0);
|
ret = db_query_run(query, 1, 0);
|
||||||
|
|
||||||
@ -4507,8 +4514,8 @@ db_perthread_deinit(void)
|
|||||||
" path VARCHAR(4096)," \
|
" path VARCHAR(4096)," \
|
||||||
" idx INTEGER NOT NULL," \
|
" idx INTEGER NOT NULL," \
|
||||||
" special_id INTEGER DEFAULT 0," \
|
" special_id INTEGER DEFAULT 0," \
|
||||||
" virtual_path VARCHAR(4096)," \
|
" parent_id INTEGER DEFAULT 0," \
|
||||||
" parent_id INTEGER DEFAULT 0" \
|
" virtual_path VARCHAR(4096)" \
|
||||||
");"
|
");"
|
||||||
|
|
||||||
#define T_PLITEMS \
|
#define T_PLITEMS \
|
||||||
@ -4638,7 +4645,6 @@ static const struct db_init_query db_init_table_queries[] =
|
|||||||
{ Q_PL5, "create default smart playlist 'Podcasts'" },
|
{ Q_PL5, "create default smart playlist 'Podcasts'" },
|
||||||
{ Q_PL6, "create default smart playlist 'Audiobooks'" },
|
{ Q_PL6, "create default smart playlist 'Audiobooks'" },
|
||||||
|
|
||||||
{ Q_SCVER, "set schema version" },
|
|
||||||
{ Q_SCVER_MAJOR, "set schema version major" },
|
{ Q_SCVER_MAJOR, "set schema version major" },
|
||||||
{ Q_SCVER_MINOR, "set schema version minor" },
|
{ Q_SCVER_MINOR, "set schema version minor" },
|
||||||
};
|
};
|
||||||
|
10
src/db.h
10
src/db.h
@ -165,7 +165,7 @@ struct media_file_info {
|
|||||||
#define mfi_offsetof(field) offsetof(struct media_file_info, field)
|
#define mfi_offsetof(field) offsetof(struct media_file_info, field)
|
||||||
|
|
||||||
enum pl_type {
|
enum pl_type {
|
||||||
PL_PLAIN,
|
PL_PLAIN = 0,
|
||||||
PL_SMART,
|
PL_SMART,
|
||||||
PL_MAX
|
PL_MAX
|
||||||
};
|
};
|
||||||
@ -181,8 +181,8 @@ struct playlist_info {
|
|||||||
char *path; /* path of underlying playlist */
|
char *path; /* path of underlying playlist */
|
||||||
uint32_t index; /* index of playlist for paths with multiple playlists */
|
uint32_t index; /* index of playlist for paths with multiple playlists */
|
||||||
uint32_t special_id; /* iTunes identifies certain 'special' playlists with special meaning */
|
uint32_t special_id; /* iTunes identifies certain 'special' playlists with special meaning */
|
||||||
char *virtual_path; /* virtual path of underlying playlist */
|
|
||||||
uint32_t parent_id; /* Id of parent playlist if the playlist is nested */
|
uint32_t parent_id; /* Id of parent playlist if the playlist is nested */
|
||||||
|
char *virtual_path; /* virtual path of underlying playlist */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define pli_offsetof(field) offsetof(struct playlist_info, field)
|
#define pli_offsetof(field) offsetof(struct playlist_info, field)
|
||||||
@ -198,8 +198,8 @@ struct db_playlist_info {
|
|||||||
char *path;
|
char *path;
|
||||||
char *index;
|
char *index;
|
||||||
char *special_id;
|
char *special_id;
|
||||||
char *virtual_path;
|
|
||||||
char *parent_id;
|
char *parent_id;
|
||||||
|
char *virtual_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define dbpli_offsetof(field) offsetof(struct db_playlist_info, field)
|
#define dbpli_offsetof(field) offsetof(struct db_playlist_info, field)
|
||||||
@ -463,7 +463,7 @@ struct playlist_info *
|
|||||||
db_pl_fetch_bytitlepath(char *title, char *path);
|
db_pl_fetch_bytitlepath(char *title, char *path);
|
||||||
|
|
||||||
int
|
int
|
||||||
db_pl_add(char *title, char *path, char *virtual_path, int *id);
|
db_pl_add(struct playlist_info *pli, int *id);
|
||||||
|
|
||||||
int
|
int
|
||||||
db_pl_add_item_bypath(int plid, char *path);
|
db_pl_add_item_bypath(int plid, char *path);
|
||||||
@ -475,7 +475,7 @@ void
|
|||||||
db_pl_clear_items(int id);
|
db_pl_clear_items(int id);
|
||||||
|
|
||||||
int
|
int
|
||||||
db_pl_update(char *title, char *path, char *virtual_path, int id);
|
db_pl_update(struct playlist_info *pli);
|
||||||
|
|
||||||
void
|
void
|
||||||
db_pl_delete(int id);
|
db_pl_delete(int id);
|
||||||
|
@ -759,8 +759,22 @@ process_pls(plist_t playlists, char *file)
|
|||||||
|
|
||||||
if (pl_id == 0)
|
if (pl_id == 0)
|
||||||
{
|
{
|
||||||
|
pli = (struct playlist_info *)malloc(sizeof(struct playlist_info));
|
||||||
|
if (!pli)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SCAN, "Out of memory\n");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(pli, 0, sizeof(struct playlist_info));
|
||||||
|
|
||||||
|
pli->title = strdup(name);
|
||||||
|
pli->path = strdup(file);
|
||||||
snprintf(virtual_path, PATH_MAX, "/file:%s", file);
|
snprintf(virtual_path, PATH_MAX, "/file:%s", file);
|
||||||
ret = db_pl_add(name, file, virtual_path, &pl_id);
|
pli->virtual_path = strdup(virtual_path);
|
||||||
|
|
||||||
|
ret = db_pl_add(pli, &pl_id);
|
||||||
|
free_pli(pli, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SCAN, "Error adding iTunes playlist '%s' (%s)\n", name, file);
|
DPRINTF(E_LOG, L_SCAN, "Error adding iTunes playlist '%s' (%s)\n", name, file);
|
||||||
|
@ -96,14 +96,6 @@ scan_playlist(char *file, time_t mtime)
|
|||||||
|
|
||||||
DPRINTF(E_LOG, L_SCAN, "Processing static playlist: %s\n", file);
|
DPRINTF(E_LOG, L_SCAN, "Processing static playlist: %s\n", file);
|
||||||
|
|
||||||
ret = stat(file, &sb);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_SCAN, "Could not stat() '%s': %s\n", file, strerror(errno));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = strrchr(file, '.');
|
ptr = strrchr(file, '.');
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
return;
|
return;
|
||||||
@ -121,21 +113,13 @@ scan_playlist(char *file, time_t mtime)
|
|||||||
else
|
else
|
||||||
filename++;
|
filename++;
|
||||||
|
|
||||||
pli = db_pl_fetch_bypath(file);
|
ret = stat(file, &sb);
|
||||||
|
if (ret < 0)
|
||||||
if (pli)
|
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SCAN, "Playlist found, updating\n");
|
DPRINTF(E_LOG, L_SCAN, "Could not stat() '%s': %s\n", file, strerror(errno));
|
||||||
|
|
||||||
pl_id = pli->id;
|
return;
|
||||||
|
|
||||||
free_pli(pli, 0);
|
|
||||||
|
|
||||||
db_pl_ping(pl_id);
|
|
||||||
db_pl_clear_items(pl_id);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
pl_id = 0;
|
|
||||||
|
|
||||||
fp = fopen(file, "r");
|
fp = fopen(file, "r");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
@ -145,33 +129,58 @@ scan_playlist(char *file, time_t mtime)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pl_id == 0)
|
/* Fetch or create playlist */
|
||||||
|
pli = db_pl_fetch_bypath(file);
|
||||||
|
if (pli)
|
||||||
{
|
{
|
||||||
/* Get only the basename, to be used as the playlist name */
|
DPRINTF(E_DBG, L_SCAN, "Found playlist '%s', updating\n", file);
|
||||||
|
|
||||||
|
pl_id = pli->id;
|
||||||
|
|
||||||
|
db_pl_ping(pl_id);
|
||||||
|
db_pl_clear_items(pl_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pli = (struct playlist_info *)malloc(sizeof(struct playlist_info));
|
||||||
|
if (!pli)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SCAN, "Out of memory\n");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(pli, 0, sizeof(struct playlist_info));
|
||||||
|
|
||||||
|
/* Get only the basename, to be used as the playlist title */
|
||||||
ptr = strrchr(filename, '.');
|
ptr = strrchr(filename, '.');
|
||||||
if (ptr)
|
if (ptr)
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
|
|
||||||
/* Safe: filename is a subset of file which is <= PATH_MAX already */
|
pli->title = strdup(filename);
|
||||||
strncpy(buf, filename, sizeof(buf));
|
|
||||||
|
|
||||||
/* Restore the full filename */
|
/* Restore the full filename */
|
||||||
if (ptr)
|
if (ptr)
|
||||||
*ptr = '.';
|
*ptr = '.';
|
||||||
|
|
||||||
|
pli->path = strdup(file);
|
||||||
snprintf(virtual_path, PATH_MAX, "/file:%s", file);
|
snprintf(virtual_path, PATH_MAX, "/file:%s", file);
|
||||||
|
pli->virtual_path = strdup(virtual_path);
|
||||||
|
|
||||||
ret = db_pl_add(buf, file, virtual_path, &pl_id);
|
ret = db_pl_add(pli, &pl_id);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SCAN, "Error adding playlist '%s'\n", file);
|
DPRINTF(E_LOG, L_SCAN, "Error adding playlist '%s'\n", file);
|
||||||
|
|
||||||
|
free_pli(pli, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(E_INFO, L_SCAN, "Added playlist as id %d\n", pl_id);
|
DPRINTF(E_INFO, L_SCAN, "Added playlist as id %d\n", pl_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_pli(pli, 0);
|
||||||
|
|
||||||
extinf = 0;
|
extinf = 0;
|
||||||
memset(&mfi, 0, sizeof(struct media_file_info));
|
memset(&mfi, 0, sizeof(struct media_file_info));
|
||||||
|
|
||||||
|
@ -645,8 +645,6 @@ spotify_playlist_save(sp_playlist *pl)
|
|||||||
}
|
}
|
||||||
fptr_sp_link_release(link);
|
fptr_sp_link_release(link);
|
||||||
|
|
||||||
// sleep(1); // Primitive way of preventing database locking (the mutex wasn't working)
|
|
||||||
|
|
||||||
pli = db_pl_fetch_bypath(url);
|
pli = db_pl_fetch_bypath(url);
|
||||||
|
|
||||||
// The starred playlist has an empty name, set it manually to "Starred"
|
// The starred playlist has an empty name, set it manually to "Starred"
|
||||||
@ -663,30 +661,51 @@ spotify_playlist_save(sp_playlist *pl)
|
|||||||
|
|
||||||
plid = pli->id;
|
plid = pli->id;
|
||||||
|
|
||||||
free_pli(pli, 0);
|
free(pli->title);
|
||||||
|
pli->title = strdup(title);
|
||||||
|
free(pli->virtual_path);
|
||||||
|
pli->virtual_path = strdup(virtual_path);
|
||||||
|
|
||||||
ret = db_pl_update(title, url, virtual_path, plid);
|
ret = db_pl_update(pli);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Error updating playlist ('%s', link %s)\n", name, url);
|
DPRINTF(E_LOG, L_SPOTIFY, "Error updating playlist ('%s', link %s)\n", name, url);
|
||||||
|
|
||||||
|
free_pli(pli, 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
db_pl_ping(plid);
|
|
||||||
db_pl_clear_items(plid);
|
db_pl_clear_items(plid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Adding playlist ('%s', link %s)\n", name, url);
|
DPRINTF(E_DBG, L_SPOTIFY, "Adding playlist ('%s', link %s)\n", name, url);
|
||||||
|
|
||||||
ret = db_pl_add(title, url, virtual_path, &plid);
|
pli = (struct playlist_info *)malloc(sizeof(struct playlist_info));
|
||||||
|
if (!pli)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SCAN, "Out of memory\n");
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(pli, 0, sizeof(struct playlist_info));
|
||||||
|
pli->title = strdup(title);
|
||||||
|
pli->path = strdup(url);
|
||||||
|
pli->virtual_path = strdup(virtual_path);
|
||||||
|
|
||||||
|
ret = db_pl_add(pli, &plid);
|
||||||
if ((ret < 0) || (plid < 1))
|
if ((ret < 0) || (plid < 1))
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Error adding playlist ('%s', link %s, ret %d, plid %d)\n", name, url, ret, plid);
|
DPRINTF(E_LOG, L_SPOTIFY, "Error adding playlist ('%s', link %s, ret %d, plid %d)\n", name, url, ret, plid);
|
||||||
|
|
||||||
|
free_pli(pli, 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_pli(pli, 0);
|
||||||
|
|
||||||
/* Save tracks and playlistitems (files and playlistitems table) */
|
/* Save tracks and playlistitems (files and playlistitems table) */
|
||||||
num_tracks = fptr_sp_playlist_num_tracks(pl);
|
num_tracks = fptr_sp_playlist_num_tracks(pl);
|
||||||
for (i = 0; i < num_tracks; i++)
|
for (i = 0; i < num_tracks; i++)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user