-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSyncSubLib.java
294 lines (261 loc) · 8.65 KB
/
SyncSubLib.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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/**
* SyncSubLib.java - Library containing methods for updating subtitle timing.
*
* @author Matt Mokary ( [email protected] )
*/
import java.util.Scanner;
import java.io.*;
// import java.io.FileNotFoundException;
class SyncSubLib {
/*
* Static variables, changed every time update is called.
* There is no constructor or non-static methods, partly to hold true to
* the utility/library feel of it, but also because editing more than one
* file in a session would require creating multiple instances of this
* class if the methods were non-static.
*/
/**
* File with which to work.
*/
private static File f;
/**
* The operation to perform on time data.
* true: addition, false: subtraction
* SEE: static final variables PLUS, MINUS
*/
private static boolean o;
/**
* Magnitude of increments for hours.
*/
private static int h;
/**
* Magnitude of increments for minutes.
*/
private static int m;
/**
* Magnitude of increments for seconds.
*/
private static int s;
/**
* Magnitude of increments for milliseconds.
*/
private static int ms;
/**
* The number of subtitle lines whose times were updates.
*/
private static int numUpdates;
/**
* Coder-friendly representation of the addition operation, which is
* internally represented as the boolean 'true'.
*/
public static final boolean PLUS = true;
/**
* Coder-friendly representation of the subtraction operation, which is
* internally represented as the boolean 'false'.
*/
public static final boolean MINUS = false;
/**
* The only method that needs to be called in order to update the times in
* a .srt file. Gets the ball rolling.
*
* @param fi File object (.srt file) to read in.
* @param op Operation to perform (true = plus, false = minus).
* @param ho Number of hours to shift.
* @param mi Number of minutes to shift.
* @param se Number of seconds to shift.
* @param mse Number of milliseconds to shift.
*/
public static void update (File fi, boolean op, int ho, int mi, int se,
int mse) {
f = fi;
o = op;
h = ho;
m = mi;
s = se;
ms = mse;
numUpdates = 0;
traverseFile();
}
/**
* Moves through the file reading individual lines. Calls the updateLine
* method on each.
*/
private static void traverseFile() {
Scanner in;
String outFile;
BufferedWriter out;
try {
in = new Scanner( f );
outFile = f.getCanonicalPath();
outFile = outFile.substring( 0, outFile.length() - 4 ) +
"(SYNCED).srt";
FileWriter fstream = new FileWriter( outFile );
out = new BufferedWriter( fstream );
while ( in.hasNext() ) {
out.write( updateLine( in.nextLine().split(" --> ") ) + "\n" );
}
out.close();
} catch ( IOException e ) {
System.err.println( "Problem opening or writing to file." );
return;
}
}
/**
* Take a line of the current "in" file, alter if necessary, and write to
* the destination file (current file + "(SYNCED)")
*
* @param l Array representing the line split around " --> "
* @return The updated line to be written to a new file
*/
protected static String updateLine( String[] l ) {
if ( l.length == 2 ) {
String newLine = "";
numUpdates += 1;
newLine += sync( l[0] ) + " --> " + sync( l[1] );
return newLine;
} else {
return l[0];
}
}
/**
* Takes in the 'old' time (format: hh:mm:ss,--- where '-' is ms) and sends
* it to the correct method for modification so that it reflects the time
* change held in plusOrMinus, h, m, s, and ms private variables.
*
* @param time String of format hh:mm:ss,--- where '-' is ms
* @return Similarly-formatted String modified to reflect designated change
*/
private static String sync( String time ) {
String[] sTime = time.split(":|,");
String newTime = o ? plusOp( sTime ) : minusOp( sTime );
return newTime;
}
/**
* Adds the current time increments to the given time, and returns a new,
* similarly-formatted string.
*
* @param time String of format hh:mm:ss,--- where '-' is ms
* @return Similarly-formatted String with time increments added.
*/
private static String plusOp( String[] time ) {
int MS = Integer.parseInt( time[3] );
int S = Integer.parseInt( time[2] );
int M = Integer.parseInt( time[1] );
int H = Integer.parseInt( time[0] );
int carry = 0;
// do math
if ( MS + ms > 999 ) {
MS = MS + ms - 1000;
carry = 1;
} else {
MS += ms;
carry = 0;
}
if ( S + s + carry > 59 ) {
S = S + s + carry - 60;
carry = 1;
} else {
S = S + s + carry;
carry = 0;
}
if ( M + m + carry > 59 ) {
M = M + m + carry - 60;
carry = 1;
} else {
M = M + m + carry;
carry = 0;
}
H = H + h + carry;
if ( H > 99 ) { H = 99; }
String[] b = bufferNums( H, M, S, MS );
return b[0] + ":" + b[1] + ":" + b[2] + "," + b[3];
}
/**
* Subtracts the current time increments from the given time and returns a
* new, similarly-formatted String with the time increments subtracted.
*
* @param time String of format hh:mm:ss,-- where '-' is ms
* @return Similarly-formatted String with time increments subtracted.
*/
private static String minusOp( String[] time ) {
int MS = Integer.parseInt( time[3] );
int S = Integer.parseInt( time[2] );
int M = Integer.parseInt( time[1] );
int H = Integer.parseInt( time[0] );
int carry = 0;
// do math
if ( MS - ms < 0 ) {
MS = ( S == 0 && M == 0 && H == 0 ) ? 0 : MS - ms + 1000;
carry = 1;
} else {
MS -= ms;
carry = 0;
}
if ( S - s - carry < 0 ) {
S = ( M == 0 && H == 0 ) ? 0 : S - s - carry + 60;
carry = 1;
} else {
S = S - s - carry;
carry = 0;
}
if ( M - m - carry < 0 ) {
M = ( H == 0 ) ? 0 : M - m - carry + 60;
carry = 1;
} else {
M = M - m - carry;
carry = 0;
}
H = H - h - carry;
if ( MS < 0 ) { MS = 0; }
if ( S < 0 ) { S = 0; }
if ( M < 0 ) { M = 0; }
if ( H < 0 ) { H = 0; }
String[] b = bufferNums( H, M, S, MS );
return b[0] + ":" + b[1] + ":" + b[2] + "," + b[3];
}
/**
* Buffers the numbers with zeroes if they aren't two (or three, in the
* case of milliseconds) characters long already.
*
* @param H hours
* @param M minutes
* @param S seconds
* @param MS milliseconds
* @return Array of values buffered with zeroes.
*/
private static String[] bufferNums ( int H, int M, int S, int MS ) {
String newH = H < 10 ?
"0" + Integer.toString( H ) : Integer.toString( H );
String newM = M < 10 ?
"0" + Integer.toString( M ) : Integer.toString( M );
String newS = S < 10 ?
"0" + Integer.toString( S ) : Integer.toString( S );
String newMS;
if ( MS < 10 ) {
newMS = "00" + Integer.toString( MS );
} else if ( MS < 100 ) {
newMS = "0" + Integer.toString( MS );
} else {
newMS = Integer.toString( MS );
}
String[] returnStr = { newH, newM, newS, newMS };
return returnStr;
}
/**
* Return the number of lines that were updated in the file.
*
* @return String representing the number of lines that were updated in the
* file.
*/
public static String getNumUpdates() {
return Integer.toString( numUpdates );
}
/* ----------------------- FOR TESTING PURPOSES ----------------------- */
/**
* Method for manually setting time increments. Has protected access so
* that a testing subclass can modify increments to artificial values.
*/
protected static void setData ( boolean O, int H, int M, int S, int MS ) {
o = O; h = H; m = M; s = S; ms = MS;
}
}