forked from shatterhand19/RhythmboxPOPM
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRBToPOPM.java
170 lines (152 loc) · 7.25 KB
/
RBToPOPM.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
/**
* Created by bozhidar on 11.10.17.
*/
public class RBToPOPM {
public static HashMap<Integer, Integer> starsToNumber = new HashMap<>();
static {
starsToNumber.putIfAbsent(0, 0);
starsToNumber.putIfAbsent(1, 51);
starsToNumber.putIfAbsent(2, 102);
starsToNumber.putIfAbsent(3, 153);
starsToNumber.putIfAbsent(4, 204);
starsToNumber.putIfAbsent(5, 255);
}
public static final String ANSI_RED = "\u001B[31m";
public static final String ANSI_GREEN = "\u001B[32m";
public static final String ANSI_YELLOW = "\u001B[33m";
public static final String ANSI_RESET = "\u001B[0m";
private static int total = 0;
private static String email = null;
public static void main(String... args) throws ParserConfigurationException, IOException, SAXException, URISyntaxException, InterruptedException, ExecutionException {
//Read flags
if (args.length >= 2) {
email = args[1];
} else {
email = "[email protected]";
}
//Enumerate all the files that are passed to the program
List<String> filenames = new ArrayList<>();
if (args.length >= 1) {
if (!new File(args[0]).isDirectory()) {
filenames = Files.readAllLines(Paths.get(args[0]));
} else {
System.out.println(ANSI_RED + "Song file argument specified is a directory (first argument should be the path to a file containing filenames)" + ANSI_RESET);
return;
}
} else {
System.out.println(ANSI_RED + "No song file argument specified (first argument should be the path to a file containing filenames)" + ANSI_RESET);
return;
}
HashMap<String, File> files = new HashMap<>();
for (String filename : filenames) {
if (!filename.equals("")) files.put(filename, new File(filename));
}
String database = System.getProperty("user.home") + "/.local/share/rhythmbox/rhythmdb.xml";
int threads = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(threads);
System.out.println("Running program on " + threads + " threads");
File db = new File(database);
if (db.canRead()) {
//Read the RB database
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse(db);
doc.getDocumentElement().normalize();
//For all songs
NodeList songs = doc.getElementsByTagName("entry");
for (int i = 0; i < songs.getLength(); i++) {
Node song = songs.item(i);
Element songElement = (Element) song;
Node location = songElement.getElementsByTagName("location").item(0);
if (location != null) {
//Get the filename and if it is one of the requested files
String val = location.getTextContent();
val = val.replace("file://", "");
val = URLDecoder.decode(val, "UTF-8");
if (files.containsKey(val)) {
File toAddPOPM = files.get(val);
boolean fileUpdated = false;
int popmRating = 0;
int playCount = 0;
//Get the rating of Rhythmbox
NodeList rbRatingNodeList = songElement.getElementsByTagName("rating");
int rbRating;
Node rbRatingNode = rbRatingNodeList.item(0);
if (rbRatingNode == null) {
rbRating = 0;
} else {
rbRating = Integer.parseInt(rbRatingNode.getTextContent());
fileUpdated = true;
}
popmRating = starsToNumber.get(rbRating);
//Get the play count of Rhythmbox
NodeList rbPlayCountNodeList = songElement.getElementsByTagName("play-count");
Node rbPlayCountNode = rbPlayCountNodeList.item(0);
if (rbPlayCountNode == null) {
playCount = 0;
} else {
playCount = Integer.parseInt(rbPlayCountNode.getTextContent());
fileUpdated = true;
}
if (fileUpdated) {
// Save the change
final int popmRatingFinal = popmRating;
final int playCountFinal = playCount;
executor.execute(() -> {
try {
addNewPOPM(toAddPOPM, popmRatingFinal, playCountFinal);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
});
//Increment the number of total processed files
total++;
}
}
}
}
executor.shutdown();
} else {
System.out.println("\n" + ANSI_RED + "Cannot read Rhythmbox library file!" + ANSI_RESET + "");
}
System.out.println("\n" + ANSI_GREEN + "Processed " + total + " songs successfully!" + ANSI_RESET + "");
}
public static void addNewPOPM(File toAddPOPM, int popmRating, int playCount) throws IOException, InterruptedException {
String options = "--add-popularity=" + email + ":" + popmRating + ":" + playCount;
/*boolean dryRunDebug = true;
if (dryRunDebug) {
System.out.println(options);
return;
}*/
//Clear out old rating
System.out.println(ANSI_YELLOW + "[Deleting obsolete POPM]\t" + ANSI_RESET + toAddPOPM.getAbsolutePath());
ProcessBuilder pb = new ProcessBuilder("eyeD3", "--remove-frame=POPM", toAddPOPM.getAbsolutePath());
Process p = pb.start();
p.waitFor();
//Add the rating
System.out.println(ANSI_GREEN + "[Adding POPM] [Rating=" + popmRating + ", Play count=" + playCount + "]\t" + ANSI_RESET + toAddPOPM.getAbsolutePath());
pb = new ProcessBuilder("eyeD3", options, toAddPOPM.getAbsolutePath());
Process addRating = pb.start();
addRating.waitFor();
}
}