OSDN Git Service

producer_consumerパターンでダウンロード,変換処理を実現
authoryukihane <yukihane.feather@gmail.com>
Mon, 29 Aug 2011 03:30:02 +0000 (12:30 +0900)
committeryukihane <yukihane.feather@gmail.com>
Mon, 29 Aug 2011 03:30:02 +0000 (12:30 +0900)
33 files changed:
frontend/__converted/.gitignore [new file with mode: 0644]
frontend/_comment/.gitignore [new file with mode: 0644]
frontend/_video/.gitignore [new file with mode: 0644]
frontend/inqubuslogging.properties [new file with mode: 0644]
frontend/nbproject/project.properties
frontend/out/_converted/.gitignore [deleted file]
frontend/out/comment/.gitignore [deleted file]
frontend/out/commentowner/.gitignore [deleted file]
frontend/out/movie/.gitignore [deleted file]
frontend/src/saccubus/Saccubus.java
frontend/src/saccubus/prompt/Prompt.java
frontend/src/saccubus/worker/ConvertProgress.java [deleted file]
frontend/src/saccubus/worker/DownloadProgress.java [deleted file]
frontend/src/saccubus/worker/TestFrame.java [deleted file]
frontend/src/saccubus/worker/Worker.java [new file with mode: 0644]
frontend/src/saccubus/worker/WorkerListener.java [new file with mode: 0644]
frontend/src/saccubus/worker/convert/Convert.java [moved from frontend/src/saccubus/worker/Convert.java with 92% similarity]
frontend/src/saccubus/worker/convert/ConvertProgress.java [new file with mode: 0644]
frontend/src/saccubus/worker/convert/ConvertResult.java [moved from frontend/src/saccubus/worker/ConvertResult.java with 65% similarity]
frontend/src/saccubus/worker/convert/ConvertStatus.java [new file with mode: 0644]
frontend/src/saccubus/worker/download/Download.java [moved from frontend/src/saccubus/worker/Download.java with 89% similarity]
frontend/src/saccubus/worker/download/DownloadProgress.java [new file with mode: 0644]
frontend/src/saccubus/worker/download/DownloadResult.java [moved from frontend/src/saccubus/worker/DownloadResult.java with 75% similarity]
frontend/src/saccubus/worker/download/DownloadStatus.java [new file with mode: 0644]
frontend/src/yukihane/inqubus/Config.java
frontend/src/yukihane/inqubus/gui/MainFrame.java
frontend/src/yukihane/inqubus/manager/Request.java [new file with mode: 0644]
frontend/src/yukihane/inqubus/manager/RequestProcess.java [new file with mode: 0644]
frontend/src/yukihane/inqubus/manager/TaskKind.java [new file with mode: 0644]
frontend/src/yukihane/inqubus/manager/TaskManage.java [new file with mode: 0644]
frontend/src/yukihane/inqubus/manager/TaskManageListener.java [new file with mode: 0644]
frontend/src/yukihane/inqubus/manager/TaskStatus.java [new file with mode: 0644]
frontend/test/saccubus/worker/ConverterTest.java

diff --git a/frontend/__converted/.gitignore b/frontend/__converted/.gitignore
new file mode 100644 (file)
index 0000000..0cc23fe
--- /dev/null
@@ -0,0 +1,3 @@
+*
+!/.gitignore
+
diff --git a/frontend/_comment/.gitignore b/frontend/_comment/.gitignore
new file mode 100644 (file)
index 0000000..0cc23fe
--- /dev/null
@@ -0,0 +1,3 @@
+*
+!/.gitignore
+
diff --git a/frontend/_video/.gitignore b/frontend/_video/.gitignore
new file mode 100644 (file)
index 0000000..0cc23fe
--- /dev/null
@@ -0,0 +1,3 @@
+*
+!/.gitignore
+
diff --git a/frontend/inqubuslogging.properties b/frontend/inqubuslogging.properties
new file mode 100644 (file)
index 0000000..804b388
--- /dev/null
@@ -0,0 +1,7 @@
+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
index 7f1a12a..3e5c6f9 100644 (file)
@@ -91,10 +91,7 @@ run.classpath=\
     ${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
diff --git a/frontend/out/_converted/.gitignore b/frontend/out/_converted/.gitignore
deleted file mode 100644 (file)
index 241e560..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-
diff --git a/frontend/out/comment/.gitignore b/frontend/out/comment/.gitignore
deleted file mode 100644 (file)
index 241e560..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-
diff --git a/frontend/out/commentowner/.gitignore b/frontend/out/commentowner/.gitignore
deleted file mode 100644 (file)
index 241e560..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-
diff --git a/frontend/out/movie/.gitignore b/frontend/out/movie/.gitignore
deleted file mode 100644 (file)
index 241e560..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-
index 526857c..f1d3b47 100644 (file)
@@ -62,7 +62,7 @@ public class Saccubus {
         * @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);
index 681855b..1242aa6 100644 (file)
@@ -12,7 +12,8 @@ import org.apache.commons.cli.HelpFormatter;
 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;
 
 /**
@@ -37,7 +38,7 @@ 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);
@@ -63,9 +64,9 @@ public class Prompt {
 
         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変換処理が正常に終了しませんでした。");
             }
@@ -142,7 +143,7 @@ public class Prompt {
     /**
      * 昔の引数形式でプログラムを実行する.
      */
-    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];
@@ -160,7 +161,7 @@ public class Prompt {
         System.out.println("VideoID: " + tag);
         System.out.println("WaybackTime: " + time);
         System.out.println("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
-        conv.run();
+        conv.call();
         System.out.println("Finished.");
     }
 }
