mirror of
https://github.com/owntone/owntone-server.git
synced 2025-02-09 04:38:10 -05:00
Merge branch 'dev'
This commit is contained in:
commit
a181b515f2
53
src/db.c
53
src/db.c
@ -2470,7 +2470,7 @@ db_file_update(struct media_file_info *mfi)
|
|||||||
" year = %d, track = %d, total_tracks = %d, disc = %d, total_discs = %d, bpm = %d," \
|
" year = %d, track = %d, total_tracks = %d, disc = %d, total_discs = %d, bpm = %d," \
|
||||||
" compilation = %d, artwork = %d, rating = %d, seek = %d, data_kind = %d, item_kind = %d," \
|
" compilation = %d, artwork = %d, rating = %d, seek = %d, data_kind = %d, item_kind = %d," \
|
||||||
" description = %Q, time_modified = %" PRIi64 "," \
|
" description = %Q, time_modified = %" PRIi64 "," \
|
||||||
" db_timestamp = %" PRIi64 ", sample_count = %" PRIi64 "," \
|
" db_timestamp = %" PRIi64 ", disabled = %" PRIi64 ", sample_count = %" PRIi64 "," \
|
||||||
" codectype = %Q, idx = %d, has_video = %d," \
|
" codectype = %Q, idx = %d, has_video = %d," \
|
||||||
" bits_per_sample = %d, album_artist = TRIM(%Q)," \
|
" bits_per_sample = %d, album_artist = TRIM(%Q)," \
|
||||||
" media_kind = %d, tv_series_name = TRIM(%Q), tv_episode_num_str = TRIM(%Q)," \
|
" media_kind = %d, tv_series_name = TRIM(%Q), tv_episode_num_str = TRIM(%Q)," \
|
||||||
@ -2500,7 +2500,7 @@ db_file_update(struct media_file_info *mfi)
|
|||||||
mfi->year, mfi->track, mfi->total_tracks, mfi->disc, mfi->total_discs, mfi->bpm,
|
mfi->year, mfi->track, mfi->total_tracks, mfi->disc, mfi->total_discs, mfi->bpm,
|
||||||
mfi->compilation, mfi->artwork, mfi->rating, mfi->seek, mfi->data_kind, mfi->item_kind,
|
mfi->compilation, mfi->artwork, mfi->rating, mfi->seek, mfi->data_kind, mfi->item_kind,
|
||||||
mfi->description, (int64_t)mfi->time_modified,
|
mfi->description, (int64_t)mfi->time_modified,
|
||||||
(int64_t)mfi->db_timestamp, mfi->sample_count,
|
(int64_t)mfi->db_timestamp, (int64_t)mfi->disabled, mfi->sample_count,
|
||||||
mfi->codectype, mfi->index, mfi->has_video,
|
mfi->codectype, mfi->index, mfi->has_video,
|
||||||
mfi->bits_per_sample, mfi->album_artist,
|
mfi->bits_per_sample, mfi->album_artist,
|
||||||
mfi->media_kind, mfi->tv_series_name, mfi->tv_episode_num_str,
|
mfi->media_kind, mfi->tv_series_name, mfi->tv_episode_num_str,
|
||||||
@ -3170,7 +3170,7 @@ db_pl_add_item_byid(int plid, int fileid)
|
|||||||
int
|
int
|
||||||
db_pl_update(char *title, char *path, int id)
|
db_pl_update(char *title, char *path, int id)
|
||||||
{
|
{
|
||||||
#define Q_TMPL "UPDATE playlists SET title = '%q', db_timestamp = %" PRIi64 ", path = '%q' WHERE id = %d;"
|
#define Q_TMPL "UPDATE playlists SET title = '%q', db_timestamp = %" PRIi64 ", disabled = 0, path = '%q' WHERE id = %d;"
|
||||||
char *query;
|
char *query;
|
||||||
char *errmsg;
|
char *errmsg;
|
||||||
int ret;
|
int ret;
|
||||||
@ -3949,11 +3949,9 @@ db_watch_delete_bycookie(uint32_t cookie)
|
|||||||
#undef Q_TMPL
|
#undef Q_TMPL
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
db_watch_get_bywd(struct watch_info *wi)
|
db_watch_get_byquery(struct watch_info *wi, char *query)
|
||||||
{
|
{
|
||||||
#define Q_TMPL "SELECT * FROM inotify WHERE wd = %d;"
|
|
||||||
char *query;
|
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
char **strval;
|
char **strval;
|
||||||
char *cval;
|
char *cval;
|
||||||
@ -3963,13 +3961,6 @@ db_watch_get_bywd(struct watch_info *wi)
|
|||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
query = sqlite3_mprintf(Q_TMPL, wi->wd);
|
|
||||||
if (!query)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query);
|
DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query);
|
||||||
|
|
||||||
ret = db_blocking_prepare_v2(query, -1, &stmt, NULL);
|
ret = db_blocking_prepare_v2(query, -1, &stmt, NULL);
|
||||||
@ -3982,7 +3973,7 @@ db_watch_get_bywd(struct watch_info *wi)
|
|||||||
ret = db_blocking_step(stmt);
|
ret = db_blocking_step(stmt);
|
||||||
if (ret != SQLITE_ROW)
|
if (ret != SQLITE_ROW)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DB, "Watch wd %d not found\n", wi->wd);
|
DPRINTF(E_WARN, L_DB, "Watch not found: '%s'\n", query);
|
||||||
|
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
sqlite3_free(query);
|
sqlite3_free(query);
|
||||||
@ -4041,7 +4032,39 @@ db_watch_get_bywd(struct watch_info *wi)
|
|||||||
sqlite3_free(query);
|
sqlite3_free(query);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
db_watch_get_bywd(struct watch_info *wi)
|
||||||
|
{
|
||||||
|
#define Q_TMPL "SELECT * FROM inotify WHERE wd = %d;"
|
||||||
|
char *query;
|
||||||
|
|
||||||
|
query = sqlite3_mprintf(Q_TMPL, wi->wd);
|
||||||
|
if (!query)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return db_watch_get_byquery(wi, query);
|
||||||
|
#undef Q_TMPL
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
db_watch_get_bypath(struct watch_info *wi)
|
||||||
|
{
|
||||||
|
#define Q_TMPL "SELECT * FROM inotify WHERE path = '%q';"
|
||||||
|
char *query;
|
||||||
|
|
||||||
|
query = sqlite3_mprintf(Q_TMPL, wi->path);
|
||||||
|
if (!query)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return db_watch_get_byquery(wi, query);
|
||||||
#undef Q_TMPL
|
#undef Q_TMPL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
src/db.h
3
src/db.h
@ -512,6 +512,9 @@ db_watch_delete_bycookie(uint32_t cookie);
|
|||||||
int
|
int
|
||||||
db_watch_get_bywd(struct watch_info *wi);
|
db_watch_get_bywd(struct watch_info *wi);
|
||||||
|
|
||||||
|
int
|
||||||
|
db_watch_get_bypath(struct watch_info *wi);
|
||||||
|
|
||||||
void
|
void
|
||||||
db_watch_mark_bypath(char *path, char *strip, uint32_t cookie);
|
db_watch_mark_bypath(char *path, char *strip, uint32_t cookie);
|
||||||
|
|
||||||
|
@ -897,7 +897,7 @@ process_directory(char *path, int flags)
|
|||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
/* Add inotify watch */
|
/* Add inotify watch */
|
||||||
wi.wd = inotify_add_watch(inofd, path, IN_CREATE | IN_DELETE | IN_CLOSE_WRITE | IN_MOVE | IN_DELETE | IN_MOVE_SELF);
|
wi.wd = inotify_add_watch(inofd, path, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_CLOSE_WRITE | IN_MOVE | IN_DELETE | IN_MOVE_SELF);
|
||||||
if (wi.wd < 0)
|
if (wi.wd < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_SCAN, "Could not create inotify watch for %s: %s\n", path, strerror(errno));
|
DPRINTF(E_WARN, L_SCAN, "Could not create inotify watch for %s: %s\n", path, strerror(errno));
|
||||||
@ -1093,6 +1093,10 @@ filescanner(void *arg)
|
|||||||
else
|
else
|
||||||
bulk_scan(F_SCAN_BULK);
|
bulk_scan(F_SCAN_BULK);
|
||||||
|
|
||||||
|
#ifdef HAVE_SPOTIFY_H
|
||||||
|
spotify_login(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!scan_exit)
|
if (!scan_exit)
|
||||||
{
|
{
|
||||||
/* Enable inotify */
|
/* Enable inotify */
|
||||||
@ -1111,16 +1115,47 @@ filescanner(void *arg)
|
|||||||
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
|
static int
|
||||||
|
watches_clear(uint32_t wd, char *path)
|
||||||
|
{
|
||||||
|
struct watch_enum we;
|
||||||
|
uint32_t rm_wd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
inotify_rm_watch(inofd, wd);
|
||||||
|
db_watch_delete_bywd(wd);
|
||||||
|
|
||||||
|
memset(&we, 0, sizeof(struct watch_enum));
|
||||||
|
|
||||||
|
we.match = path;
|
||||||
|
|
||||||
|
ret = db_watch_enum_start(&we);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while ((db_watch_enum_fetchwd(&we, &rm_wd) == 0) && (rm_wd))
|
||||||
|
{
|
||||||
|
inotify_rm_watch(inofd, rm_wd);
|
||||||
|
}
|
||||||
|
|
||||||
|
db_watch_enum_end(&we);
|
||||||
|
|
||||||
|
db_watch_delete_bymatch(path);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Thread: scan */
|
/* Thread: scan */
|
||||||
static void
|
static void
|
||||||
process_inotify_dir(struct watch_info *wi, char *path, struct inotify_event *ie)
|
process_inotify_dir(struct watch_info *wi, char *path, struct inotify_event *ie)
|
||||||
{
|
{
|
||||||
struct watch_enum we;
|
struct watch_enum we;
|
||||||
uint32_t rm_wd;
|
uint32_t rm_wd;
|
||||||
|
char *s;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_SCAN, "Directory event: 0x%x, cookie 0x%x, wd %d\n", ie->mask, ie->cookie, wi->wd);
|
DPRINTF(E_SPAM, L_SCAN, "Directory event: 0x%x, cookie 0x%x, wd %d\n", ie->mask, ie->cookie, wi->wd);
|
||||||
|
|
||||||
if (ie->mask & IN_UNMOUNT)
|
if (ie->mask & IN_UNMOUNT)
|
||||||
{
|
{
|
||||||
@ -1165,26 +1200,10 @@ process_inotify_dir(struct watch_info *wi, char *path, struct inotify_event *ie)
|
|||||||
* and we can't tell where it's going
|
* and we can't tell where it's going
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inotify_rm_watch(inofd, ie->wd);
|
ret = watches_clear(ie->wd, path);
|
||||||
db_watch_delete_bywd(ie->wd);
|
|
||||||
|
|
||||||
memset(&we, 0, sizeof(struct watch_enum));
|
|
||||||
|
|
||||||
we.match = path;
|
|
||||||
|
|
||||||
ret = db_watch_enum_start(&we);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while ((db_watch_enum_fetchwd(&we, &rm_wd) == 0) && (rm_wd))
|
|
||||||
{
|
|
||||||
inotify_rm_watch(inofd, rm_wd);
|
|
||||||
}
|
|
||||||
|
|
||||||
db_watch_enum_end(&we);
|
|
||||||
|
|
||||||
db_watch_delete_bymatch(path);
|
|
||||||
|
|
||||||
db_file_disable_bymatch(path, "", 0);
|
db_file_disable_bymatch(path, "", 0);
|
||||||
db_pl_disable_bymatch(path, "", 0);
|
db_pl_disable_bymatch(path, "", 0);
|
||||||
}
|
}
|
||||||
@ -1213,6 +1232,40 @@ process_inotify_dir(struct watch_info *wi, char *path, struct inotify_event *ie)
|
|||||||
ie->mask |= IN_CREATE;
|
ie->mask |= IN_CREATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ie->mask & IN_ATTRIB)
|
||||||
|
{
|
||||||
|
DPRINTF(E_DBG, L_SCAN, "Directory permissions changed (%s): %s\n", wi->path, path);
|
||||||
|
|
||||||
|
// Find out if we are already watching the dir (ret will be 0)
|
||||||
|
s = wi->path;
|
||||||
|
wi->path = path;
|
||||||
|
ret = db_watch_get_bypath(wi);
|
||||||
|
if (ret == 0)
|
||||||
|
free(wi->path);
|
||||||
|
wi->path = s;
|
||||||
|
|
||||||
|
if (euidaccess(path, (R_OK | X_OK)) < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SCAN, "Directory access to '%s' failed: %s\n", path, strerror(errno));
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
watches_clear(wi->wd, path);
|
||||||
|
|
||||||
|
db_file_disable_bymatch(path, "", 0);
|
||||||
|
db_pl_disable_bymatch(path, "", 0);
|
||||||
|
}
|
||||||
|
else if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SCAN, "Directory access to '%s' achieved\n", path);
|
||||||
|
|
||||||
|
ie->mask |= IN_CREATE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINTF(E_INFO, L_SCAN, "Directory event, but '%s' already being watched\n", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ie->mask & IN_CREATE)
|
if (ie->mask & IN_CREATE)
|
||||||
{
|
{
|
||||||
process_directories(path, flags);
|
process_directories(path, flags);
|
||||||
@ -1237,6 +1290,7 @@ process_inotify_file(struct watch_info *wi, char *path, struct inotify_event *ie
|
|||||||
if (ie->mask & IN_DELETE)
|
if (ie->mask & IN_DELETE)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SCAN, "File deleted: %s\n", path);
|
DPRINTF(E_DBG, L_SCAN, "File deleted: %s\n", path);
|
||||||
|
|
||||||
db_file_delete_bypath(path);
|
db_file_delete_bypath(path);
|
||||||
db_pl_delete_bypath(path);
|
db_pl_delete_bypath(path);
|
||||||
}
|
}
|
||||||
@ -1244,13 +1298,33 @@ process_inotify_file(struct watch_info *wi, char *path, struct inotify_event *ie
|
|||||||
if (ie->mask & IN_MOVED_FROM)
|
if (ie->mask & IN_MOVED_FROM)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SCAN, "File moved from: %s\n", path);
|
DPRINTF(E_DBG, L_SCAN, "File moved from: %s\n", path);
|
||||||
|
|
||||||
db_file_disable_bypath(path, path, ie->cookie);
|
db_file_disable_bypath(path, path, ie->cookie);
|
||||||
db_pl_disable_bypath(path, path, ie->cookie);
|
db_pl_disable_bypath(path, path, ie->cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ie->mask & IN_ATTRIB)
|
||||||
|
{
|
||||||
|
DPRINTF(E_DBG, L_SCAN, "File permissions changed: %s\n", path);
|
||||||
|
|
||||||
|
if (euidaccess(path, R_OK) < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SCAN, "File access to '%s' failed: %s\n", path, strerror(errno));
|
||||||
|
|
||||||
|
db_file_delete_bypath(path);;
|
||||||
|
}
|
||||||
|
else if (db_file_id_bypath(path) <= 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SCAN, "File access to '%s' achieved\n", path);
|
||||||
|
|
||||||
|
ie->mask |= IN_CLOSE_WRITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ie->mask & IN_MOVED_TO)
|
if (ie->mask & IN_MOVED_TO)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SCAN, "File moved to: %s\n", path);
|
DPRINTF(E_DBG, L_SCAN, "File moved to: %s\n", path);
|
||||||
|
|
||||||
ret = db_file_enable_bycookie(ie->cookie, path);
|
ret = db_file_enable_bycookie(ie->cookie, path);
|
||||||
|
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
@ -1268,6 +1342,7 @@ process_inotify_file(struct watch_info *wi, char *path, struct inotify_event *ie
|
|||||||
if (ie->mask & IN_CREATE)
|
if (ie->mask & IN_CREATE)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SCAN, "File created: %s\n", path);
|
DPRINTF(E_DBG, L_SCAN, "File created: %s\n", path);
|
||||||
|
|
||||||
ret = lstat(path, &sb);
|
ret = lstat(path, &sb);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@ -1283,6 +1358,7 @@ process_inotify_file(struct watch_info *wi, char *path, struct inotify_event *ie
|
|||||||
if (ie->mask & IN_CLOSE_WRITE)
|
if (ie->mask & IN_CLOSE_WRITE)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SCAN, "File closed: %s\n", path);
|
DPRINTF(E_DBG, L_SCAN, "File closed: %s\n", path);
|
||||||
|
|
||||||
ret = lstat(path, &sb);
|
ret = lstat(path, &sb);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
147
src/spotify.c
147
src/spotify.c
@ -501,21 +501,21 @@ spotify_track_save(int plid, sp_track *track)
|
|||||||
|
|
||||||
if (fptr_sp_track_get_availability(g_sess, track) != SP_TRACK_AVAILABILITY_AVAILABLE)
|
if (fptr_sp_track_get_availability(g_sess, track) != SP_TRACK_AVAILABILITY_AVAILABLE)
|
||||||
{
|
{
|
||||||
DPRINTF(E_INFO, L_SPOTIFY, "Track not available for playback\n");
|
DPRINTF(E_LOG, L_SPOTIFY, "Track not available for playback: '%s'\n", fptr_sp_track_name(track));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
link = fptr_sp_link_create_from_track(track, 0);
|
link = fptr_sp_link_create_from_track(track, 0);
|
||||||
if (!link)
|
if (!link)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not create link for track\n");
|
DPRINTF(E_LOG, L_SPOTIFY, "Could not create link for track: '%s'\n", fptr_sp_track_name(track));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fptr_sp_link_as_string(link, url, sizeof(url));
|
ret = fptr_sp_link_as_string(link, url, sizeof(url));
|
||||||
if (ret == sizeof(url))
|
if (ret == sizeof(url))
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Spotify link truncated: %s\n", url);
|
DPRINTF(E_DBG, L_SPOTIFY, "Spotify link truncated: '%s'\n", url);
|
||||||
}
|
}
|
||||||
fptr_sp_link_release(link);
|
fptr_sp_link_release(link);
|
||||||
|
|
||||||
@ -523,7 +523,7 @@ spotify_track_save(int plid, sp_track *track)
|
|||||||
ret = db_pl_add_item_bypath(plid, url);
|
ret = db_pl_add_item_bypath(plid, url);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not save playlist item\n");
|
DPRINTF(E_LOG, L_SPOTIFY, "Could not save playlist item: '%s'\n", url);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,7 +532,7 @@ spotify_track_save(int plid, sp_track *track)
|
|||||||
ret = spotify_metadata_get(track, &mfi);
|
ret = spotify_metadata_get(track, &mfi);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Metadata missing (but track should be loaded?)\n");
|
DPRINTF(E_LOG, L_SPOTIFY, "Metadata missing (but track should be loaded?): '%s'\n", fptr_sp_track_name(track));
|
||||||
free_mfi(&mfi, 1);
|
free_mfi(&mfi, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -566,13 +566,13 @@ spotify_playlist_save(sp_playlist *pl)
|
|||||||
|
|
||||||
name = fptr_sp_playlist_name(pl);
|
name = fptr_sp_playlist_name(pl);
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Saving playlist: %s\n", name);
|
DPRINTF(E_INFO, L_SPOTIFY, "Saving playlist: '%s'\n", name);
|
||||||
|
|
||||||
/* Save playlist (playlists table) */
|
/* Save playlist (playlists table) */
|
||||||
link = fptr_sp_link_create_from_playlist(pl);
|
link = fptr_sp_link_create_from_playlist(pl);
|
||||||
if (!link)
|
if (!link)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not create link for playlist (wait)\n");
|
DPRINTF(E_LOG, L_SPOTIFY, "Could not create link for playlist (wait): '%s'\n", name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,14 +583,14 @@ 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)
|
// 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);
|
||||||
snprintf(title, sizeof(title), "[s] %s", name);
|
snprintf(title, sizeof(title), "[s] %s", name);
|
||||||
|
|
||||||
if (pli)
|
if (pli)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Playlist found (%s, link %s), updating\n", name, url);
|
DPRINTF(E_DBG, L_SPOTIFY, "Playlist found ('%s', link %s), updating\n", name, url);
|
||||||
|
|
||||||
plid = pli->id;
|
plid = pli->id;
|
||||||
|
|
||||||
@ -599,7 +599,7 @@ spotify_playlist_save(sp_playlist *pl)
|
|||||||
ret = db_pl_update(title, url, plid);
|
ret = db_pl_update(title, url, plid);
|
||||||
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);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,12 +608,12 @@ spotify_playlist_save(sp_playlist *pl)
|
|||||||
}
|
}
|
||||||
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, &plid);
|
ret = db_pl_add(title, url, &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);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -625,14 +625,14 @@ spotify_playlist_save(sp_playlist *pl)
|
|||||||
track = fptr_sp_playlist_track(pl, i);
|
track = fptr_sp_playlist_track(pl, i);
|
||||||
if (!track)
|
if (!track)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Track %d in playlist %s (id %d) is invalid\n", i, name, plid);
|
DPRINTF(E_LOG, L_SPOTIFY, "Track %d in playlist '%s' (id %d) is invalid\n", i, name, plid);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = spotify_track_save(plid, track);
|
ret = spotify_track_save(plid, track);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Error saving track %d to playlist %s (id %d)\n", i, name, plid);
|
DPRINTF(E_LOG, L_SPOTIFY, "Error saving track %d to playlist '%s' (id %d)\n", i, name, plid);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1648,47 +1648,38 @@ spotify_artwork_get(struct evbuffer *evbuf, char *path, int max_w, int max_h)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Thread: filescanner */
|
static int
|
||||||
void
|
spotify_file_read(char *path, char **username, char **password)
|
||||||
spotify_login(char *path)
|
|
||||||
{
|
{
|
||||||
char buf[256];
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *username;
|
char *u;
|
||||||
char *password;
|
char *p;
|
||||||
|
char buf[256];
|
||||||
int len;
|
int len;
|
||||||
int ret;
|
|
||||||
sp_error err;
|
|
||||||
|
|
||||||
if (!g_sess)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Can't login! No valid Spotify session.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fp = fopen(path, "rb");
|
fp = fopen(path, "rb");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not open Spotify credentials file %s: %s\n", path, strerror(errno));
|
DPRINTF(E_LOG, L_SPOTIFY, "Could not open Spotify credentials file %s: %s\n", path, strerror(errno));
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
username = fgets(buf, sizeof(buf), fp);
|
u = fgets(buf, sizeof(buf), fp);
|
||||||
if (!username)
|
if (!u)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Empty Spotify credentials file %s\n", path);
|
DPRINTF(E_LOG, L_SPOTIFY, "Empty Spotify credentials file %s\n", path);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(username);
|
len = strlen(u);
|
||||||
if (buf[len - 1] != '\n')
|
if (buf[len - 1] != '\n')
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Invalid Spotify credentials file %s: username name too long or missing password\n", path);
|
DPRINTF(E_LOG, L_SPOTIFY, "Invalid Spotify credentials file %s: username name too long or missing password\n", path);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len)
|
while (len)
|
||||||
@ -1707,29 +1698,29 @@ spotify_login(char *path)
|
|||||||
DPRINTF(E_LOG, L_SPOTIFY, "Invalid Spotify credentials file %s: empty line where username expected\n", path);
|
DPRINTF(E_LOG, L_SPOTIFY, "Invalid Spotify credentials file %s: empty line where username expected\n", path);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
username = strdup(buf);
|
u = strdup(buf);
|
||||||
if (!username)
|
if (!u)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Out of memory for username while reading %s\n", path);
|
DPRINTF(E_LOG, L_SPOTIFY, "Out of memory for username while reading %s\n", path);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
password = fgets(buf, sizeof(buf), fp);
|
p = fgets(buf, sizeof(buf), fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (!password)
|
if (!p)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Invalid Spotify credentials file %s: no password\n", path);
|
DPRINTF(E_LOG, L_SPOTIFY, "Invalid Spotify credentials file %s: no password\n", path);
|
||||||
|
|
||||||
free(username);
|
free(u);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(password);
|
len = strlen(p);
|
||||||
|
|
||||||
while (len)
|
while (len)
|
||||||
{
|
{
|
||||||
@ -1742,18 +1733,42 @@ spotify_login(char *path)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
password = strdup(buf);
|
p = strdup(buf);
|
||||||
if (!password)
|
if (!p)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Out of memory for password while reading %s\n", path);
|
DPRINTF(E_LOG, L_SPOTIFY, "Out of memory for password while reading %s\n", path);
|
||||||
|
|
||||||
free(username);
|
free(u);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF(E_LOG, L_SPOTIFY, "Spotify credentials file OK, logging in with username %s\n", u);
|
||||||
|
|
||||||
|
*username = u;
|
||||||
|
*password = p;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thread: filescanner */
|
||||||
|
void
|
||||||
|
spotify_login(char *path)
|
||||||
|
{
|
||||||
|
char *username;
|
||||||
|
char *password;
|
||||||
|
int ret;
|
||||||
|
sp_error err;
|
||||||
|
|
||||||
|
if (!g_sess)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SPOTIFY, "Can't login! No valid Spotify session.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Log out if thread already running */
|
||||||
if (g_state != SPOTIFY_STATE_INACTIVE)
|
if (g_state != SPOTIFY_STATE_INACTIVE)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Existing login terminating (state %d)\n", g_state);
|
DPRINTF(E_LOG, L_SPOTIFY, "Existing login terminating (state %d)\n", g_state);
|
||||||
|
|
||||||
thread_exit();
|
thread_exit();
|
||||||
|
|
||||||
@ -1765,15 +1780,29 @@ spotify_login(char *path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Spotify credentials file OK, logging in with username %s\n", username);
|
/* Log in */
|
||||||
|
if (path)
|
||||||
|
{
|
||||||
|
ret = spotify_file_read(path, &username, &password);
|
||||||
|
if (ret < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DPRINTF(E_INFO, L_SPOTIFY, "Logging into Spotify\n");
|
||||||
err = fptr_sp_session_login(g_sess, username, password, 1, NULL);
|
err = fptr_sp_session_login(g_sess, username, password, 1, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINTF(E_INFO, L_SPOTIFY, "Logging into Spotify\n");
|
||||||
|
err = fptr_sp_session_relogin(g_sess);
|
||||||
|
}
|
||||||
|
|
||||||
if (SP_ERROR_OK != err)
|
if (SP_ERROR_OK != err)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not login into Spotify: %s\n", fptr_sp_error_message(err));
|
DPRINTF(E_LOG, L_SPOTIFY, "Could not login into Spotify: %s\n", fptr_sp_error_message(err));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Spawn thread */
|
||||||
ret = pthread_create(&tid_spotify, NULL, spotify, NULL);
|
ret = pthread_create(&tid_spotify, NULL, spotify, NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@ -1941,30 +1970,9 @@ spotify_init(void)
|
|||||||
pthread_mutex_init(&g_audio_fifo->mutex, NULL);
|
pthread_mutex_init(&g_audio_fifo->mutex, NULL);
|
||||||
pthread_cond_init(&g_audio_fifo->cond, NULL);
|
pthread_cond_init(&g_audio_fifo->cond, NULL);
|
||||||
|
|
||||||
/* Log in and spawn thread */
|
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Logging into Spotify\n");
|
|
||||||
err = fptr_sp_session_relogin(sp);
|
|
||||||
if (SP_ERROR_OK != err)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not login into Spotify: %s\n", fptr_sp_error_message(err));
|
|
||||||
goto login_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = pthread_create(&tid_spotify, NULL, spotify, NULL);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not spawn Spotify thread: %s\n", strerror(errno));
|
|
||||||
goto thread_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Spotify init complete\n");
|
DPRINTF(E_DBG, L_SPOTIFY, "Spotify init complete\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
thread_fail:
|
|
||||||
pthread_cond_destroy(&g_audio_fifo->cond);
|
|
||||||
pthread_mutex_destroy(&g_audio_fifo->mutex);
|
|
||||||
free(g_audio_fifo);
|
|
||||||
|
|
||||||
audio_fifo_fail:
|
audio_fifo_fail:
|
||||||
fptr_sp_session_release(g_sess);
|
fptr_sp_session_release(g_sess);
|
||||||
g_sess = NULL;
|
g_sess = NULL;
|
||||||
@ -1992,7 +2000,6 @@ spotify_init(void)
|
|||||||
g_libhandle = NULL;
|
g_libhandle = NULL;
|
||||||
|
|
||||||
libspotify_fail:
|
libspotify_fail:
|
||||||
login_fail:
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user