OSDN Git Service

ConverterからRunnable実装を削除
[coroid/inqubus.git] / frontend / src / saccubus / converter / Converter.java
1 package saccubus.converter;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.concurrent.Callable;
6 import java.util.regex.Matcher;
7 import java.util.regex.Pattern;
8 import saccubus.ConvertStopFlag;
9 import saccubus.converter.filegetter.FileInstanciator;
10 import saccubus.net.TextProgressListener;
11 import yukihane.saccubus.converter.profile.FfmpegOption;
12 import yukihane.saccubus.converter.profile.Profile;
13
14 /**
15  * <p>タイトル: さきゅばす</p>
16  *
17  * <p>説明: ニコニコ動画の動画をコメントつきで保存</p>
18  *
19  * <p>著作権: Copyright (c) 2007 PSI</p>
20  *
21  * <p>会社名: </p>
22  *
23  * @author 未入力
24  * @version 1.0
25  */
26 public class Converter extends AbstractCommand implements Callable<Boolean> {
27
28     private final Profile profile;
29     private final String movieId;
30     private final String time;
31
32     /**
33      * コンバータを構築します.
34      * @param url 対象となる動画のURL.
35      * @param time
36      * @param profile
37      * @param listener
38      * @param flag
39      */
40     public Converter(String url, String time, Profile profile,
41             TextProgressListener listener, ConvertStopFlag flag) {
42         super(listener, flag);
43
44         // TODO 入力欄の値から動画IDの切り出しはGUI側でやるべきだろう
45         final int startIdIdx = url.lastIndexOf("/") + 1;
46         final String altId = url.substring(startIdIdx);
47         final Pattern idPattern = Pattern.compile("([a-z]*\\d+)");
48         final Matcher idMatcher = idPattern.matcher(altId);
49         if (idMatcher.find()) {
50             this.movieId = idMatcher.group(1);
51         } else {
52             throw new IllegalArgumentException("URL/IDの指定が不正です: " + url);
53         }
54
55         this.time = time;
56         this.profile = profile;
57     }
58
59     @Override
60     public Boolean call() throws Exception {
61         boolean result = false;
62         try {
63             result = runConvert();
64         } finally {
65             getStopFlag().finished();
66         }
67         return Boolean.valueOf(result);
68     }
69
70     // TODO Runnableを実装しなくなったので削除する
71     public void run() {
72         try {
73             call();
74         } catch (Exception ex) {
75             String text = (ex.getMessage() != null) ? ex.getMessage() : "予期しないエラー発生のため中断しました。";
76             sendText(text);
77             ex.printStackTrace();
78         }
79     }
80
81     private boolean runConvert() throws IOException, InterruptedException {
82         if (!shouldRun(profile)) {
83             sendText("何もすることがありません");
84             return true;
85         }
86
87         validSetting();
88         final FfmpegOption ov = profile.getFfmpeg().getFfmpegOption();
89
90         sendText("ログイン中");
91
92         final FileInstanciator fi = createInstanciator();
93
94         stopFlagReturn();
95
96         final File videoFile = fi.getVideoFile(getListener());
97
98         stopFlagReturn();
99
100         File commentFile = fi.getCommentFile(getListener());
101
102         stopFlagReturn();
103
104         File tcommFile = fi.getTcommFile(getListener());
105
106         if (!profile.needsConvert()) {
107             sendText("動画・コメントを保存し、変換は行いませんでした。");
108             return true;
109         }
110
111         if (!videoFile.isFile()) {
112             throw new IOException("入力動画ファイルが存在しません:" + videoFile.getPath());
113         }
114
115         if (profile.getOutputFileSetting().isAddComment()) {
116             if (!commentFile.isFile()) {
117                 throw new IOException("入力コメントファイルが存在しません:" + commentFile.getPath());
118             }
119         } else {
120             commentFile = null;
121         }
122
123         if (profile.getOutputFileSetting().isAddTcomment()) {
124             if (!tcommFile.isFile()) {
125                 throw new IOException("入力投稿者コメントファイルが存在しません" + tcommFile.getPath());
126             }
127         } else {
128             tcommFile = null;
129         }
130
131         /*ビデオ名の確定*/
132         File convertedVideoFile;
133         if (!profile.getOutputFileSetting().getFile().isFile()) {
134             String conv_name = fi.getVideoTitle();
135             if (profile.getOutputFileSetting().isAppendPrefixVideoId()) {
136                 conv_name = getVideoIDWithBracket() + conv_name;
137             }
138             convertedVideoFile = new File(profile.getOutputFileSetting().getFile().getFile(),
139                     conv_name + ov.getExtOption());
140         } else {
141             String filename = profile.getOutputFileSetting().getFile().getFile().getPath();
142             if (!filename.endsWith(ov.getExtOption())) {
143                 filename = filename.substring(0, filename.lastIndexOf('.')) + ov.getExtOption();
144                 convertedVideoFile = new File(filename);
145             } else {
146                 convertedVideoFile = profile.getOutputFileSetting().getFile().getFile();
147             }
148         }
149
150         boolean res = new FfmpegCommand(getListener(), getStopFlag(), commentFile, tcommFile, videoFile,
151                 convertedVideoFile, profile.getFfmpeg(), profile.getGeneralSetting()).execute();
152         return res;
153     }
154
155     private FileInstanciator createInstanciator() throws IOException {
156         FileInstanciator fi;
157
158         FileInstanciator.InstanciationType videoType = new FileInstanciator.InstanciationType(profile.getVideoSetting());
159
160         FileInstanciator.CommentInstanciationType commentType = new FileInstanciator.CommentInstanciationType(profile.
161                 getCommentSetting(), profile.getCommentSetting().isSelfAdjustCommentNum(), profile.getCommentSetting().
162                 getBackComment(), profile.getCommentSetting().isReduceComment());
163
164         FileInstanciator.InstanciationType tcommType = new FileInstanciator.InstanciationType(
165                 profile.getCommentSetting());
166
167         fi = FileInstanciator.create(getStopFlag(), videoType, commentType, tcommType, profile.getLoginInfo(), profile.
168                 getProxySetting(), movieId, time);
169         return fi;
170     }
171
172     /**
173      * (ネットワーク設定以外の)設定を検証する.
174      * @throws IllegalArgumentException 設定に不備がある場合.
175      */
176     private void validSetting() {
177         if (profile.needsConvert()) {
178             File a = profile.getFfmpeg().getFfmpeg();
179             if (!a.canRead()) {
180                 throw new IllegalArgumentException("FFmpegが見つかりません。");
181             }
182             if (profile.getFfmpeg().getVhook().getPath().indexOf(' ') >= 0) {
183                 throw new IllegalArgumentException("すいません。現在vhookライブラリには半角空白は使えません。");
184             }
185             a = profile.getFfmpeg().getVhook();
186             if (!a.canRead()) {
187                 throw new IllegalArgumentException("Vhookライブラリが見つかりません。");
188             }
189             a = profile.getFfmpeg().getFont();
190             if (!a.canRead()) {
191                 throw new IllegalArgumentException("フォントが見つかりません。");
192             }
193         }
194     }
195
196     private String getVideoIDWithBracket() {
197         return "[" + movieId + "]";
198     }
199
200     public boolean isConverted() {
201         return getStopFlag().isFinished();
202     }
203
204     @Override
205     public ConvertStopFlag getStopFlag() {
206         return super.getStopFlag();
207     }
208
209     /** @return 何か実行すべき処理があればtrue. */
210     private static boolean shouldRun(Profile profile) {
211         return profile.getOutputFileSetting().isConvert() || needsDownload(profile);
212     }
213
214     /** @return 何かダウンロードするものがあればtrue. */
215     private static boolean needsDownload(Profile profile) {
216         return (profile.getVideoSetting().isDownload() || profile.getCommentSetting().isDownload());
217     }
218 }