diff --git a/frontend/src/saccubus/worker/ConvertProgress.java b/frontend/src/saccubus/worker/ConvertProgress.java
deleted file mode 100644 (file)
index 68ce0e9..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package saccubus.worker;
-
-/**
- *
- * @author yuki
- */
-public class ConvertProgress {
-
-    private final String message;
-
-    ConvertProgress(String message) {
-        this.message = message;
-    }
-
-    public String getMessage() {
-        return message;
-    }
-}
diff --git a/frontend/src/saccubus/worker/DownloadProgress.java b/frontend/src/saccubus/worker/DownloadProgress.java
deleted file mode 100644 (file)
index e4035d3..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package saccubus.worker;
-
-/**
- *
- * @author yuki
- */
-public class DownloadProgress {
-
-    private final String message;
-
-    DownloadProgress(String message) {
-        this.message = message;
-    }
-
-    public String getMessage() {
-        return message;
-    }
-}
diff --git a/frontend/src/saccubus/worker/TestFrame.java b/frontend/src/saccubus/worker/TestFrame.java
deleted file mode 100644 (file)
index aaf1c1f..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * 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;
-        }
-    }
-}
diff --git a/frontend/src/saccubus/worker/Worker.java b/frontend/src/saccubus/worker/Worker.java
new file mode 100644 (file)
index 0000000..975eb18
--- /dev/null
@@ -0,0 +1,58 @@
+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);
+        }
+    }
+}
diff --git a/frontend/src/saccubus/worker/WorkerListener.java b/frontend/src/saccubus/worker/WorkerListener.java
new file mode 100644 (file)
index 0000000..2749d6d
--- /dev/null
@@ -0,0 +1,16 @@
+package saccubus.worker;
+
+/**
+ *
+ * @author yuki
+ */
+public interface WorkerListener<T, V> {
+
+    void process(V progress);
+
+    void cancelled();
+
+    void done(T result);
+
+    void error(Throwable th);
+}
@@ -1,8 +1,9 @@
 /* $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;
@@ -14,8 +15,9 @@ import java.util.ArrayList;
 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;
@@ -31,13 +33,17 @@ import yukihane.swf.Cws2Fws;
  * 動画を(コメント付きに)変換するワーカクラス.
  * @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 変換用プロファイル.
@@ -46,14 +52,15 @@ public class Convert extends SwingWorker<ConvertResult, ConvertProgress> {
      * @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, "");
         }
@@ -77,18 +84,18 @@ public class Convert extends SwingWorker<ConvertResult, ConvertProgress> {
             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()) {
@@ -184,7 +191,7 @@ public class Convert extends SwingWorker<ConvertResult, ConvertProgress> {
             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);
                 }
diff --git a/frontend/src/saccubus/worker/convert/ConvertProgress.java b/frontend/src/saccubus/worker/convert/ConvertProgress.java
new file mode 100644 (file)
index 0000000..59387e0
--- /dev/null
@@ -0,0 +1,31 @@
+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);
+    }
+}
@@ -1,4 +1,6 @@
-package saccubus.worker;
+package saccubus.worker.convert;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
 
 /**
  *
@@ -21,4 +23,9 @@ public class ConvertResult {
     public String getTitle() {
         return title;
     }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
 }
diff --git a/frontend/src/saccubus/worker/convert/ConvertStatus.java b/frontend/src/saccubus/worker/convert/ConvertStatus.java
new file mode 100644 (file)
index 0000000..5f87899
--- /dev/null
@@ -0,0 +1,10 @@
+package saccubus.worker.convert;
+
+/**
+ *
+ * @author yuki
+ */
+public enum ConvertStatus {
+
+    READY, PROCESS, DONE, CANCELLED, ERROR;
+}
@@ -1,11 +1,11 @@
-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;
@@ -13,9 +13,10 @@ import nicobrowser.ProgressListener;
 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;
 
@@ -31,12 +32,16 @@ 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.
@@ -45,22 +50,23 @@ public class Download extends SwingWorker<DownloadResult, DownloadProgress> impl
      * @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 {
@@ -72,9 +78,9 @@ public class Download extends SwingWorker<DownloadResult, DownloadProgress> impl
 //        }
 //    }
     @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;
@@ -126,7 +132,7 @@ public class Download extends SwingWorker<DownloadResult, DownloadProgress> impl
                 @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)));
                 }
             });
 
