OSDN Git Service

merge.
[coroid/inqubus.git] / frontend / src / saccubus / Converter.java
1 package saccubus;
2
3 import saccubus.filegetter.LoginInfo;
4 import saccubus.filegetter.FileInstanciator;
5 import java.io.BufferedReader;
6 import java.io.File;
7 import java.io.FileInputStream;
8 import java.io.IOException;
9 import java.io.InputStreamReader;
10 import java.io.UnsupportedEncodingException;
11 import java.net.URLEncoder;
12 import java.util.Properties;
13 import saccubus.conv.ConvertToVideoHook;
14 import saccubus.net.TextProgressListener;
15 import yukihane.swf.Cws2Fws;
16
17 /**
18  * <p>\83^\83C\83g\83\8b\82³\82«\82ã\82Î\82·</p>
19  *
20  * <p>\90à\96¾: \83j\83R\83j\83R\93®\89æ\82Ì\93®\89æ\82ð\83R\83\81\83\93\83g\82Â\82«\82Å\95Û\91¶</p>
21  *
22  * <p>\92\98\8dì\8c : Copyright (c) 2007 PSI</p>
23  *
24  * <p>\89ï\8eÐ\96¼: </p>
25  *
26  * @author \96¢\93ü\97Í
27  * @version 1.0
28  */
29 public class Converter extends Thread {
30
31     private static final String VIDEO_URL_PARSER = "http://www.nicovideo.jp/watch/";
32     private static final String TMP_CWS = "fws_tmp.swf";
33     private final ConvertingSetting Setting;
34     private final String Tag;
35     private final String Time;
36     private final TextProgressListener listener;
37     private final ConvertStopFlag StopFlag;
38     private final File commentMiddleFile = new File("./vhook.tmp");
39     private final File tcommMiddleFile = new File("./tcomment.tmp");
40
41     public Converter(String url, String time, ConvertingSetting setting,
42             TextProgressListener listener, ConvertStopFlag flag) {
43         url = url.trim();
44         if (url.startsWith(VIDEO_URL_PARSER)) {
45             int index = url.indexOf('?', VIDEO_URL_PARSER.length());
46             if (index >= 0) {
47                 Tag = url.substring(VIDEO_URL_PARSER.length(), index);
48             } else {
49                 Tag = url.substring(VIDEO_URL_PARSER.length());
50             }
51         } else {
52             Tag = url;
53         }
54         Time = time;
55         Setting = setting;
56         this.listener = listener;
57         StopFlag = flag;
58     }
59
60     @Override
61     public void run() {
62         try {
63             runConvert();
64         } catch (Exception ex) {
65             sendText(ex.getMessage());
66             ex.printStackTrace();
67         } finally {
68             if (commentMiddleFile.exists()) {
69                 commentMiddleFile.delete();
70             }
71             if (tcommMiddleFile.exists()) {
72                 tcommMiddleFile.delete();
73             }
74             StopFlag.finished();
75         }
76     }
77
78     private void runConvert() throws IOException, InterruptedException {
79         if (!shouldRun()) {
80             sendText("\89½\82à\82·\82é\82±\82Æ\82ª\82 \82è\82Ü\82¹\82ñ");
81             return;
82         }
83
84         validSetting();
85         final OptionValue ov = detectOption();
86
87         sendText("\83\8d\83O\83C\83\93\92\86");
88
89         final FileInstanciator fi = createInstanciator();
90
91         stopFlagReturn();
92
93         final File videoFile = fi.getVideoFile(listener);
94
95         stopFlagReturn();
96
97         final File commentFile = fi.getCommentFile(listener);
98
99         stopFlagReturn();
100
101         final File tcommFile = fi.getTcommFile(listener);
102
103         if (!Setting.isSaveConverted()) {
104             sendText("\93®\89æ\81E\83R\83\81\83\93\83g\82ð\95Û\91\82µ\81A\95Ï\8a·\82Í\8ds\82¢\82Ü\82¹\82ñ\82Å\82µ\82½\81B");
105             return;
106         }
107
108         if (Setting.getAddComment()) {
109             sendText("\83R\83\81\83\93\83g\82Ì\92\86\8aÔ\83t\83@\83C\83\8b\82Ö\82Ì\95Ï\8a·\92\86");
110
111             boolean conv = ConvertToVideoHook.convert(commentFile, commentMiddleFile,
112                     Setting.getNG_ID(), Setting.getNG_Word());
113             if (!conv) {
114                 sendText("\83R\83\81\83\93\83g\95Ï\8a·\82É\8e¸\94s\81B\82¨\82»\82ç\82­\90³\8bK\95\\8c»\82Ì\8aÔ\88á\82¢\81H");
115                 return;
116             }
117         }
118
119         stopFlagReturn();
120
121         if (Setting.getAddTcomment()) {
122             sendText("\93\8a\8de\8eÒ\83R\83\81\83\93\83g\82Ì\92\86\8aÔ\83t\83@\83C\83\8b\82Ö\82Ì\95Ï\8a·\92\86");
123
124             boolean conv = ConvertToVideoHook.convert(tcommFile, tcommMiddleFile,
125                     Setting.getNG_ID(), Setting.getNG_Word());
126             if (!conv) {
127                 sendText("\83R\83\81\83\93\83g\95Ï\8a·\82É\8e¸\94s\81B\82¨\82»\82ç\82­\90³\8bK\95\\8c»\82Ì\8aÔ\88á\82¢\81H");
128                 return;
129             }
130         }
131
132         stopFlagReturn();
133
134         sendText("\93®\89æ\82Ì\95Ï\8a·\82ð\8aJ\8en");
135         /*\83r\83f\83I\96¼\82Ì\8am\92è*/
136         File convertedVideoFile;
137         if (Setting.isConvFixFileName()) {
138             if (fi.getVideoTitle() == null) {
139                 sendText("\95Ï\8a·\8cã\82Ì\83r\83f\83I\83t\83@\83C\83\8b\96¼\82ª\8am\92è\82Å\82«\82Ü\82¹\82ñ\81B");
140                 return;
141             }
142             Setting.getConvFixFileNameFolder().mkdir();
143             String conv_name = fi.getVideoTitle();
144             if (!Setting.isNotAddVideoID_Conv()) {//\95t\89Á\82µ\82È\82¢\82È\82ç
145                 conv_name = getVideoIDWithBracket() + conv_name;
146             }
147             convertedVideoFile = new File(Setting.getConvFixFileNameFolder(), conv_name + ov.getExtOption());
148         } else {
149             String filename = Setting.getConvertedVideoFile().getPath();
150             if (!filename.endsWith(ov.getExtOption())) {
151                 filename = filename.substring(0, filename.lastIndexOf('.'))
152                         + ov.getExtOption();
153                 convertedVideoFile = new File(filename);
154             } else {
155                 convertedVideoFile = Setting.getConvertedVideoFile();
156             }
157         }
158         int code;
159         if ((code = converting_video(videoFile, convertedVideoFile, Setting.getAddComment(), commentMiddleFile.getPath(),
160                 Setting.getAddTcomment(), tcommMiddleFile.getPath(), ov)) == 0) {
161             sendText("\95Ï\8a·\82ª\90³\8fí\82É\8fI\97¹\82µ\82Ü\82µ\82½\81B");
162             if (Setting.isDeleteCommentAfterConverting()) {
163                 commentFile.delete();
164             }
165             if (Setting.isDeleteVideoAfterConverting()) {
166                 videoFile.delete();
167             }
168         } else {
169             sendText("\95Ï\8a·\83G\83\89\81[");
170         }
171     }
172
173     private FileInstanciator createInstanciator() throws IOException {
174         FileInstanciator fi;
175         LoginInfo li = new LoginInfo(Setting.getMailAddress(), Setting.getPassword(), Setting.useProxy(),
176                 Setting.getProxy(), Setting.getProxyPort());
177
178         File initVFileName;
179         File vDir;
180         final boolean autoVNaming = Setting.isVideoFixFileName();
181         if (autoVNaming) {
182             initVFileName = Setting.getVideoFixFileNameFolder();
183             vDir = initVFileName;
184         } else {
185             initVFileName = Setting.getVideoFile();
186             vDir = initVFileName.getAbsoluteFile().getParentFile();
187         }
188         if (vDir == null || !vDir.isDirectory()) {
189             throw new IllegalArgumentException("\93ü\97Í\93®\89æ\83f\83B\83\8c\83N\83g\83\8a\82ª\91\8dÝ\82µ\82Ü\82¹\82ñ: " + vDir);
190         }
191         FileInstanciator.InstanciationType<VideoSaveKind> videoType = new FileInstanciator.InstanciationType<VideoSaveKind>(Setting.
192                 getVideoSaveKind(), autoVNaming, initVFileName);
193
194         File initCFileName;
195         File cDir;
196         final boolean autoCNaming = Setting.isCommentFixFileName();
197         if (autoCNaming) {
198             initCFileName = Setting.getCommentFixFileNameFolder();
199             cDir = initCFileName;
200         } else {
201             initCFileName = Setting.getCommentFile();
202             cDir = initCFileName.getAbsoluteFile().getParentFile();
203         }
204         if (cDir == null || !cDir.isDirectory()) {
205             throw new IllegalArgumentException("\93ü\97Í\83R\83\81\83\93\83g\83f\83B\83\8c\83N\83g\83\8a\82ª\91\8dÝ\82µ\82Ü\82¹\82ñ: " + cDir);
206         }
207         FileInstanciator.CommentInstanciationType commentType = new FileInstanciator.CommentInstanciationType(Setting.
208                 isSaveComment(), autoCNaming, initCFileName, Setting.isFixCommentNum(), Setting.getBackComment());
209
210         File initTFileName;
211         File tDir;
212         final boolean autoTNaming = Setting.getTcommentSetting().isAutoFileName();
213         tDir = Setting.getTcommentSetting().getDirectory();
214         if (!tDir.isDirectory()) {
215             throw new IllegalArgumentException("\93ü\97Í\93\8a\8de\8eÒ\83R\83\81\83\93\83g\83f\83B\83\8c\83N\83g\83\8a\82ª\91\8dÝ\82µ\82Ü\82¹\82ñ: " + tDir);
216         }
217         if (autoTNaming) {
218             initTFileName = tDir;
219         } else {
220             initTFileName = new File(tDir, Setting.getTcommentSetting().getFileName());
221         }
222         FileInstanciator.InstanciationType<Boolean> tcommType = new FileInstanciator.InstanciationType<Boolean>(
223                 Setting.getTcommentSetting().isDownload(), autoTNaming, initTFileName);
224
225         fi = FileInstanciator.create(StopFlag, videoType, commentType, tcommType, li, Tag, Time);
226         return fi;
227     }
228
229     /**
230      * (\83l\83b\83g\83\8f\81[\83N\90Ý\92è\88È\8aO\82Ì)\90Ý\92è\82ð\8c\9f\8fØ\82·\82é.
231      * @throws IllegalArgumentException \90Ý\92è\82É\95s\94õ\82ª\82 \82é\8fê\8d\87.
232      */
233     private void validSetting() {
234         if (Setting.isSaveConverted()) {
235             File a = new File(Setting.getFFmpegPath());
236             if (!a.canRead()) {
237                 throw new IllegalArgumentException("FFmpeg\82ª\8c©\82Â\82©\82è\82Ü\82¹\82ñ\81B");
238             }
239             if (Setting.getVhookPath().indexOf(' ') >= 0) {
240                 throw new IllegalArgumentException("\82·\82¢\82Ü\82¹\82ñ\81B\8c»\8dÝvhook\83\89\83C\83u\83\89\83\8a\82É\82Í\94¼\8ap\8bó\94\92\82Í\8eg\82¦\82Ü\82¹\82ñ\81B");
241             }
242             a = new File(Setting.getVhookPath());
243             if (!a.canRead()) {
244                 throw new IllegalArgumentException("Vhook\83\89\83C\83u\83\89\83\8a\82ª\8c©\82Â\82©\82è\82Ü\82¹\82ñ\81B");
245             }
246             a = new File(Setting.getFontPath());
247             if (!a.canRead()) {
248                 throw new IllegalArgumentException("\83t\83H\83\93\83g\82ª\8c©\82Â\82©\82è\82Ü\82¹\82ñ\81B");
249             }
250         } else {
251             if (Setting.isDeleteVideoAfterConverting()) {
252                 throw new IllegalArgumentException("\95Ï\8a·\82µ\82È\82¢\82Ì\82É\81A\93®\89æ\8dí\8f\9c\82µ\82¿\82á\82Á\82Ä\97Ç\82¢\82ñ\82Å\82·\82©\81H");
253             }
254             if (Setting.isDeleteCommentAfterConverting()) {
255                 throw new IllegalArgumentException("\95Ï\8a·\82µ\82È\82¢\82Ì\82É\81A\83R\83\81\83\93\83g\8dí\8f\9c\82µ\82¿\82á\82Á\82Ä\97Ç\82¢\82ñ\82Å\82·\82©\81H");
256             }
257         }
258     }
259
260     /** @return \89½\82©\8eÀ\8ds\82·\82×\82«\8f\88\97\9d\82ª\82 \82ê\82Îtrue. */
261     private boolean shouldRun() {
262         return Setting.isSaveConverted() || needsDownload();
263     }
264
265     /** @return \89½\82©\83_\83E\83\93\83\8d\81[\83h\82·\82é\82à\82Ì\82ª\82 \82ê\82Îtrue. */
266     private boolean needsDownload() {
267         return (Setting.getVideoSaveKind() == VideoSaveKind.SAVE) || Setting.isSaveComment();
268     }
269
270     private void sendText(String text) {
271         listener.setText(text);
272     }
273
274     private int converting_video(File videoFile, File convertedVideoFile, boolean addComment, String vhook_path,
275             boolean addTcomment, String tcommPath, OptionValue ov) throws InterruptedException, IOException {
276         File fwsFile = Cws2Fws.createFws(videoFile, new File(TMP_CWS));
277
278         StringBuffer sb = new StringBuffer();
279         sb.append("\"");
280         sb.append(Setting.getFFmpegPath().replace("\\", "\\\\"));
281         sb.append("\"");
282         sb.append(" -y ");
283         sb.append(ov.getMainOption());
284         sb.append(" ");
285         sb.append(ov.getInOption());
286         sb.append(" -i ");
287         if (fwsFile == null) {
288             sb.append("\"");
289             sb.append(videoFile.getPath().replace("\\", "\\\\"));
290             sb.append("\"");
291         } else {
292             sb.append(fwsFile.getPath().replace("\\", "\\\\"));
293         }
294         sb.append(" ");
295         sb.append(ov.getOutOption());
296         sb.append(" \"");
297         sb.append(convertedVideoFile.getPath().replace("\\", "\\\\"));
298         sb.append("\"");
299         if (!Setting.isVhookDisabled()) {
300             if (!addVhookSetting(sb, addComment, vhook_path, addTcomment, tcommPath)) {
301                 return -1;
302             }
303         }
304         String cmd = sb.substring(0);
305         System.out.println("arg:" + cmd);
306         try {
307             System.out.println("\n\n----\nProcessing FFmpeg...\n----\n\n");
308             Process process = Runtime.getRuntime().exec(cmd);
309             BufferedReader ebr = new BufferedReader(new InputStreamReader(
310                     process.getErrorStream()));
311             String e;
312             while ((e = ebr.readLine()) != null) {
313                 String state = e;
314                 if (state.startsWith("frame=")) {
315                     sendText(state);
316                 } else if (!state.endsWith("No accelerated colorspace conversion found")) {
317                     System.out.println(e);
318                 }
319
320                 try {
321                     stopFlagReturn();
322                 } catch (InterruptedException ex) {
323                     process.destroy();
324                     throw ex;
325                 }
326
327             }
328             process.waitFor();
329             return process.exitValue();
330         } finally {
331             if (fwsFile != null) {
332                 fwsFile.delete();
333             }
334         }
335     }
336
337     private boolean addVhookSetting(StringBuffer sb, boolean addComment, String vhook_path, boolean addTcomment,
338             String tcommPath) {
339         try {
340             sb.append(" -vfilters \"vhext=");
341             sb.append(Setting.getVhookPath().replace("\\", "/"));
342             if (addComment) {
343                 sb.append("|");
344                 sb.append("--data-user:");
345                 sb.append(URLEncoder.encode(vhook_path.replace("\\", "/"), "Shift_JIS"));
346             }
347             if (addTcomment) {
348                 sb.append("|");
349                 sb.append("--data-owner:");
350                 sb.append(URLEncoder.encode(tcommPath.replace("\\", "/"), "Shift_JIS"));
351             }
352             sb.append("|");
353             sb.append("--font:");
354             sb.append(URLEncoder.encode(
355                     Setting.getFontPath().replace("\\", "/"), "Shift_JIS"));
356             sb.append("|");
357             sb.append("--font-index:");
358             sb.append(Setting.getFontIndex());
359             sb.append("|");
360             sb.append("--show-user:");
361             sb.append(Setting.getVideoShowNum());
362             sb.append("|");
363             sb.append("--shadow:");
364             sb.append(Setting.getShadowIndex());
365             sb.append("|");
366             if (Setting.isVhook_ShowConvertingVideo()) {
367                 sb.append("--enable-show-video");
368                 sb.append("|");
369             }
370             if (Setting.isFixFontSize()) {
371                 sb.append("--enable-fix-font-size");
372                 sb.append("|");
373             }
374             if (Setting.isOpaqueComment()) {
375                 sb.append("--enable-opaque-comment");
376             }
377             sb.append("\"");
378             return true;
379         } catch (UnsupportedEncodingException e) {
380             e.printStackTrace();
381             return false;
382         }
383     }
384
385     public boolean isConverted() {
386         return StopFlag.isFinished();
387     }
388
389     private void stopFlagReturn() throws InterruptedException {
390         if (StopFlag.needStop()) {
391             throw new InterruptedException("\92\86\8e~\82µ\82Ü\82µ\82½\81B");
392         }
393     }
394
395     public ConvertStopFlag getStopFlag() {
396         return this.StopFlag;
397     }
398
399     private OptionValue detectOption() {
400         String extOption;
401         String inOption;
402         String outOption;
403         String mainOption;
404         if (Setting.getOptionFile() != null) {
405             try {
406                 Properties prop = new Properties();
407                 prop.loadFromXML(new FileInputStream(Setting.getOptionFile()));
408                 extOption = prop.getProperty("EXT", null);
409                 inOption = prop.getProperty("IN", null);
410                 outOption = prop.getProperty("OUT", null);
411                 mainOption = prop.getProperty("MAIN", null);
412                 if (extOption != null && inOption != null && outOption != null
413                         && mainOption != null) {
414                 } else {
415                     throw new IllegalArgumentException("\95Ï\8a·\83I\83v\83V\83\87\83\93\83t\83@\83C\83\8b\82Ì\93Ç\82Ý\8d\9e\82Ý\82É\8e¸\94s\82µ\82Ü\82µ\82½\81B");
416                 }
417             } catch (IOException ex) {
418                 ex.printStackTrace();
419                 throw new IllegalArgumentException("\95Ï\8a·\83I\83v\83V\83\87\83\93\83t\83@\83C\83\8b\82Ì\93Ç\82Ý\8d\9e\82Ý\82É\8e¸\94s\82µ\82Ü\82µ\82½\81B");
420             }
421         } else {
422             extOption = Setting.getCmdLineOptionExt();
423             inOption = Setting.getCmdLineOptionIn();
424             outOption = Setting.getCmdLineOptionOut();
425             mainOption = Setting.getCmdLineOptionMain();
426         } //\83I\83v\83V\83\87\83\93\82É\8ag\92£\8eq\82ð\8aÜ\82ñ\82Å\82µ\82Ü\82Á\82½\8fê\8d\87\82É\82à\91Î\89\9e\81\99
427         if (!extOption.startsWith(".")) {
428             extOption = "." + extOption;
429         }
430         return new OptionValue(extOption, inOption, outOption, mainOption);
431     }
432
433     private String getVideoIDWithBracket() {
434         return "[" + Tag + "]";
435     }
436 }