Skip to content

Commit

Permalink
[library,scan] library api to automatically write metadata upon to me…
Browse files Browse the repository at this point in the history
…dia update changes (at this time 'rating')

Implemented for filescanner via ffmpeg
  • Loading branch information
whatdoineed2do/Ray committed Dec 12, 2023
1 parent bf91178 commit c845f4d
Show file tree
Hide file tree
Showing 4 changed files with 351 additions and 7 deletions.
17 changes: 15 additions & 2 deletions src/library.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ static struct library_callback_register library_cb_register[LIBRARY_MAX_CALLBACK
int
library_media_save(struct media_file_info *mfi)
{
int ret, i;
struct library_source **ls;

if (!mfi->path || !mfi->fname || !mfi->scan_kind)
{
DPRINTF(E_LOG, L_LIB, "Ignoring media file with missing values (path='%s', fname='%s', scan_kind='%d', data_kind='%d')\n",
Expand All @@ -134,9 +137,19 @@ library_media_save(struct media_file_info *mfi)
}

if (mfi->id == 0)
return db_file_add(mfi);
ret = db_file_add(mfi);
else
return db_file_update(mfi);
{
ret = db_file_update(mfi);

ls = sources;
for (i=0; ls[i]; ++i)
{
if (!ls[i]->disabled && ls[i]->write_metadata)
ls[i]->write_metadata(mfi->virtual_path, NULL, mfi->rating);
}
}
return ret;
}

int
Expand Down
5 changes: 5 additions & 0 deletions src/library.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ struct library_source
*/
int (*fullrescan)(void);

/*
* write meta to media, via virtual_path OR id
*/
int (*write_metadata)(const char *virtual_path, const uint32_t *id, uint32_t rating);

/*
* Add an item to the library
*/
Expand Down
96 changes: 91 additions & 5 deletions src/library/filescanner.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@
#define F_SCAN_TYPE_AUDIOBOOK (1 << 2)
#define F_SCAN_TYPE_COMPILATION (1 << 3)

#ifdef __linux__
#define INOTIFY_FLAGS (IN_ATTRIB | IN_CREATE | IN_DELETE | IN_CLOSE_WRITE | IN_MOVE | IN_DELETE | IN_MOVE_SELF)
#else
#define INOTIFY_FLAGS (IN_CREATE | IN_DELETE | IN_MOVE)
#endif



enum file_type {
FILE_UNKNOWN = 0,
Expand Down Expand Up @@ -156,6 +163,8 @@ filescanner_rescan();
static int
filescanner_fullrescan();

int
filescanner_ffmpeg_write_rating(const struct media_file_info *mfi);

/* ----------------------- Internal utility functions --------------------- */

Expand Down Expand Up @@ -906,11 +915,7 @@ process_directory(char *path, int parent_id, int flags)

// Add inotify watch (for FreeBSD we limit the flags so only dirs will be
// opened, otherwise we will be opening way too many files)
#ifdef __linux__
wi.wd = inotify_add_watch(inofd, path, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_CLOSE_WRITE | IN_MOVE | IN_DELETE | IN_MOVE_SELF);
#else
wi.wd = inotify_add_watch(inofd, path, IN_CREATE | IN_DELETE | IN_MOVE);
#endif
wi.wd = inotify_add_watch(inofd, path, INOTIFY_FLAGS);
if (wi.wd < 0)
{
DPRINTF(E_WARN, L_SCAN, "Could not create inotify watch for %s: %s\n", path, strerror(errno));
Expand Down Expand Up @@ -1719,6 +1724,86 @@ filescanner_fullrescan()
return 0;
}

static int
filescanner_write_metadata(const char *virtual_path, const uint32_t *id, uint32_t rating)
{
int ret;
char inotify_path[PATH_MAX] = { 0 };
struct watch_info wi = { 0 };
struct media_file_info* mfi = NULL;

if (virtual_path)
{
mfi = db_file_fetch_byvirtualpath(virtual_path);
if (!mfi)
{
DPRINTF(E_INFO, L_SCAN, "No known path for local media, (%s) requested for rating write\n", virtual_path);
return -1;
}
}
else
{
// Determine if this is local media
mfi = db_file_fetch_byid(*id);
if (!mfi)
{
DPRINTF(E_LOG, L_SCAN, "No known path for local media, (%d) requested for rating write\n", *id);
return -1;
}
}

if (mfi->data_kind != DATA_KIND_FILE)
{
DPRINTF(E_INFO, L_SCAN, "Ignoring non local media (%d/%s is %s) requested for rating write\n", mfi->id, mfi->path, db_data_kind_label(mfi->data_kind));
ret = -1;
goto cleanup;
}

// Inotify watches dir paths
strcpy(inotify_path, mfi->path);
dirname(inotify_path);

if (access(mfi->path, W_OK) < 0 || access(inotify_path, W_OK) < 0)
{
DPRINTF(E_INFO, L_SCAN, "No permissions to update metadata, skipping %s\n", mfi->path);
ret = 0;
goto cleanup;
}

// Temporarily disable inotify
ret = db_watch_get_bypath(&wi, inotify_path);
if (ret == 0)
{
inotify_rm_watch(inofd, wi.wd);
db_watch_delete_bywd(wi.wd);
free_wi(&wi, 1);
}


filescanner_ffmpeg_write_rating(mfi);


// and re-enable
wi.wd = inotify_add_watch(inofd, inotify_path, INOTIFY_FLAGS);
if (wi.wd < 0)
{
DPRINTF(E_WARN, L_SCAN, "Could not create inotify watch for %s: %s\n", inotify_path, strerror(errno));
ret = -1;
goto cleanup;
}

wi.cookie = 0;
wi.path = inotify_path;

db_watch_add(&wi);

cleanup:
free_mfi(mfi, 0);

return ret;
}


static int
queue_item_stream_add(const char *path, int position, char reshuffle, uint32_t item_id, int *count, int *new_item_id)
{
Expand Down Expand Up @@ -2166,6 +2251,7 @@ struct library_source filescanner =
.rescan = filescanner_rescan,
.metarescan = filescanner_metarescan,
.fullrescan = filescanner_fullrescan,
.write_metadata = filescanner_write_metadata,
.playlist_item_add = playlist_item_add,
.playlist_remove = playlist_remove,
.queue_save = queue_save,
Expand Down
Loading

0 comments on commit c845f4d

Please sign in to comment.