@@ -194,7 +200,6 @@ public class Download extends SwingWorker<DownloadResult, DownloadProgress> impl
 //            }
 //        }
 //    }
-
     /**
      * HttpClientを生成し, ニコニコ動画サーバへログインします.
      * @return 生成したHttpClientインスタンス.
diff --git a/frontend/src/saccubus/worker/download/DownloadProgress.java b/frontend/src/saccubus/worker/download/DownloadProgress.java
new file mode 100644 (file)
index 0000000..c63acae
--- /dev/null
@@ -0,0 +1,31 @@
+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);
+    }
+}
@@ -1,6 +1,7 @@
-package saccubus.worker;
+package saccubus.worker.download;
 
 import java.io.File;
+import org.apache.commons.lang.builder.ToStringBuilder;
 
 /**
  *
@@ -29,4 +30,9 @@ public class DownloadResult {
     public File getDownloadVideo() {
         return downloadVideo;
     }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
 }
diff --git a/frontend/src/saccubus/worker/download/DownloadStatus.java b/frontend/src/saccubus/worker/download/DownloadStatus.java
new file mode 100644 (file)
index 0000000..66580ff
--- /dev/null
@@ -0,0 +1,10 @@
+package saccubus.worker.download;
+
+/**
+ *
+ * @author yuki
+ */
+public enum DownloadStatus {
+
+    READY, PROCESS, DONE, CANCELLED, ERROR;
+}
index e9c7228..68ce880 100644 (file)
@@ -74,7 +74,7 @@ public enum Config {
     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) {
@@ -105,7 +105,7 @@ public enum Config {
     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) {
@@ -136,7 +136,7 @@ public enum Config {
     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) {
index 206f827..2fd268a 100644 (file)
@@ -49,15 +49,24 @@ import org.apache.commons.lang.StringUtils;
 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;
 
@@ -78,6 +87,9 @@ public class MainFrame extends JFrame {
     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() {
@@ -337,16 +349,23 @@ public class MainFrame extends JFrame {
         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
@@ -566,6 +585,54 @@ public class MainFrame extends JFrame {
         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;
@@ -625,6 +692,9 @@ public class MainFrame extends JFrame {
         }
     }
 
+    /*
+     * ここからDownloadProfile作成用クラスの定義
+     */
 
     private class InqubusDownloadProfile implements DownloadProfile {
 
@@ -889,4 +959,280 @@ public class MainFrame extends JFrame {
             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);
+        }
+    }
 }
diff --git a/frontend/src/yukihane/inqubus/manager/Request.java b/frontend/src/yukihane/inqubus/manager/Request.java
new file mode 100644 (file)
index 0000000..b08687a
--- /dev/null
@@ -0,0 +1,10 @@
+package yukihane.inqubus.manager;
+
+/**
+ *
+ * @author yuki
+ */
+public interface Request {
+
+    int getRowId();
+}
diff --git a/frontend/src/yukihane/inqubus/manager/RequestProcess.java b/frontend/src/yukihane/inqubus/manager/RequestProcess.java
new file mode 100644 (file)
index 0000000..0b343af
--- /dev/null
@@ -0,0 +1,41 @@
+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;
+    }
+}
diff --git a/frontend/src/yukihane/inqubus/manager/TaskKind.java b/frontend/src/yukihane/inqubus/manager/TaskKind.java
new file mode 100644 (file)
index 0000000..8cebdbf
--- /dev/null
@@ -0,0 +1,20 @@
+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;
+    }
+}
diff --git a/frontend/src/yukihane/inqubus/manager/TaskManage.java b/frontend/src/yukihane/inqubus/manager/TaskManage.java
new file mode 100644 (file)
index 0000000..35a719e
--- /dev/null
@@ -0,0 +1,166 @@
+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
diff --git a/frontend/src/yukihane/inqubus/manager/TaskManageListener.java b/frontend/src/yukihane/inqubus/manager/TaskManageListener.java
new file mode 100644 (file)
index 0000000..7b58817
--- /dev/null
@@ -0,0 +1,10 @@
+package yukihane.inqubus.manager;
+
+/**
+ *
+ * @author yuki
+ */
+public interface TaskManageListener {
+
+    void process(int id, TaskKind kind, TaskStatus status, double percentage, String message);
+}
diff --git a/frontend/src/yukihane/inqubus/manager/TaskStatus.java b/frontend/src/yukihane/inqubus/manager/TaskStatus.java
new file mode 100644 (file)
index 0000000..a8bb282
--- /dev/null
@@ -0,0 +1,20 @@
+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;
+    }
+}
index 7811620..44e61ee 100644 (file)
@@ -4,7 +4,7 @@
  */
 package saccubus.worker;
 
-import saccubus.worker.Download;
+import saccubus.worker.download.Download;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;