--- /dev/null
+*
+!/.gitignore
+
--- /dev/null
+*
+!/.gitignore
+
--- /dev/null
+*
+!/.gitignore
+
--- /dev/null
+saccubus.level = FINEST\r
+yukihane.inqubus.level = FINEST\r
+\r
+handlers = java.util.logging.ConsoleHandler\r
+\r
+java.util.logging.ConsoleHandler.level = FINEST\r
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter\r
${libs.Rome.classpath}:\\r
${libs.groovy-all.classpath}:\\r
${libs.NekoHtml.classpath}\r
-# Space-separated list of JVM arguments used when running the project\r
-# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value\r
-# or test-sys-prop.name=value to set system properties for unit tests):\r
-run.jvmargs=\r
+run.jvmargs=-Djava.util.logging.config.file=inqubuslogging.properties\r
run.test.classpath=\\r
${javac.test.classpath}:\\r
${build.test.classes.dir}\r
* @param args
* String[]
*/
- public static void main(String[] args) throws IOException {
+ public static void main(String[] args) throws Exception {
//引数が有る場合はCUIで起動
if (args.length > 0) {
Prompt.main(args);
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
-import saccubus.worker.Download;
+import saccubus.worker.download.Download;
+import saccubus.worker.download.DownloadResult;
import saccubus.worker.classic.profile.Profile;
/**
*/
public class Prompt {
- public static void main(String[] args) throws IOException {
+ public static void main(String[] args) throws Exception {
// 第1引数がメールアドレスと思しき時は昔の引数であるとみなしてパース、実行する.
if (args.length > 0 && args[0].contains("@")) {
doWithOldArguments(args);
Download conv = new Download(profile, "dummy0");
ExecutorService es = Executors.newSingleThreadExecutor();
- Future<Boolean> future = es.submit((Callable<Boolean>) conv);
+ final Future<DownloadResult> future = es.submit(conv);
try {
- boolean res = future.get().booleanValue();
+ boolean res = future.get().getResultValue();
if (!res) {
throw new IOException("ffmpeg変換処理が正常に終了しませんでした。");
}
/**
* 昔の引数形式でプログラムを実行する.
*/
- private static void doWithOldArguments(String[] args) throws IOException {
+ private static void doWithOldArguments(String[] args) throws Exception {
String mail = args[0];
String pass = args[1];
String tag = args[2];
System.out.println("VideoID: " + tag);
System.out.println("WaybackTime: " + time);
System.out.println("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
- conv.run();
+ conv.call();
System.out.println("Finished.");
}
}
+++ /dev/null
-package saccubus.worker;
-
-/**
- *
- * @author yuki
- */
-public class ConvertProgress {
-
- private final String message;
-
- ConvertProgress(String message) {
- this.message = message;
- }
-
- public String getMessage() {
- return message;
- }
-}
+++ /dev/null
-package saccubus.worker;
-
-/**
- *
- * @author yuki
- */
-public class DownloadProgress {
-
- private final String message;
-
- DownloadProgress(String message) {
- this.message = message;
- }
-
- public String getMessage() {
- return message;
- }
-}
+++ /dev/null
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package saccubus.worker;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import javax.swing.GroupLayout;
-import javax.swing.JButton;
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-import javax.swing.SwingUtilities;
-import saccubus.worker.profile.CommentProfile;
-import saccubus.worker.profile.ConvertProfile;
-import saccubus.worker.profile.FfmpegProfile;
-import saccubus.worker.profile.GeneralProfile;
-import saccubus.worker.profile.LoginProfile;
-import saccubus.worker.profile.OutputProfile;
-import saccubus.worker.profile.DownloadProfile;
-import saccubus.worker.profile.ProxyProfile;
-import saccubus.worker.profile.VideoProfile;
-
-/**
- *
- * @author yuki
- */
-public class TestFrame extends JFrame {
-
- private static final long serialVersionUID = 1L;
- private final JTextField fldVideoId = new JTextField();
- private final JButton btnDownload = new JButton("DOWNLOAD");
- private final JButton btnCancel = new JButton("Cancel");
- private final JTextField fldStatus = new JTextField();
- private final JButton btnConv = new JButton("Conv");
- private final JButton btnConvCancel = new JButton("ConvCancl");
- private Download downloader;
- private Convert converter;
-
- public TestFrame() {
- JPanel panel = new JPanel();
- GroupLayout lo = new GroupLayout(panel);
- panel.setLayout(lo);
-
- lo.setHorizontalGroup(lo.createParallelGroup()
- .addGroup(lo.createSequentialGroup()
- .addComponent(fldVideoId).addComponent(btnDownload))
- .addGroup(lo.createSequentialGroup()
- .addComponent(fldStatus).addComponent(btnCancel))
- .addGroup(lo.createSequentialGroup()
- .addComponent(btnConv).addComponent(btnConvCancel)));
-
- lo.setVerticalGroup(lo.createSequentialGroup()
- .addGroup(lo.createParallelGroup()
- .addComponent(fldVideoId).addComponent(btnDownload))
- .addGroup(lo.createParallelGroup()
- .addComponent(fldStatus).addComponent(btnCancel))
- .addGroup(lo.createParallelGroup()
- .addComponent(btnConv).addComponent(btnConvCancel)));
-
- setContentPane(panel);
- pack();
-
-
- btnDownload.addActionListener(new DownloadListener());
- btnCancel.addActionListener(new CancelListener());
- btnConv.addActionListener(new ConvertListener());
- btnConvCancel.addActionListener(new ConvCnclListener());
- }
-
- private class ConvCnclListener implements ActionListener {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- if (converter != null) {
- converter.cancel(true);
- }
- }
- }
-
- private class ConvertListener implements ActionListener {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- converter = new Convert(new MyConvProfile(), new File("out/sm8994079.mp4"), new File("out/sm9.xml")) {
-
- @Override
- protected void process(List<ConvertProgress> chunks) {
- ConvertProgress chunk = chunks.get(chunks.size() - 1);
- fldStatus.setText(chunk.getMessage());
- }
-
- @Override
- protected void done() {
- btnConv.setEnabled(true);
- try {
- ConvertResult res = get();
- } catch (InterruptedException ex) {
- ex.printStackTrace();
- } catch (ExecutionException ex) {
- ex.printStackTrace();
- }
- }
- };
-
- btnConv.setEnabled(false);
- converter.execute();
-
- }
- }
-
- private class CancelListener implements ActionListener {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- if (downloader != null) {
- downloader.cancel(true);
- }
- }
- }
-
- private class DownloadListener implements ActionListener {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- downloader = new Download(new MyProfile(), fldVideoId.getText()) {
-
- @Override
- protected void process(List<DownloadProgress> chunks) {
- DownloadProgress chunk = chunks.get(chunks.size() - 1);
- fldStatus.setText(chunk.getMessage());
- }
-
- @Override
- protected void done() {
- btnDownload.setEnabled(true);
- try {
- DownloadResult res = get();
- } catch (InterruptedException ex) {
- ex.printStackTrace();
- } catch (ExecutionException ex) {
- ex.printStackTrace();
- }
- }
- };
-
- btnDownload.setEnabled(false);
- downloader.execute();
-
- }
- }
-
- public static void main(String[] args) {
- SwingUtilities.invokeLater(new Runnable() {
-
- @Override
- public void run() {
- TestFrame view = new TestFrame();
- view.setDefaultCloseOperation(EXIT_ON_CLOSE);
- view.setVisible(true);
- }
- });
- }
-
- private static class MyProfile implements DownloadProfile {
-
- @Override
- public LoginProfile getLoginInfo() {
- return new LoginProfile() {
-
- @Override
- public String getMail() {
- return "yamamoto5_5963@hotmail.com";
- }
-
- @Override
- public String getPassword() {
- return "piyopiyo";
- }
- };
- }
-
- @Override
- public ProxyProfile getProxyProfile() {
- return new ProxyProfile() {
-
- @Override
- public boolean use() {
- return false;
- }
-
- @Override
- public String getHost() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public int getPort() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
- };
- }
-
- @Override
- public VideoProfile getVideoProfile() {
- return new VideoProfile() {
-
- @Override
- public boolean isDownload() {
- return true;
- }
-
- @Override
- public File getDir() {
- return new File("out");
- }
-
- @Override
- public String getFileName() {
- return "{id}";
- }
-
- @Override
- public File getLocalFile() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
- };
- }
-
- @Override
- public CommentProfile getCommentProfile() {
- return new CommentProfile() {
-
- @Override
- public int getLengthRelatedCommentSize() {
- return -1;
- }
-
- @Override
- public boolean isDisablePerMinComment() {
- return false;
- }
-
- @Override
- public int getPerMinCommentSize() {
- return -1;
- }
-
- @Override
- public long getBackLogPoint() {
- return -1;
- }
-
- @Override
- public boolean isDownload() {
- return true;
- }
-
- @Override
- public File getDir() {
- return new File("out");
- }
-
- @Override
- public String getFileName() {
- return "{id}_{title}";
- }
-
- @Override
- public File getLocalFile() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
- };
- }
-
-// @Override
-// public OutputProfile getOutputFileSetting() {
-// return new OutputProfile() {
-//
-// @Override
-// public boolean isConvert() {
-// return false;
-// }
-//
-// @Override
-// public boolean isAddComment() {
-// throw new UnsupportedOperationException("Not supported yet.");
-// }
-//
-// @Override
-// public File getDir() {
-// throw new UnsupportedOperationException("Not supported yet.");
-// }
-//
-// @Override
-// public String getFileName() {
-// throw new UnsupportedOperationException("Not supported yet.");
-// }
-// };
-// }
- @Override
- public GeneralProfile getGeneralProfile() {
- return new GeneralProfile() {
-
- @Override
- public String getReplaceFrom() {
- return "<>\\/#";
- }
-
- @Override
- public String getReplaceTo() {
- return "_";
- }
- };
- }
- }
-
- private class MyConvProfile implements ConvertProfile {
-
- @Override
- public FfmpegProfile getFfmpegOption() {
- return new FfmpegProfile() {
-
- @Override
- public String getExtOption() {
- return "";
- }
-
- @Override
- public String getInOption() {
- return "";
- }
-
- @Override
- public String getMainOption() {
- return "";
- }
-
- @Override
- public String getOutOption() {
- return "-f ipod -g 150 -qcomp 0.7 -qmin 20 -qmax 30 -qdiff 4 -subq 6 -me_range 16 -i_qfactor 0.714286";
- }
-
- @Override
- public String getAvfilterOption() {
- return "";
- }
-
- @Override
- public boolean isResize() {
- return false;
- }
-
- @Override
- public int getResizeWidth() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public int getResizeHeight() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public boolean isAdjustRatio() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
- };
- }
-
- @Override
- public File getFfmpeg() {
- return new File("bin/ffmpeg.exe");
- }
-
- @Override
- public boolean isVhookDisabled() {
- return true;
- }
-
- @Override
- public File getVhook() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public File getTempDir() {
- return new File("out");
- }
-
- @Override
- public File getFont() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public int getFontIndex() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public boolean isCommentOpaque() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public boolean isDisableFontSizeArrange() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public int getShadowIndex() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public boolean isShowConverting() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public int getMaxNumOfComment() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public HideCondition getNgSetting() {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public OutputProfile getOutputProfile() {
- return new OutputProfile() {
-
- @Override
- public File getDir() {
- return new File("out");
- }
-
- @Override
- public String getFileName() {
- return "outconv";
- }
-
- @Override
- public String getVideoId() {
- return "";
- }
-
- @Override
- public String getTitile() {
- return "";
- }
- };
- }
-
- @Override
- public GeneralProfile getGeneralProfile() {
- return new GeneralProfile() {
-
- @Override
- public String getReplaceFrom() {
- return "";
- }
-
- @Override
- public String getReplaceTo() {
- return "";
- }
- };
- }
-
- @Override
- public boolean isConvert() {
- return true;
- }
-
- @Override
- public boolean isCommentOverlay() {
- return false;
- }
- }
-}
--- /dev/null
+package saccubus.worker;
+
+import java.util.concurrent.Callable;
+
+/**
+ * 途中経過を報告できるCallableです.
+ * 通常のcallableのように使用できる他, 途中経過を呼び出し側が受け取れるようリスナを使用することができます.
+ * リスナを使用した場合, 本インスタンスの処理終了は{@link WorkerListener#done(java.lang.Object)}(通常の終了),
+ * {@link WorkerListener#cancelled()}(キャンセルされた),
+ * {@link WorkerListener#error(java.lang.Throwable) }(例外発生)
+ * のいずれかで以て通知されます.
+ *
+ * @author yuki
+ */
+public abstract class Worker<T, V> implements Callable<T> {
+
+ private static int serialNumber = 0;
+ private final int id;
+ private final WorkerListener<T, V> listener;
+
+ public Worker(WorkerListener<T, V> listener) {
+ this.id = ++serialNumber;
+ this.listener = listener;
+ }
+
+ @Override
+ public final T call() throws Exception {
+ try {
+ final T result = work();
+ if (listener != null) {
+ listener.done(result);
+ }
+ return result;
+ } catch (InterruptedException ex) {
+ if( listener != null){
+ listener.cancelled();
+ }
+ throw ex;
+ } catch (Throwable th) {
+ if(listener != null){
+ listener.error(th);
+ }
+ throw th;
+ }
+ }
+
+ protected abstract T work() throws Exception;
+
+ public final int getId() {
+ return id;
+ }
+
+ protected final void publish(V value) {
+ if (listener != null) {
+ listener.process(value);
+ }
+ }
+}
--- /dev/null
+package saccubus.worker;
+
+/**
+ *
+ * @author yuki
+ */
+public interface WorkerListener<T, V> {
+
+ void process(V progress);
+
+ void cancelled();
+
+ void done(T result);
+
+ void error(Throwable th);
+}
/* $Id$ */
-package saccubus.worker;
+package saccubus.worker.convert;
import static org.apache.commons.io.FilenameUtils.getBaseName;
import static org.apache.commons.lang.StringUtils.*;
+import static saccubus.worker.convert.ConvertStatus.*;
import java.io.BufferedReader;
import java.io.File;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.swing.SwingWorker;
import saccubus.conv.ConvertToVideoHook;
+import saccubus.worker.Worker;
+import saccubus.worker.WorkerListener;
import saccubus.worker.profile.ConvertProfile;
import saccubus.worker.profile.ConvertProfile.HideCondition;
import saccubus.worker.profile.FfmpegProfile;
* 動画を(コメント付きに)変換するワーカクラス.
* @author yuki
*/
-public class Convert extends SwingWorker<ConvertResult, ConvertProgress> {
+public class Convert extends Worker<ConvertResult, ConvertProgress> {
private static final Logger logger = Logger.getLogger(Convert.class.getName());
private final ConvertProfile profile;
private final File videoFile;
private final File commentFile;
+ public Convert(ConvertProfile profile, File video, File comment) {
+ this(profile, video, comment, null);
+ }
+
/**
* 変換ワーカコンストラクタ.
* @param profile 変換用プロファイル.
* @param output 変換後出力動画.
* @throws IOException 変換失敗.
*/
- public Convert(ConvertProfile profile, File video, File comment) {
+ public Convert(ConvertProfile profile, File video, File comment, WorkerListener<ConvertResult, ConvertProgress> listener) {
+ super(listener);
this.profile = profile;
this.videoFile = video;
this.commentFile = comment;
}
@Override
- protected ConvertResult doInBackground() throws Exception {
+ protected ConvertResult work() throws Exception {
if (!profile.isConvert()) {
return new ConvertResult(true, "");
}
if (profile.isCommentOverlay()) {
transformedComment = File.createTempFile("vhk", ".tmp", profile.getTempDir());
final HideCondition hide = profile.getNgSetting();
- publish(new ConvertProgress("コメントの中間ファイルへの変換中"));
+ publish(new ConvertProgress(PROCESS, "コメントの中間ファイルへの変換中"));
ConvertToVideoHook.convert(commentFile, transformedComment, hide.getId(), hide.getWord());
}
checkStop();
- publish(new ConvertProgress("動画の変換を開始"));
+ publish(new ConvertProgress(PROCESS, "動画の変換を開始"));
final int code = convert(transformedComment, outputFile);
if (code != 0) {
throw new IOException("ffmpeg実行失敗: " + outputFile.getPath());
}
- publish(new ConvertProgress("変換が正常に終了しました。"));
+ publish(new ConvertProgress(PROCESS, "変換が正常に終了しました。"));
return new ConvertResult(true, outputFile.getName());
} finally {
if (transformedComment != null && transformedComment.exists()) {
String msg;
while ((msg = ebr.readLine()) != null) {
if (msg.startsWith("frame=")) {
- publish(new ConvertProgress(msg));
+ publish(new ConvertProgress(PROCESS, msg));
} else if (!msg.endsWith("No accelerated colorspace conversion found")) {
logger.log(Level.INFO, msg);
}
--- /dev/null
+package saccubus.worker.convert;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+/**
+ *
+ * @author yuki
+ */
+public class ConvertProgress {
+
+ private final ConvertStatus status;
+ private final String message;
+
+ ConvertProgress(ConvertStatus status, String message) {
+ this.status = status;
+ this.message = message;
+ }
+
+ public ConvertStatus getStatus() {
+ return status;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+}
-package saccubus.worker;
+package saccubus.worker.convert;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
/**
*
public String getTitle() {
return title;
}
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
}
--- /dev/null
+package saccubus.worker.convert;
+
+/**
+ *
+ * @author yuki
+ */
+public enum ConvertStatus {
+
+ READY, PROCESS, DONE, CANCELLED, ERROR;
+}
-package saccubus.worker;
+package saccubus.worker.download;
+
+import static saccubus.worker.download.DownloadStatus.*;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
-import java.util.concurrent.Callable;
import java.util.logging.Logger;
-import javax.swing.SwingWorker;
import nicobrowser.GetFlvResult;
import nicobrowser.NamePattern;
import nicobrowser.NicoHttpClient;
import nicobrowser.WayBackInfo;
import nicobrowser.entity.NicoContent.Status;
import org.apache.http.HttpException;
+import saccubus.worker.Worker;
+import saccubus.worker.WorkerListener;
import saccubus.worker.profile.CommentProfile;
import saccubus.worker.profile.GeneralProfile;
-import saccubus.worker.profile.OutputProfile;
import saccubus.worker.profile.DownloadProfile;
import saccubus.worker.profile.ProxyProfile;
* @author 未入力
* @version 1.0
*/
-public class Download extends SwingWorker<DownloadResult, DownloadProgress> implements Callable<Boolean> {
+public class Download extends Worker<DownloadResult, DownloadProgress> {
private static final Logger logger = Logger.getLogger(Download.class.getName());
private final DownloadProfile profile;
private final String videoId;
+ public Download(DownloadProfile profile, String videoId) {
+ this(profile, videoId, null);
+ }
+
/**
* コンバータを構築します.
* @param videoId 対象となる動画のID.
* @param listener
* @param flag
*/
- public Download(DownloadProfile profile, String videoId) {
+ public Download(DownloadProfile profile, String videoId, WorkerListener<DownloadResult, DownloadProgress> listener) {
+ // TODO listener登録
+ super(listener);
this.videoId = videoId;
this.profile = profile;
}
- @Override
- public Boolean call() throws Exception {
- try {
- final DownloadResult result = doInBackground();
- return Boolean.valueOf(result.getResultValue());
- } finally {
- // TODO 何か処理が必要?
-// getStopFlag().finished();
- }
- }
-
+// @Override
+// public Boolean call() throws Exception {
+// try {
+// final DownloadResult result = doInBackground();
+// return Boolean.valueOf(result.getResultValue());
+// } finally {
+// // TODO 何か処理が必要?
+//// getStopFlag().finished();
+// }
+// }
// // TODO Runnableを実装しなくなったので削除する
// public void run() {
// try {
// }
// }
@Override
- protected DownloadResult doInBackground() throws Exception {
+ public DownloadResult work() throws Exception {
- publish(new DownloadProgress("ログイン中"));
+ publish(new DownloadProgress(PROCESS, "ログイン中"));
NicoHttpClient client = null;
nicobrowser.VideoInfo vi = null;
@Override
public void progress(long fileSize, long downloadSize) {
final double vol = (double) downloadSize / (double) fileSize * 100.0;
- publish(new DownloadProgress(String.format("ダウンロード%.2f%%", vol)));
+ publish(new DownloadProgress(PROCESS, String.format("ダウンロード%.2f%%", vol)));
}
});
// }
// }
// }
-
/**
* HttpClientを生成し, ニコニコ動画サーバへログインします.
* @return 生成したHttpClientインスタンス.
--- /dev/null
+package saccubus.worker.download;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+/**
+ *
+ * @author yuki
+ */
+public class DownloadProgress {
+
+ private final DownloadStatus status;
+ private final String message;
+
+ DownloadProgress(DownloadStatus status, String message) {
+ this.status = status;
+ this.message = message;
+ }
+
+ public DownloadStatus getStatus() {
+ return status;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+}
-package saccubus.worker;
+package saccubus.worker.download;
import java.io.File;
+import org.apache.commons.lang.builder.ToStringBuilder;
/**
*
public File getDownloadVideo() {
return downloadVideo;
}
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
}
--- /dev/null
+package saccubus.worker.download;
+
+/**
+ *
+ * @author yuki
+ */
+public enum DownloadStatus {
+
+ READY, PROCESS, DONE, CANCELLED, ERROR;
+}
private static final String FILE_VIDEO_DIR = "file.video.dir";
public String getVideoDir() {
- return config.getString(FILE_VIDEO_DIR, "in/video");
+ return config.getString(FILE_VIDEO_DIR, "_video");
}
public void setVideoDir(String s) {
private static final String FILE_COMMENT_DIR = "file.comment.dir";
public String getCommentDir() {
- return config.getString(FILE_COMMENT_DIR, "in/comment");
+ return config.getString(FILE_COMMENT_DIR, "_comment");
}
public void setCommentDir(String s) {
private static final String FILE_OUTPUT_DIR = "file.output.dir";
public String getOutputDir() {
- return config.getString(FILE_OUTPUT_DIR, "out");
+ return config.getString(FILE_OUTPUT_DIR, "__converted");
}
public void setOutputDir(String s) {
import org.apache.commons.lang.builder.ToStringBuilder;
import saccubus.MainFrame_AboutBox;
import saccubus.util.WayBackTimeParser;
-import saccubus.worker.Download;
+import saccubus.worker.convert.ConvertProgress;
+import saccubus.worker.download.DownloadProgress;
+import saccubus.worker.WorkerListener;
+import saccubus.worker.convert.ConvertResult;
+import saccubus.worker.download.DownloadResult;
import saccubus.worker.profile.CommentProfile;
+import saccubus.worker.profile.ConvertProfile;
import saccubus.worker.profile.DownloadProfile;
+import saccubus.worker.profile.FfmpegProfile;
import saccubus.worker.profile.GeneralProfile;
import saccubus.worker.profile.LoginProfile;
+import saccubus.worker.profile.OutputProfile;
import saccubus.worker.profile.ProxyProfile;
import saccubus.worker.profile.VideoProfile;
import yukihane.Util;
import yukihane.inqubus.Config;
+import yukihane.inqubus.manager.RequestProcess;
+import yukihane.inqubus.manager.TaskManage;
import yukihane.inqubus.model.Target;
import yukihane.inqubus.model.TargetsTableModel;
private static final String FILE_OUTPUTFIELD_TOOLTIP
= "ファイル命名規則入力します。";
private final TargetsTableModel targetModel = new TargetsTableModel();
+ private final TaskManage taskManager;
+ private final DownloadProgressListener downloadProgressListener = new DownloadProgressListener();
+ private final ConvertProgressListener convertProgressListener = new ConvertProgressListener();
/** Creates new form MainFrame */
public MainFrame() {
initInputPanel();
pnlMain.setTransferHandler(new DownloadListTransferHandler());
tblDisplay.setTransferHandler(new TableTransferHandler());
+
+ final Config p = Config.INSTANCE;
+ // TODO コンフィグからスレッド数
+ taskManager = new TaskManage(1, 1);
+
}
private class ApplyActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
- final DownloadProfile prof = new InqubusDownloadProfile();
+ final DownloadProfile downProf = new InqubusDownloadProfile();
final String id = Util.getVideoId(fldId.getText());
- logger.log(Level.INFO, prof.toString());
- new Download(prof, id).execute();
+ final InqubusConvertProfile convProf = new InqubusConvertProfile();
+ logger.log(Level.INFO, downProf.toString());
+ logger.log(Level.INFO, convProf.toString());
+ taskManager.add(new RequestProcess(downProf, id, convProf));
}
}
/** This method is called from within the constructor to
return menuBar;
}
+ private class DownloadProgressListener implements WorkerListener<DownloadResult, DownloadProgress> {
+
+ @Override
+ public void process(DownloadProgress progress) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void cancelled() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void done(DownloadResult result) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void error(Throwable th) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+ private class ConvertProgressListener implements WorkerListener<ConvertResult, ConvertProgress> {
+
+ @Override
+ public void process(ConvertProgress progress) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void cancelled() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void done(ConvertResult result) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void error(Throwable th) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+
+
private class DownloadListTransferHandler extends TransferHandler {
private static final long serialVersionUID = 1L;
}
}
+ /*
+ * ここからDownloadProfile作成用クラスの定義
+ */
private class InqubusDownloadProfile implements DownloadProfile {
return ToStringBuilder.reflectionToString(this);
}
}
+
+ /*
+ * ここからConvertProfile作成用クラスの定義
+ */
+ private class InqubusConvertProfile implements ConvertProfile {
+ private final OutputProfile outputProfile;
+ private final GeneralProfile generalProfile;
+ private final FfmpegProfile ffmpegProfile;
+ private final boolean convert;
+ private final File ffmpeg;
+ private final boolean vhookDisabled;
+ private final boolean commentOverlay;
+ private final File vhook;
+ private final File tmpDir;
+ private final File font;
+ private final int fontIndex;
+ private final boolean commentOpaque;
+ private final boolean disableFontSizeArrange;
+ private final int shadowIndex;
+ private final boolean showConvrting;
+ private final int maxNumOfComment;
+ private final HideCondition ngSetting;
+
+ private InqubusConvertProfile() {
+ final Config p = Config.INSTANCE;
+ this.outputProfile = new InqubusOutputProfile();
+ this.generalProfile = new InqubusGeneralProfile();
+ this.ffmpegProfile = new InqubusFfmpegProfile();
+ this.convert = cbOutputEnable.isSelected();
+ this.ffmpeg = new File(p.getFfmpegPath());
+ // TODO コンフィグに設定なし
+ this.vhookDisabled = false;
+ this.commentOverlay = p.getOutputCommentOverlay();
+ this.vhook = new File(p.getFfmpegDllPath());
+ // TODO コンフィグに設定なし
+ this.tmpDir = new File(".");
+ this.font = new File(p.getFontPath());
+ this.fontIndex = Integer.parseInt(p.getFontIndex());
+ this.commentOpaque = p.getCommentOpaque();
+ this.disableFontSizeArrange = p.getFontSizeArrangeDisable();
+ this.shadowIndex = p.getFontShadow();
+ // TODO コンフィグに設定なし
+ this.showConvrting = true;
+ this.maxNumOfComment = (p.getCommentDisplaySizeDefault()) ? -1 : Integer.parseInt(p.
+ getCommentDisplaySizeManual());
+ this.ngSetting = new InqubusHideCondition();
+ }
+
+ @Override
+ public OutputProfile getOutputProfile() {
+ return this.outputProfile;
+ }
+
+ @Override
+ public GeneralProfile getGeneralProfile() {
+ return this.generalProfile;
+ }
+
+ @Override
+ public FfmpegProfile getFfmpegOption() {
+ return this.ffmpegProfile;
+ }
+
+ @Override
+ public boolean isConvert() {
+ return this.convert;
+ }
+
+ @Override
+ public File getFfmpeg() {
+ return this.ffmpeg;
+ }
+
+ @Override
+ public boolean isVhookDisabled() {
+ return this.vhookDisabled;
+ }
+
+ @Override
+ public boolean isCommentOverlay() {
+ return this.commentOverlay;
+ }
+
+ @Override
+ public File getVhook() {
+ return this.vhook;
+ }
+
+ @Override
+ public File getTempDir() {
+ return this.tmpDir;
+ }
+
+ @Override
+ public File getFont() {
+ return this.font;
+ }
+
+ @Override
+ public int getFontIndex() {
+ return this.fontIndex;
+ }
+
+ @Override
+ public boolean isCommentOpaque() {
+ return this.commentOpaque;
+ }
+
+ @Override
+ public boolean isDisableFontSizeArrange() {
+ return this.disableFontSizeArrange;
+ }
+
+ @Override
+ public int getShadowIndex() {
+ return this.shadowIndex;
+ }
+
+ @Override
+ public boolean isShowConverting() {
+ return this.showConvrting;
+ }
+
+ @Override
+ public int getMaxNumOfComment() {
+ return this.maxNumOfComment;
+ }
+
+ @Override
+ public HideCondition getNgSetting() {
+ return this.ngSetting;
+ }
+
+ @Override
+ public String toString(){
+ return ToStringBuilder.reflectionToString(this);
+ }
+ }
+
+ private class InqubusOutputProfile implements OutputProfile {
+ private final File dir;
+ private final String fileName;
+ private final String videoId;
+ private final String title;
+
+
+ private InqubusOutputProfile(){
+ final Config p = Config.INSTANCE;
+ this.dir = new File(p.getOutputDir());
+ this.fileName = fldOutput.getText();
+ // TODO この時点でのID/Titleはどうするか…
+ this.videoId = "";
+ this.title = "";
+ }
+
+ @Override
+ public File getDir() {
+ return this.dir;
+ }
+
+ @Override
+ public String getFileName() {
+ return this.fileName;
+ }
+
+ @Override
+ public String getVideoId() {
+ return this.videoId;
+ }
+
+ @Override
+ public String getTitile() {
+ return this.title;
+ }
+
+ @Override
+ public String toString(){
+ return ToStringBuilder.reflectionToString(this);
+ }
+ }
+
+ private class InqubusFfmpegProfile implements FfmpegProfile {
+ private final String extOption;
+ private final String inOption;
+ private final String mainOption;
+ private final String outOption;
+ private final String avOption;
+ private final boolean resize;
+ private final int resizeWidth;
+ private final int resizeHeight;
+ private final boolean adjustRatio;
+
+ private InqubusFfmpegProfile() {
+ // TODO FFMPEGオプションは、後でメイン画面でも設定できるようにするかも
+ final Config p = Config.INSTANCE;
+ this.extOption = p.getFfmpegExtension();
+ this.inOption = p.getFfmpegInOption();
+ this.mainOption = p.getFfmpegMainOption();
+ this.outOption = p.getFfmpegOutOption();
+ this.avOption = p.getFfmpegAvOption();
+ this.resize = p.getFfmpegResizeEnable();
+ this.resizeWidth = Integer.parseInt(p.getFfmpegResizeWidth());
+ this.resizeHeight = Integer.parseInt(p.getFfmpegResizeHeight());
+ this.adjustRatio = p.getFfmpegKeepAspect();
+ }
+
+ @Override
+ public String getExtOption() {
+ return this.extOption;
+ }
+
+ @Override
+ public String getInOption() {
+ return this.inOption;
+ }
+
+ @Override
+ public String getMainOption() {
+ return this.mainOption;
+ }
+
+ @Override
+ public String getOutOption() {
+ return this.outOption;
+ }
+
+ @Override
+ public String getAvfilterOption() {
+ return this.avOption;
+ }
+
+ @Override
+ public boolean isResize() {
+ return this.resize;
+ }
+
+ @Override
+ public int getResizeWidth() {
+ return this.resizeWidth;
+ }
+
+ @Override
+ public int getResizeHeight() {
+ return this.resizeHeight;
+ }
+
+ @Override
+ public boolean isAdjustRatio() {
+ return this.adjustRatio;
+ }
+
+ @Override
+ public String toString(){
+ return ToStringBuilder.reflectionToString(this);
+ }
+ }
+
+ private class InqubusHideCondition implements ConvertProfile.HideCondition{
+
+ @Override
+ public String getWord() {
+ // TODO
+ return "";
+ }
+
+ @Override
+ public String getId() {
+ // TODO
+ return "";
+ }
+
+ @Override
+ public String toString(){
+ return ToStringBuilder.reflectionToString(this);
+ }
+ }
}
--- /dev/null
+package yukihane.inqubus.manager;
+
+/**
+ *
+ * @author yuki
+ */
+public interface Request {
+
+ int getRowId();
+}
--- /dev/null
+package yukihane.inqubus.manager;
+
+import saccubus.worker.profile.ConvertProfile;
+import saccubus.worker.profile.DownloadProfile;
+
+/**
+ *
+ * @author yuki
+ */
+public class RequestProcess implements Request {
+
+ private static int serialId;
+ private final int rowId;
+ private final DownloadProfile downloadProfile;
+ private final String videoId;
+ private final ConvertProfile convertProfile;
+
+ public RequestProcess(DownloadProfile download, String videoId, ConvertProfile convert) {
+ this.rowId = ++serialId;
+ this.downloadProfile = download;
+ this.videoId = videoId;
+ this.convertProfile = convert;
+ }
+
+ public ConvertProfile getConvertProfile() {
+ return convertProfile;
+ }
+
+ public DownloadProfile getDownloadProfile() {
+ return downloadProfile;
+ }
+
+ public String getVideoId() {
+ return videoId;
+ }
+
+ @Override
+ public int getRowId() {
+ return rowId;
+ }
+}
--- /dev/null
+package yukihane.inqubus.manager;
+
+/**
+ *
+ * @author yuki
+ */
+public enum TaskKind {
+
+ DOWNLOAD("ダウンロード"), CONVERT("変換");
+ private final String text;
+
+ private TaskKind(String text) {
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+}
--- /dev/null
+package yukihane.inqubus.manager;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import saccubus.worker.WorkerListener;
+import saccubus.worker.convert.Convert;
+import saccubus.worker.convert.ConvertProgress;
+import saccubus.worker.convert.ConvertResult;
+import saccubus.worker.download.Download;
+import saccubus.worker.download.DownloadProgress;
+import saccubus.worker.download.DownloadResult;
+import saccubus.worker.profile.ConvertProfile;
+import saccubus.worker.profile.DownloadProfile;
+
+/**
+ *
+ * @author yuki
+ */
+public class TaskManage {
+ private static final Logger logger = Logger.getLogger(TaskManage.class.getName());
+ private final ExecutorService downloadExecutorService;
+ private final ExecutorService convertExecutorService;
+ private final Map<Integer, ManageTarget<DownloadResult>> downloadTargets = new HashMap<>();
+ private final Map<Integer, ManageTarget<ConvertResult>> convertTargets = new HashMap<>();
+ private final TaskManageListener clientListener;
+
+ public TaskManage() {
+ this(1, 1, null);
+ }
+
+ public TaskManage(int maxDownload, int maxConvert) {
+ this(maxDownload, maxConvert, null);
+ }
+
+ public TaskManage(int maxDownload, int maxConvert, TaskManageListener listener) {
+ downloadExecutorService = Executors.newFixedThreadPool(maxDownload);
+ convertExecutorService = Executors.newFixedThreadPool(maxConvert);
+ this.clientListener = listener;
+ }
+
+ public synchronized boolean add(RequestProcess request) {
+ final DownloadProfile dp = request.getDownloadProfile();
+ final ConvertProfile cp = request.getConvertProfile();
+ if (dp != null && (dp.getVideoProfile().isDownload() || dp.getCommentProfile().isDownload())) {
+ // ダウンロードするものがあればまずダウンロード処理
+ final Download task = new Download(dp, request.getVideoId(),
+ new DownloadListener(request.getRowId()));
+ final Future<DownloadResult> future = downloadExecutorService.submit(task);
+ downloadTargets.put(request.getRowId(), new ManageTarget<>(request, future));
+ return true;
+
+ } else if (cp != null && cp.isConvert()) {
+ final Convert task = new Convert(cp, dp.getVideoProfile().getLocalFile(), dp.getCommentProfile().
+ getLocalFile(), new ConvertListener(request.getRowId()));
+ final Future<ConvertResult> future = convertExecutorService.submit(task);
+ convertTargets.put(request.getRowId(), new ManageTarget<>(request, future));
+ return true;
+ }
+ return false;
+ }
+
+ private class DownloadListener extends TaskManageInnerListener<DownloadResult, DownloadProgress> {
+
+ private DownloadListener(int rowId) {
+ super(rowId);
+ }
+
+ @Override
+ public void done(DownloadResult result) {
+ super.done(result);
+ // TODO 変換が必要なら変換キューに入れる
+ }
+
+ @Override
+ protected TaskKind getKind() {
+ return TaskKind.DOWNLOAD;
+ }
+ }
+
+ private class ConvertListener extends TaskManageInnerListener<ConvertResult, ConvertProgress> {
+
+ private ConvertListener(int rowId) {
+ super(rowId);
+ }
+
+ @Override
+ protected TaskKind getKind() {
+ return TaskKind.CONVERT;
+ }
+ }
+
+ abstract class TaskManageInnerListener<T, V> implements WorkerListener<T, V> {
+
+ private final int rowId;
+
+ protected TaskManageInnerListener(int rowId) {
+ this.rowId = rowId;
+ }
+
+ private void notify(TaskStatus status) {
+ notify(status, 0.0, "");
+ }
+
+ private void notify(TaskStatus status, double percentage, String message) {
+ if (getListener() == null) {
+ return;
+ }
+ getListener().process(rowId, getKind(), status, percentage, message);
+ }
+
+ private TaskManageListener getListener() {
+ return clientListener;
+ }
+
+ protected abstract TaskKind getKind();
+
+ @Override
+ public void process(V progress) {
+ logger.log(Level.FINEST, "process: {0}", progress);
+ // TOOD
+ notify(TaskStatus.DOING, 0.0, "");
+ }
+
+ @Override
+ public void cancelled() {
+ logger.log(Level.FINE, "cancelled: {0}", toString());
+ notify(TaskStatus.CANCELLED);
+ }
+
+ @Override
+ public void done(T result) {
+ logger.log(Level.FINE, "done: {0}", result);
+ notify(TaskStatus.DONE);
+ }
+
+ @Override
+ public void error(Throwable th) {
+ logger.log(Level.SEVERE, "error", th);
+ notify(TaskStatus.ERROR, 0.0, th.getMessage());
+ }
+ }
+
+ class ManageTarget<T> {
+
+ private final RequestProcess request;
+ private final Future<T> future;
+
+ ManageTarget(RequestProcess request, Future<T> future) {
+ this.request = request;
+ this.future = future;
+ }
+
+ Future<T> getFuture() {
+ return future;
+ }
+
+ RequestProcess getRequest() {
+ return request;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+package yukihane.inqubus.manager;
+
+/**
+ *
+ * @author yuki
+ */
+public interface TaskManageListener {
+
+ void process(int id, TaskKind kind, TaskStatus status, double percentage, String message);
+}
--- /dev/null
+package yukihane.inqubus.manager;
+
+/**
+ *
+ * @author yuki
+ */
+public enum TaskStatus {
+
+ READY("待機"), DOING("実行"), DONE("完了"), CANCELLED("キャンセル"), ERROR("エラー");
+ private final String text;
+
+ private TaskStatus(String text) {
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+}
*/
package saccubus.worker;
-import saccubus.worker.Download;
+import saccubus.worker.download.Download;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;