-
Notifications
You must be signed in to change notification settings - Fork 237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
media rating sync #1681
media rating sync #1681
Conversation
9d2d9ff
to
a799d9b
Compare
@ejurgensen - can you provide feedback on the inotify handling part? This seems to do what we want with specific inotify removal per file being updated. I did find an (odd?) situation with that my testing db |
I have received a row of notifications for amendments to this PR, please don't create PRs for work in progress. It's of course fine to ask for feedback on a draft, but then mark it as a draft and continue working on another branch. |
i'm done with changes |
7ddc7d9
to
1205cd2
Compare
One more fix for inotify removal but this should be ready for review |
I still don't understand the purpose of the extra endpoint? Is it because you don't want to write the metadata automatically? |
Yes, didnt want auto update. Auto updating at the db update seems too low level to also manipulate the media file esp if there are errors to report. Also it may not be something a user wants or enables if media is on a read only filesystem (NFS mount like one of my RPis) so I choose the option that required a user request for this to happen. We could use the existing endpoint which accepts rating updates in |
I think the sync should be automatic, but with a setting/config option that makes it disabled by default. The implementation that does the update should be in the library layer (either an extension of filescanner_ffmpeg or separate module), so not in the API. |
Let me know if this is more what you're after. The rating update to the media file happens after the db rating is applied and iterates for all the library sources asking them to sync metadata, where (atm) only file scanner implements this. All ffmpeg related items are in filescanner_ffmpeg I'll cleanup the commits if you're ok with this approach. To test, find an id of the local supported media file (mp3 or flac):
I haven't quited tested the mpd auto-rating update but its through the same path using the virtual_path supplied |
Yes, this structure looks good. Have you looked into if there are any interfaces that update the rating via db_file_update()? I guess that would be challenging to catch and sync. |
Looking at these it doesnt makes sense for the remote items (top 3 in list) to try to update remote media. The REST endpoint may be the only one of interest ( |
@ejurgensen - any more thoughts on this PR? Otherwise I'll squash the commits for the merge |
Overall it looks fine, but I need to find time for a more detailed review. You're welcome to squash. |
34cf6c9
to
c5259a4
Compare
src/db.c
Outdated
|
||
ret = db_query_run(query, 1, 0); | ||
|
||
if (ret == 0) | ||
{ | ||
db_admin_setint64(DB_ADMIN_DB_MODIFIED, (int64_t) time(NULL)); | ||
listener_notify(LISTENER_RATING); | ||
|
||
if (cfg_getbool(cfg_getsec(cfg, "library"), "rating_sync")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not fond of this, the db module should generally not be calliing into the library, and especially not the sources. I see there is a LISTENER_RATING, couldn't that be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see there are calls to db_file_rating_update_xxx() in dacp, json and mpd. Ideally, they should probably be replaced with library_rating_update_xxx(), and then the library can call the db.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's some more comments. If I understand the implementation correctly, it involves rewriting the entire file, which would seem a bit risky. Is that the only way to save metadata with ffmpeg?
Yes, this appears to be correct. not seen any code to suggest otherwise and its how ffmpeg command line does it too (separate input and output files) |
790b6d4
to
b73f8b3
Compare
@ejurgensen - let me know if you have any additional comments on the review fixes, otherwise i'll squash the commits in prep for merge |
You're welcome to do that. I will go through it again and just make final edits myself before merging. |
3724cf1
to
c845f4d
Compare
I started going through this, but there are a few things in filescanner_ffmpeg_write_rating() I couldn't understand:
You don't need to make any fixes concerning these, I'm fixing it up anyway. Just need to understand the above. |
do it based on the audio codec but this is prob suboptimal to check against codec vs container - however neither
yes, this looks like an oversight when
I am using ffmpeg to write the file and then using
|
Thanks for the info. Locally, I’ve made the adjustments that I want to include before merging (plus fixed the conflicts), but how/when to trigger the write to the files is giving me headaches. I’m not happy with the PR's hooks in db_file_rating_update() and library_media_save(). In additon to being somewhat ugly, I think the hook in db_file_rating_update means that the write will be carried out in the httpd and mpd threads? If so, that’s no good. A better solution should also work when the rating updates happen via db_file_inc_playcount etc, so that there is no chance that the ratings in the db and in the file diverge. However, all the alternatives that I can think of also have their problems, so for now I have to think some more about it. |
1bdc4b3
to
5e07129
Compare
Let me take a look over the next few days. Unless we're running as
I seem to remember fixing a bug in The most important test for me was validating that the audio stream hash is identical between the original and the new file; this was done via: |
5e07129
to
7eeb291
Compare
rebased with master and updated for ownership/file mask although this is done as a best efforts ... To ensure the ownership of the replacement file is correct, the server needs to be running as |
Looks a bit too hacky to me, and like you say, it won't work in some cases. There must be a cleaner way of doing this. |
The alternative to I went with the commit approach to keep the matching logic together. |
I suggest you look into how a normal tagging app like kid3 does this. Or I guess any app that edits a file. I can't imagine that they mess around with chown/chmod/umask. Btw, start by just sharing possible ideas. Don't push anything to the branch until we have agreed. |
No unfortunately, we have two options already outlined since there are no other unixy provisions for what you're requiring:
To verify this, you can see what mirroring utils (rsync/tar/install as root) do: I would take this approach and match most utils in unix: if you copy a file under unix, the resulting file will belong to you - even as superuser (excluding mirroring
and not do anything with ownership unless we go with more or less what is already in the last commit. EDIT: |
actually,
ownership change still problem for outlined previous |
@ejurgensen - any conclusive thoughts on this based on my comments above: The additional commit would be as follows @@ -20,6 +20,7 @@
# include <config.h>
#endif
+#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -956,6 +957,7 @@ write_metadata_ffmpeg(struct media_file_info *mfi)
int max_rating;
int file_rating;
int fd = -1;
+ struct stat st;
int ret;
// ffmpeg's metadata update are limited - some formats do not support rating
@@ -1008,6 +1010,14 @@ write_metadata_ffmpeg(struct media_file_info *mfi)
goto end;
}
+ ret = stat(in_fmt_ctx->url, &st);
+ if (ret == 0)
+ {
+ // best efforts...
+ fchmod(fd, st.st_mode & 0777);
+ fchown(fd, st.st_uid, st.st_gid);
+ }
+
ret = file_write_rating(in_fmt_ctx, new_rating_file);
if (ret < 0)
{ |
I'll have a look at it |
I think the way to go about this is to just write directly to the media file. So abandon writing to a copy and so also abandon renaming/replacing/chmod-ing. It will require an extra file copy, because the source file first has to be copied to tmp file to be read from, but I think it will be more clean. I will add a commit to the PR with this. |
7eeb291
to
5ac283a
Compare
I've made an update to the PR with the different method of updating the file. This method should also mean that the file creation time remains correct, which was also an issue with the other method. The disabling of inotify might also not be necessary any more. I won't merge right now, it will be after the next release, so in a few weeks. |
i've added one more commit to this - the |
It's not really required with the changed method, since fast_copy() isn't overwriting anything, it's just making a copy of the source. Then ffmpeg does the overwriting from that copy. However, maybe I will change it so that it's ffmpeg first, and then have fast_copy() overwrite to the file. Then ftruncate() will indeed be needed. |
…dia update changes (at this time 'rating') Implemented for filescanner via ffmpeg
…on - WIP Need to find a better solution for the hook
Doesn't catch automatic rating updates, but maybe better to exclude them since they can lead to whole-playlist file rewriting.
The previous method of writing to a copy and then renaming doesn't assure that file ownership and mask is preserved.
Not really necessary with the new way of writing the rating update (no risk of looping).
7fd0b97
to
ffa2986
Compare
Squashed and merged now, thanks for the contribution. As you might notice, I removed the disabling of inotify, since with the current solution it isn't really needed. Of course, the file will now be rescanned when the rating is written, but there won't be a loop. |
Closes #1678
rating
from local media on scanTest: