summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRasmus Steinke <rasi@xssn.at>2017-09-23 15:18:31 +0200
committerRasmus Steinke <rasi@xssn.at>2017-09-23 15:18:31 +0200
commitd4cb48883528f531e9bac41808be97095809915f (patch)
tree543b3472682a5c18a30aff983b2c222d0d951f9c
parent4a03ed7a11863b53597cd80bfd3f0613a3e8f82b (diff)
downloadperl-app-clerk-d4cb48883528f531e9bac41808be97095809915f.tar.gz
perl-app-clerk-d4cb48883528f531e9bac41808be97095809915f.tar.xz
initial support for writing ratings to files, using a helper client
-rwxr-xr-xclerk52
-rw-r--r--clerk.conf5
-rwxr-xr-xclerk_rating_client123
3 files changed, 168 insertions, 12 deletions
diff --git a/clerk b/clerk
index a0273f4..e2bedd7 100755
--- a/clerk
+++ b/clerk
@@ -8,7 +8,7 @@ use utf8;
use Config::Simple;
use Time::HiRes qw (sleep);
use Data::MessagePack;
-#use DDP;
+use DDP;
use Encode qw(decode encode);
use File::Basename;
use File::Path qw(make_path);
@@ -44,6 +44,7 @@ my $mpd_host = $general_cfg->{mpd_host};
my $tmux_config = $general_cfg->{tmux_config};
my $db_file = $general_cfg->{database};
my $songs = $general_cfg->{songs};
+my $tagging = $general_cfg->{tagging};
my $chunksize = $general_cfg->{chunksize};
my $player = $general_cfg->{player};
@@ -354,7 +355,7 @@ sub do_action {
}
}
} elsif ($context eq "Tracks") {
- my @action_items = ("Add\n", "Replace\n", "Rate Track\n");
+ my @action_items = ("Add\n", "Replace\n", "---\n", "Rate Track\n");
$action = backend_call(\@action_items);
if ($action eq "Replace\n") {
$mpd->clear();
@@ -368,7 +369,10 @@ sub do_action {
foreach my $line (split /\n/, $in) {
my $uri = (split /[\t\n]/, $line)[-1];
$uri = decode('UTF-8', $uri );
- $mpd->sticker_value("song", "$uri", "rating", "$rating")
+ if ($tagging eq "true") {
+ $mpd->sticker_value("song", "$uri", "rating", "$rating");
+ }
+ $mpd->send_message('rating', "$uri\tRATING\t${rating}");
}
}
elsif ($action eq "Add\n" || $action eq "Replace\n") {
@@ -384,17 +388,45 @@ sub do_action {
$mpd->play();
}
} elsif ($context eq "Albums" || $context eq "Latest") {
- my @action_items = ("Add\n", "Replace\n");
+ my @action_items = ("Add\n", "Replace\n", "---\n", "Rate Album\n");
$action = backend_call(\@action_items);
+ if ($action eq "Rate Album\n") {
+ my @rating_value = ("1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n", "10\n");
+ my $rating;
+ $rating = backend_call(\@rating_value);
+ chomp $rating;
+ my $input;
+ foreach my $line (split /\n/, $in) {
+ my $song_tags;
+ my $uri = (split /[\t\n]/, $line)[-1];
+ $uri = decode('UTF-8', $uri );
+ my @files = $mpd->search('filename', $uri);
+ my @song_tags = $files[0];
+ my $artist = $song_tags[0]->{AlbumArtist};
+ my $album = $song_tags[0]->{Album};
+ my $date = $song_tags[0]->{Date};
+ my @songs_to_tag = $mpd->search('albumartist', $artist, 'album', $album, 'date', $date);
+ foreach my $songs (@songs_to_tag) {
+ my $filename = $songs->{uri};
+ $mpd->sticker_value("song", $filename, "albumrating", "$rating");
+ if ($tagging eq "true") {
+ $mpd->send_message('rating', "$filename\tALBUMRATING\t${rating}");
+ }
+ }
+ }
+ }
+
if ($action eq "Replace\n") {
$mpd->clear();
}
- my $input;
- foreach my $line (split /\n/, $in) {
- my $uri = (split /[\t\n]/, $line)[-1];
- $uri = decode('UTF-8', $uri );
- $mpd->add($uri);
- system(@queue_cmd);
+ if ($action eq "Add\n" || $action eq "Replace\n") {
+ my $input;
+ foreach my $line (split /\n/, $in) {
+ my $uri = (split /[\t\n]/, $line)[-1];
+ $uri = decode('UTF-8', $uri );
+ $mpd->add($uri);
+ system(@queue_cmd);
+ }
}
if ($action eq "Replace\n") {
$mpd->play();
diff --git a/clerk.conf b/clerk.conf
index d42e32b..32abf9b 100644
--- a/clerk.conf
+++ b/clerk.conf
@@ -15,8 +15,9 @@ songs=20
# if mpd drops the connection while updating, reduce this.
chunksize=30000
-# rofi theme to use for clerk
-rofi_theme=clerk
+# write tags to audio files. Needs running clerk_rating_client on machine with audio files
+# ratings will always be written to sticker database.
+tagging=false
[Columns]
# width of columns
diff --git a/clerk_rating_client b/clerk_rating_client
new file mode 100755
index 0000000..4d56526
--- /dev/null
+++ b/clerk_rating_client
@@ -0,0 +1,123 @@
+#!/usr/bin/perl
+
+binmode(STDOUT, ":utf8");
+use v5.10;
+use warnings;
+use Array::Utils qw(:all);
+use DDP;
+use File::Spec;
+use strict;
+use utf8;
+use Encode qw(decode encode);
+use File::Find;
+use Getopt::Std;
+use Net::MPD;
+
+my $mpd_host = "tauron";
+my $mpd = Net::MPD->connect($ENV{MPD_HOST} // $mpd_host // 'localhost');
+my $music_root = "/mnt/raid/Audio/Rips";
+
+sub main {
+ my %options=();
+ getopts("rst", \%options);
+
+ if ($options{r} // $options{s} // $options{t}) {
+ if (defined $options{r}) { subscribe_ratings_channel(); track_rating(); }
+ elsif (defined $options{s}) { subscribe_ratings_channel(); sync_ratings(); }
+ elsif (defined $options{t}) { tag_from_sticker(); }
+ } else { subscribe_ratings_channel(); track_rating(); };
+}
+
+sub subscribe_ratings_channel {
+ $mpd->subscribe('rating');
+}
+
+sub track_rating {
+ while(1) {
+ $mpd->idle('message');
+ my @blub = $mpd->read_messages;
+ foreach (@blub) {
+ my $string = $_->{message};
+ my @array = split("\t", $string);
+ my $uri = $array[0];
+ my $mode = $array[1];
+ my $rating = $array[2];
+ $uri = decode('UTF-8', $uri );
+ my @files = $mpd->search('filename', $uri);
+ my @song_tags = $files[0];
+ my $albumartist = $song_tags[0]->{AlbumArtist};
+ my $artist = $song_tags[0]->{Artist};
+ my $title = $song_tags[0]->{Title};
+ my $album = $song_tags[0]->{Album};
+ if ($uri =~ /.*.flac$/) {
+ if ($mode eq "RATING") {
+ print ":: tagging track \"${title}\" by \"${artist}\" with rating of \"${rating}\"\n";
+ } elsif ($mode eq "ALBUMRATING") {
+ print ":: tagging track \"${title}\" by \"${albumartist}\" with albumrating of \"${rating}\"\n";
+ }
+ system('metaflac', '--remove-tag=RATING', "${music_root}/${uri}");
+ system('metaflac', "--set-tag=${mode}=${rating}", "${music_root}/${uri}");
+ }
+ elsif ($uri =~ /.*.mp3$/) {
+ if ($mode eq "RATING") {
+ print ":: tagging track \"${title}\" by \"${artist}\" with rating of \"${rating}\"\n";
+ } elsif ($mode eq "ALBUMRATING") {
+ print ":: tagging track \"${title}\" by \"${albumartist}\" with albumrating of \"${rating}\"\n";
+ }
+ system('mid3v2', "--TXXX:${mode}:${rating}", "${music_root}/${uri}");
+ }
+ elsif ($uri =~ /.*.ogg$/) {
+ print "!! OGG files not supported, yet\n";
+ }
+ }
+ }
+}
+
+sub sync_ratings {
+ my @sticker_uris;
+ my @actual_uris;
+ my @available_stickers = $mpd->sticker_find('song', 'rating', '');
+ foreach my $rated_song (@available_stickers) {
+ push @sticker_uris, "$rated_song->{file}";
+ }
+
+ my @absolute;
+ find({
+ wanted => sub { push @absolute, $_ if -f and -r },
+ no_chdir => 1,
+ }, $music_root);
+ my @relative = map { File::Spec->abs2rel($_, $music_root) } @absolute;
+ push @actual_uris, $_ for @relative;
+
+ my @diff = array_diff(@sticker_uris, @actual_uris);
+ foreach my $unrated_song (@diff) {
+ if ( $unrated_song =~ /.*.flac$/) {
+ my $rating = system('metaflac', '--show-tag=RATING', "${music_root}/${unrated_song}");
+ print "$rating\n";
+ if ($rating ne "0") {
+ print "rating ${music_root}/${unrated_song} with $rating\n";
+ $mpd->sticker_value("song", "$unrated_song", "rating", "$rating");
+ }
+ }
+ }
+}
+
+sub tag_from_sticker {
+ my @available_stickers = $mpd->sticker_find('song', 'rating', '');
+ foreach my $rated_song (@available_stickers) {
+ my $uri = $rated_song->{file};
+ my $rating = $rated_song->{sticker};
+ if ($uri =~ /.*.flac$/) {
+ system('metaflac', '--remove-tag=RATING', "${music_root}/${uri}");
+ system('metaflac', "--set-tag=RATING=$rating", "${music_root}/${uri}");
+ }
+ elsif ($uri =~ /.*.mp3$/) {
+ system('mid3v2', "--TXXX:RATING:${rating}", "${music_root}/${uri}");
+ }
+ elsif ($uri =~ /.*.ogg$/) {
+ print "!! OGG files not supported, yet\n";
+ }
+ }
+}
+
+main();