OSDN Git Service

d8975bc6e47ba8e3adf9fc7d750e1f243273a300
[coroid/inqubus.git] / frontend / src / yukihane / inqubus / gui / MainFrame.java
1 /*
2  * MainFrame.java
3  *
4  * Created on 2011/05/28, 18:14:51
5  */
6 package yukihane.inqubus.gui;
7
8 import java.awt.Image;
9 import java.awt.ItemSelectable;
10 import java.awt.Toolkit;
11 import java.awt.datatransfer.DataFlavor;
12 import java.awt.datatransfer.Transferable;
13 import java.awt.event.ActionEvent;
14 import java.awt.event.ActionListener;
15 import java.awt.event.FocusEvent;
16 import java.awt.event.FocusListener;
17 import java.awt.event.ItemEvent;
18 import java.awt.event.ItemListener;
19 import java.awt.event.KeyEvent;
20 import java.beans.PropertyChangeEvent;
21 import java.beans.PropertyChangeListener;
22 import java.io.File;
23 import java.io.FilenameFilter;
24 import java.io.IOException;
25 import java.net.URL;
26 import java.nio.file.FileSystem;
27 import java.nio.file.FileSystems;
28 import java.nio.file.Path;
29 import java.util.ArrayList;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Set;
33 import java.util.logging.Level;
34 import java.util.logging.Logger;
35 import java.util.regex.Pattern;
36 import javax.swing.BorderFactory;
37 import javax.swing.DropMode;
38 import javax.swing.GroupLayout;
39 import javax.swing.GroupLayout.Alignment;
40 import javax.swing.JButton;
41 import javax.swing.JCheckBox;
42 import javax.swing.JFrame;
43 import javax.swing.JLabel;
44 import javax.swing.JMenu;
45 import javax.swing.JMenuBar;
46 import javax.swing.JMenuItem;
47 import javax.swing.JOptionPane;
48 import javax.swing.JPanel;
49 import javax.swing.JScrollPane;
50 import javax.swing.JTabbedPane;
51 import javax.swing.JTable;
52 import javax.swing.JTextField;
53 import javax.swing.KeyStroke;
54 import javax.swing.LayoutStyle.ComponentPlacement;
55 import javax.swing.SwingUtilities;
56 import javax.swing.TransferHandler;
57 import javax.swing.WindowConstants;
58 import javax.swing.border.BevelBorder;
59 import org.apache.commons.lang.StringUtils;
60 import org.apache.commons.lang.builder.ToStringBuilder;
61 import saccubus.FfmpegOption;
62 import saccubus.MainFrame_AboutBox;
63 import saccubus.util.WayBackTimeParser;
64 import saccubus.worker.impl.convert.ConvertProgress;
65 import saccubus.worker.impl.download.DownloadProgress;
66 import saccubus.worker.WorkerListener;
67 import saccubus.worker.impl.convert.ConvertResult;
68 import saccubus.worker.impl.download.DownloadResult;
69 import saccubus.worker.profile.CommentProfile;
70 import saccubus.worker.profile.ConvertProfile;
71 import saccubus.worker.profile.DownloadProfile;
72 import saccubus.worker.profile.FfmpegProfile;
73 import saccubus.worker.profile.GeneralProfile;
74 import saccubus.worker.profile.LoginProfile;
75 import saccubus.worker.profile.OutputProfile;
76 import saccubus.worker.profile.ProxyProfile;
77 import saccubus.worker.profile.VideoProfile;
78 import yukihane.Util;
79 import yukihane.inqubus.Config;
80 import yukihane.inqubus.filewatch.FileWatch;
81 import yukihane.inqubus.manager.RequestProcess;
82 import yukihane.inqubus.manager.TaskKind;
83 import yukihane.inqubus.manager.TaskManage;
84 import yukihane.inqubus.manager.TaskManageListener;
85 import yukihane.inqubus.manager.TaskStatus;
86 import yukihane.inqubus.model.Target;
87 import yukihane.inqubus.model.TargetsTableModel;
88
89 /**
90  *
91  * @author yuki
92  */
93 public class MainFrame extends JFrame {
94
95     private static final long serialVersionUID = 1L;
96     private static final Logger logger = Logger.getLogger(MainFrame.class.getName());
97     private static final String ID_FIELD_TOOLTIP = "動画のIDまたはURLを入力します。";
98     private static final String FILE_LOCALBUTTON_TOOLTIP
99             = "<html>ダウンロードする場合はチェックを外します。<br/>ローカルファイルを使用する場合はチェックを入れます。</html>";
100     private static final String FILE_INPUTFIELD_TOOLTIP
101             = "<html>ダウンロードする場合はファイル命名規則を入力します。<br/>"
102             + "ローカルファイルを使用する場合はパスを含むファイル名を入力します。</html>";
103     private static final String FILE_OUTPUTFIELD_TOOLTIP
104             = "ファイル命名規則入力します。";
105     private final TargetsTableModel targetModel = new TargetsTableModel();
106     private final TaskManage taskManager;
107     private final Thread videoFileWatcherThread;
108     private final FileWatch videoFileWatcher;
109
110     /** Creates new form MainFrame */
111     public MainFrame() {
112         final Config p = Config.INSTANCE;
113
114         // ワーカスレッド生成
115         final int thDownload = p.getSystemDownloadThread();
116         final int secDownload = p.getSystemDownloadWait();
117         final int thConvert = p.getSystemConvertThread();
118         taskManager = new TaskManage(thDownload, secDownload, thConvert, new GuiTaskManageListener());
119
120         // TODO ディレクトリ監視スレッド生成
121         final List<String> videoSearchDirs = p.getSearchVideoDirs();
122         videoSearchDirs.add(p.getVideoDir());
123         final FileSystem fs = FileSystems.getDefault();
124         final Set<Path> videoPaths = new HashSet<>(videoSearchDirs.size());
125         for (String s : videoSearchDirs) {
126             videoPaths.add(fs.getPath(s));
127         }
128         videoFileWatcher = new FileWatch(videoPaths);
129         this.videoFileWatcherThread = new Thread(videoFileWatcher);
130         this.videoFileWatcherThread.setDaemon(true);
131
132         final URL url = MainFrame_AboutBox.class.getResource("icon.png");
133         final Image icon1 = Toolkit.getDefaultToolkit().createImage(url);
134         final URL url32 = MainFrame_AboutBox.class.getResource("icon32.png");
135         final Image icon2 = Toolkit.getDefaultToolkit().createImage(url32);
136         final List<Image> images = new ArrayList<>(2);
137         images.add(icon1);
138         images.add(icon2);
139         setIconImages(images);
140
141         final JPanel pnlMain = new JPanel();
142         final JScrollPane scrDisplay = new JScrollPane();
143         tblDisplay = new JTable(targetModel, new TargetsColumnModel());
144         tblDisplay.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
145         final JPanel pnlButton = new JPanel();
146         final JTabbedPane tbpInput = new JTabbedPane();
147         final JPanel pnlInputMain = new JPanel();
148         final JLabel lblId = new JLabel();
149         final JLabel lblVideo = new JLabel();
150         cbVideoLocal = new JCheckBox();
151         cbVideoLocal.setToolTipText(FILE_LOCALBUTTON_TOOLTIP);
152         fldVideo = new JTextField();
153         fldVideo.setToolTipText(FILE_INPUTFIELD_TOOLTIP);
154         final JLabel lblComment = new JLabel();
155
156         fldBackLog.setToolTipText("YYYY/MM/DD hh:mm:ss形式、あるいは1970/01/01からの経過秒を入力します。");
157         cbBackLog.addItemListener(new ItemListener() {
158
159             @Override
160             public void itemStateChanged(ItemEvent e) {
161                 final boolean selected = (e.getStateChange() == ItemEvent.SELECTED);
162                 fldBackLog.setEnabled(selected);
163             }
164         });
165         cbBackLog.addPropertyChangeListener("enabled", new PropertyChangeListener() {
166
167             @Override
168             public void propertyChange(PropertyChangeEvent evt) {
169                 final boolean enabled = ((Boolean) evt.getNewValue()).booleanValue();
170                 final boolean fldEnabled = enabled ? cbBackLog.isSelected() : false;
171                 fldBackLog.setEnabled(fldEnabled);
172             }
173         });
174         cbBackLogReduce.setToolTipText("「コメントの量を減らす」場合はチェックを付けます。");
175
176         cbCommentLocal = new JCheckBox();
177         cbCommentLocal.setToolTipText(FILE_LOCALBUTTON_TOOLTIP);
178         cbCommentLocal.addItemListener(new ItemListener() {
179
180             @Override
181             public void itemStateChanged(ItemEvent e) {
182                 final boolean selected = (e.getStateChange() == ItemEvent.SELECTED);
183                 cbBackLogReduce.setEnabled(!selected);
184                 cbBackLog.setEnabled(!selected);
185             }
186         });
187         fldComment = new JTextField();
188         fldComment.setToolTipText(FILE_INPUTFIELD_TOOLTIP);
189         final JLabel lblOutput = new JLabel();
190         cbOutputEnable = new JCheckBox();
191         fldOutput = new JTextField();
192         fldOutput.setToolTipText(FILE_OUTPUTFIELD_TOOLTIP);
193
194         setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
195
196         btnStop.addActionListener(new StopActionListener());
197         final ApplyActionListener applyListener = new ApplyActionListener();
198         btnApply.addActionListener(applyListener);
199
200         pnlMain.setBorder(BorderFactory.createEtchedBorder());
201
202         tblDisplay.setDropMode(DropMode.INSERT_ROWS);
203         scrDisplay.setViewportView(tblDisplay);
204
205         pnlButton.setBorder(BorderFactory.createEtchedBorder());
206
207         GroupLayout gl_pnlButton = new GroupLayout(pnlButton);
208         pnlButton.setLayout(gl_pnlButton);
209         gl_pnlButton.setHorizontalGroup(
210             gl_pnlButton.createParallelGroup(Alignment.LEADING)
211             .addGroup(gl_pnlButton.createSequentialGroup()
212                 .addContainerGap()
213                 .addComponent(btnStart)
214                 .addPreferredGap(ComponentPlacement.RELATED)
215                 .addComponent(btnStop)
216                 .addPreferredGap(ComponentPlacement.RELATED, 250, Short.MAX_VALUE)
217                 .addComponent(btnDeselect)
218                 .addContainerGap())
219         );
220         gl_pnlButton.setVerticalGroup(
221             gl_pnlButton.createParallelGroup(Alignment.LEADING)
222             .addGroup(gl_pnlButton.createSequentialGroup()
223                 .addContainerGap()
224                 .addGroup(gl_pnlButton.createParallelGroup(Alignment.BASELINE)
225                     .addComponent(btnStart)
226                     .addComponent(btnStop)
227                     .addComponent(btnDeselect))
228                 .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
229         );
230
231         lblId.setText("ID");
232
233
234         fldId = new IdComboBox(videoFileWatcher);
235         fldId.setToolTipText(ID_FIELD_TOOLTIP);
236 //        fldId.addActionListener(applyListener);
237         fldId.addFocusListener(new java.awt.event.FocusAdapter() {
238
239             public void focusLost(java.awt.event.FocusEvent evt) {
240                 idFieldFocusLost(evt);
241             }
242         });
243
244         lblVideo.setText("動画");
245
246         cbVideoLocal.setText("local");
247         cbVideoLocal.addItemListener(new java.awt.event.ItemListener() {
248
249             public void itemStateChanged(java.awt.event.ItemEvent evt) {
250                 useMovieLocalCheckBoxItemStateChanged(evt);
251             }
252         });
253
254         lblComment.setText("コメント");
255
256         cbCommentLocal.setText("local");
257         cbCommentLocal.addItemListener(new java.awt.event.ItemListener() {
258
259             public void itemStateChanged(java.awt.event.ItemEvent evt) {
260                 useMovieLocalCheckBoxItemStateChanged(evt);
261             }
262         });
263
264         lblOutput.setText("出力");
265
266         cbOutputEnable.setText("変換");
267         cbOutputEnable.addItemListener(new java.awt.event.ItemListener() {
268
269             public void itemStateChanged(java.awt.event.ItemEvent evt) {
270                 outputConvertCheckBoxItemStateChanged(evt);
271             }
272         });
273
274
275         final GroupLayout glInputMain = new GroupLayout(pnlInputMain);
276         pnlInputMain.setLayout(glInputMain);
277         glInputMain.setHorizontalGroup(
278             glInputMain.createParallelGroup(Alignment.LEADING)
279             .addGroup(glInputMain.createSequentialGroup()
280                 .addContainerGap()
281                 .addComponent(lblId)
282                 .addPreferredGap(ComponentPlacement.RELATED)
283                 .addComponent(fldId, GroupLayout.PREFERRED_SIZE, 100, Short.MAX_VALUE)
284                 .addPreferredGap(ComponentPlacement.UNRELATED)
285                 .addComponent(cbBackLogReduce)
286                 .addPreferredGap(ComponentPlacement.UNRELATED)
287                 .addComponent(cbBackLog)
288                 .addPreferredGap(ComponentPlacement.RELATED)
289                 .addComponent(fldBackLog, GroupLayout.PREFERRED_SIZE, 150, GroupLayout.PREFERRED_SIZE)
290                 .addContainerGap()
291             )
292             .addGroup(glInputMain.createSequentialGroup()
293                 .addContainerGap()
294                 .addGroup(glInputMain.createParallelGroup(Alignment.LEADING)
295                     .addComponent(lblVideo)
296                     .addComponent(lblComment)
297                     .addComponent(lblOutput)
298                 )
299                 .addPreferredGap(ComponentPlacement.RELATED)
300                 .addGroup(glInputMain.createParallelGroup(Alignment.LEADING)
301                     .addComponent(cbVideoLocal)
302                     .addComponent(cbCommentLocal)
303                     .addComponent(cbOutputEnable)
304                 )
305                 .addPreferredGap(ComponentPlacement.RELATED)
306                 .addGroup(glInputMain.createParallelGroup(Alignment.LEADING)
307                     .addComponent(fldVideo, GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
308                     .addComponent(fldComment, GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
309                     .addComponent(fldOutput, GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
310                 )
311                 .addContainerGap()
312             )
313         );
314
315         glInputMain.setVerticalGroup(
316             glInputMain.createParallelGroup(Alignment.LEADING)
317             .addGroup(glInputMain.createSequentialGroup()
318                 .addContainerGap()
319                 .addGroup(glInputMain.createParallelGroup(Alignment.BASELINE)
320                     .addComponent(fldId, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
321                     .addComponent(lblId)
322                     .addComponent(cbBackLogReduce)
323                     .addComponent(cbBackLog)
324                     .addComponent(fldBackLog)
325                 )
326                 .addPreferredGap(ComponentPlacement.RELATED)
327                 .addGroup(glInputMain.createParallelGroup(Alignment.BASELINE)
328                     .addComponent(lblVideo)
329                     .addComponent(fldVideo, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
330                     .addComponent(cbVideoLocal))
331                 .addPreferredGap(ComponentPlacement.RELATED)
332                 .addGroup(glInputMain.createParallelGroup(Alignment.BASELINE)
333                     .addComponent(lblComment)
334                     .addComponent(fldComment, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
335                     .addComponent(cbCommentLocal))
336                 .addPreferredGap(ComponentPlacement.RELATED)
337                 .addGroup(glInputMain.createParallelGroup(Alignment.BASELINE)
338                     .addComponent(lblOutput)
339                     .addComponent(fldOutput, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
340                     .addComponent(cbOutputEnable)
341                 )
342             )
343         );
344
345         // ffmpeg入力パネル
346         pnlInputFfmpeg.fldFfmpegOptionResizeWidth.setEnabled(false);
347         pnlInputFfmpeg.fldFfmpegOptionResizeHeight.setEnabled(false);
348         pnlInputFfmpeg.cbFfmpegOptionKeepAspect.setEnabled(false);
349         pnlInputFfmpeg.cmbFfmpegOptionFile.addActionListener(new ActionListener() {
350
351             @Override
352             public void actionPerformed(ActionEvent e) {
353                 final boolean notFile = !pnlInputFfmpeg.mdlFfmpegOption.isFile();
354                 pnlInputFfmpeg.fldFfmpegOptionExtension.setEnabled(notFile);
355                 pnlInputFfmpeg.fldFfmpegOptionMain.setEnabled(notFile);
356                 pnlInputFfmpeg.fldFfmpegOptionIn.setEnabled(notFile);
357                 pnlInputFfmpeg.fldFfmpegOptionOut.setEnabled(notFile);
358                 pnlInputFfmpeg.fldFfmpegOptionAv.setEnabled(notFile);
359                 pnlInputFfmpeg.cbFfmpegOptionResize.setEnabled(notFile);
360             }
361         });
362         pnlInputFfmpeg.cbFfmpegOptionResize.addItemListener(new ItemListener() {
363
364             @Override
365             public void itemStateChanged(ItemEvent e) {
366                 final boolean selected = (e.getStateChange() == ItemEvent.SELECTED);
367                 pnlInputFfmpeg.fldFfmpegOptionResizeWidth.setEnabled(selected);
368                 pnlInputFfmpeg.fldFfmpegOptionResizeHeight.setEnabled(selected);
369                 pnlInputFfmpeg.cbFfmpegOptionKeepAspect.setEnabled(selected);
370             }
371         });
372         pnlInputFfmpeg.cbFfmpegOptionResize.addPropertyChangeListener("enabled", new PropertyChangeListener() {
373
374             @Override
375             public void propertyChange(PropertyChangeEvent evt) {
376                 final boolean enabled = ((Boolean) evt.getNewValue()).booleanValue();
377                 final boolean fldEnabled = enabled ? pnlInputFfmpeg.cbFfmpegOptionResize.isSelected() : false;
378                 pnlInputFfmpeg.fldFfmpegOptionResizeWidth.setEnabled(fldEnabled);
379                 pnlInputFfmpeg.fldFfmpegOptionResizeHeight.setEnabled(fldEnabled);
380                 pnlInputFfmpeg.cbFfmpegOptionKeepAspect.setEnabled(fldEnabled);
381             }
382         });
383
384
385         tbpInput.add("メイン", pnlInputMain);
386         tbpInput.add("ffmpeg", pnlInputFfmpeg);
387
388         // 入力部のボタンやメッセージ表示部
389         fldInputMessage.setEditable(false);
390         fldInputMessage.setEnabled(false);
391         fldInputMessage.setBorder(BorderFactory.createEmptyBorder());
392
393         final JPanel pnlInputButton = new JPanel();
394         final GroupLayout glInputButton = new GroupLayout(pnlInputButton);
395         pnlInputButton.setLayout(glInputButton);
396         glInputButton.setHorizontalGroup(glInputButton.createSequentialGroup()
397             .addContainerGap()
398             .addComponent(fldInputMessage, GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
399             .addPreferredGap(ComponentPlacement.UNRELATED)
400             .addComponent(btnApply)
401             .addContainerGap()
402         );
403         glInputButton.setVerticalGroup(glInputButton.createSequentialGroup()
404             .addContainerGap()
405             .addGroup(glInputButton.createParallelGroup(Alignment.BASELINE)
406                 .addComponent(fldInputMessage, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
407                 .addComponent(btnApply)
408             )
409             .addContainerGap()
410         );
411
412         // 画面下半分の入力部分
413         final JPanel pnlInputAll = new JPanel();
414         pnlInputAll.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
415         final GroupLayout glInputAll = new GroupLayout(pnlInputAll);
416         pnlInputAll.setLayout(glInputAll);
417         glInputAll.setHorizontalGroup(glInputAll.createParallelGroup()
418             .addComponent(tbpInput)
419             .addComponent(pnlInputButton)
420         );
421         glInputAll.setVerticalGroup(glInputAll.createSequentialGroup()
422             .addComponent(tbpInput)
423             .addComponent(pnlInputButton)
424         );
425
426         GroupLayout gl_pnlMain = new GroupLayout(pnlMain);
427         pnlMain.setLayout(gl_pnlMain);
428         gl_pnlMain.setHorizontalGroup(
429             gl_pnlMain.createParallelGroup(Alignment.LEADING)
430             .addGroup(Alignment.TRAILING, gl_pnlMain.createSequentialGroup()
431                 .addContainerGap()
432                 .addGroup(gl_pnlMain.createParallelGroup(Alignment.TRAILING)
433                     .addComponent(scrDisplay, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 480, Short.MAX_VALUE)
434                     .addComponent(pnlButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
435                     .addComponent(pnlInputAll, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
436                 )
437                 .addContainerGap())
438         );
439         gl_pnlMain.setVerticalGroup(
440             gl_pnlMain.createParallelGroup(Alignment.LEADING)
441             .addGroup(Alignment.TRAILING, gl_pnlMain.createSequentialGroup()
442                 .addContainerGap()
443                 .addComponent(scrDisplay, GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE)
444                 .addPreferredGap(ComponentPlacement.RELATED)
445                 .addComponent(pnlButton, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
446                 .addPreferredGap(ComponentPlacement.RELATED)
447                 .addComponent(pnlInputAll, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
448                 .addContainerGap()
449             )
450         );
451
452
453         JMenuBar menuBar = initMenuBar();
454         setJMenuBar(menuBar);
455
456         GroupLayout layout = new GroupLayout(getContentPane());
457         getContentPane().setLayout(layout);
458         layout.setHorizontalGroup(
459             layout.createParallelGroup(Alignment.LEADING)
460             .addComponent(pnlMain, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
461         );
462         layout.setVerticalGroup(
463             layout.createParallelGroup(Alignment.LEADING)
464             .addComponent(pnlMain, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
465         );
466
467         pack();
468         initInputPanel();
469         pnlMain.setTransferHandler(new DownloadListTransferHandler());
470         tblDisplay.setTransferHandler(new TableTransferHandler());
471     }
472
473     public void startWatcher() {
474         videoFileWatcherThread.start();
475     }
476
477     private class GuiTaskManageListener implements TaskManageListener {
478
479         @Override
480         public void process(final int id, final TaskKind kind, final TaskStatus status, final double percentage,
481                 final String message) {
482             SwingUtilities.invokeLater(new Runnable() {
483
484                 @Override
485                 public void run() {
486                     targetModel.setStatus(id, kind, status, percentage, message);
487                 }
488             });
489         }
490     }
491
492     private class StopActionListener implements ActionListener {
493
494         @Override
495         public void actionPerformed(ActionEvent e) {
496             final int row = tblDisplay.getSelectedRow();
497             final Target t = targetModel.getTarget(row);
498             final boolean res = taskManager.cancel(t.getRowId());
499             logger.log(Level.FINE, "停止: {0} {1}", new Object[]{t.getVideoId(), res});
500             if (res) {
501                 targetModel.setStatus(t.getRowId(), null, TaskStatus.CANCELLED, -1.0, "キャンセル");
502             }
503         }
504     }
505
506     private class ApplyActionListener implements ActionListener {
507
508         @Override
509         public void actionPerformed(ActionEvent e) {
510             try {
511                 final DownloadProfile downProf = new InqubusDownloadProfile();
512                 final String id = Util.getVideoId(fldId.getText());
513                 final InqubusConvertProfile convProf = new InqubusConvertProfile();
514                 logger.log(Level.INFO, downProf.toString());
515                 logger.log(Level.INFO, convProf.toString());
516                 final RequestProcess rp = new RequestProcess(downProf, id, convProf);
517                 taskManager.add(rp);
518                 targetModel.addTarget(new Target(rp));
519                 initInputPanel();
520             } catch (Throwable th) {
521                 logger.log(Level.SEVERE, null, th);
522                 JOptionPane.showMessageDialog(MainFrame.this, th.getMessage(), "中断しました", JOptionPane.ERROR_MESSAGE);
523             }
524         }
525     }
526
527     private File searchFileMatchId(final File dir, final String id) {
528         // TODO 候補は複数返すようにして、その後の対処は呼び出しもとで行ってもらった方が良いかも
529         if (id.isEmpty()) {
530             return null;
531         }
532
533         final File[] lists = dir.listFiles(new FilenameFilter() {
534
535             final Pattern pattern = Pattern.compile(id + "\\D");
536
537             @Override
538             public boolean accept(File dir, String name) {
539                 return pattern.matcher(name).find();
540             }
541         });
542
543         if (lists.length == 1) {
544             return lists[0];
545         } else if (lists.length > 1) {
546             throw new UnsupportedOperationException();
547         } else {
548             return null;
549         }
550     }
551
552     /**
553      * 動画, コメントの"local"チェックボックス更新時の処理.
554      */
555     private void useMovieLocalCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_useMovieLocalCheckBoxItemStateChanged
556         final Config p = Config.INSTANCE;
557
558         final ItemSelectable source = evt.getItemSelectable();
559
560         JTextField field;
561         File dir;
562         if (source == cbVideoLocal) {
563             field = fldVideo;
564             dir = new File(p.getVideoDir());
565         } else {
566             field = fldComment;
567             dir = new File(p.getCommentDir());
568         }
569
570         final boolean useLocal = (evt.getStateChange() == ItemEvent.SELECTED);
571
572         String text;
573         if (useLocal) {
574             final File f = searchFileMatchId(dir, fldId.getText());
575             if (f != null) {
576                 text = f.getPath();
577             } else {
578                 text = "";
579             }
580         } else {
581             text = p.getVideoFileNamePattern();
582         }
583         field.setText(text);
584
585     }//GEN-LAST:event_useMovieLocalCheckBoxItemStateChanged
586
587     private void outputConvertCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_outputConvertCheckBoxItemStateChanged
588         final boolean convert = (evt.getStateChange() == ItemEvent.SELECTED);
589         fldOutput.setEnabled(convert);
590     }//GEN-LAST:event_outputConvertCheckBoxItemStateChanged
591
592     private void idFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_idFieldFocusLost
593         final Config p = Config.INSTANCE;
594         final String id = fldId.getText();
595         if (id.isEmpty()) {
596             return;
597         }
598
599         if (cbVideoLocal.isSelected() && fldVideo.getText().isEmpty()) {
600             final File dir = new File(p.getVideoDir());
601             final File file = searchFileMatchId(dir, id);
602             if (file != null) {
603                 fldVideo.setText(file.getPath());
604             }
605         }
606
607         if (cbCommentLocal.isSelected() && fldComment.getText().isEmpty()) {
608             final File dir = new File(p.getCommentDir());
609             final File file = searchFileMatchId(dir, id);
610             if (file != null) {
611                 fldComment.setText(file.getPath());
612             }
613         }
614
615     }//GEN-LAST:event_idFieldFocusLost
616     // Variables declaration - do not modify//GEN-BEGIN:variables
617     private final JTable tblDisplay;
618     // ボタン領域
619     private final JButton btnStart = new JButton("開始");
620     private final JButton btnStop = new JButton("停止");
621     private final JButton btnDeselect = new JButton("選択解除");
622     // 入力領域 - メイン
623     private final IdComboBox fldId;
624     private final JCheckBox cbBackLogReduce = new JCheckBox("コメ数減少");
625     private final JCheckBox cbBackLog = new JCheckBox("過去ログ");
626     private final JTextField fldBackLog = new JTextField();
627     private final JCheckBox cbVideoLocal;
628     private final JTextField fldVideo;
629     private final JCheckBox cbCommentLocal;
630     private final JTextField fldComment;
631     private final JCheckBox cbOutputEnable;
632     private final JTextField fldOutput;
633     // 入力領域 - ffmpeg
634     private final FfmpegParamPanel pnlInputFfmpeg = new FfmpegParamPanel();
635     // 適用
636     private final JTextField fldInputMessage = new JTextField();
637     private final JButton btnApply = new JButton("適用");
638     // End of variables declaration//GEN-END:variables
639
640     private void initInputPanel() {
641         initMainTab();
642         initFfmpegTab();
643     }
644
645     private void initMainTab() {
646         final Config p = Config.INSTANCE;
647
648         fldId.setText("");
649         fldBackLog.setEnabled(false);
650         cbBackLog.setEnabled(true);
651
652         final boolean movieLocal = p.getVideoUseLocal();
653         cbVideoLocal.setSelected(movieLocal);
654         if (!movieLocal) {
655             fldVideo.setText(p.getVideoFileNamePattern());
656         }
657
658         final boolean commentLocal = p.getCommentUseLocal();
659         cbCommentLocal.setSelected(commentLocal);
660         if (!commentLocal) {
661             fldComment.setText(p.getCommentFileNamePattern());
662         }
663
664         final boolean convert = p.getOutputEnable();
665         cbOutputEnable.setSelected(convert);
666         fldOutput.setEnabled(convert);
667         fldOutput.setText(p.getOutputFileNamePattern());
668     }
669
670     private void initFfmpegTab() {
671         pnlInputFfmpeg.init(Config.INSTANCE);
672     }
673
674     private JMenuBar initMenuBar() {
675         final JMenuBar menuBar = new JMenuBar();
676
677         final JMenu mnFile = new JMenu("ファイル(F)");
678         menuBar.add(mnFile);
679
680         final JMenuItem itExit = new JMenuItem("終了(X)", KeyEvent.VK_X);
681         itExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
682         itExit.addActionListener(new ActionListener() {
683
684             @Override
685             public void actionPerformed(ActionEvent e) {
686                 throw new UnsupportedOperationException("Not supported yet.");
687             }
688         });
689         mnFile.add(itExit);
690
691         final JMenu mnTool = new JMenu("ツール(T)");
692         menuBar.add(mnTool);
693
694         final JMenuItem itOption = new JMenuItem("オプション(O)...", KeyEvent.VK_O);
695         // TODO ショートカットキー
696         itOption.addActionListener(new ActionListener() {
697
698             @Override
699             public void actionPerformed(ActionEvent e) {
700                 final yukihane.inqubus.gui.ConfigDialog dlg = new yukihane.inqubus.gui.ConfigDialog(MainFrame.this);
701                 dlg.setLocationRelativeTo(MainFrame.this);
702                 dlg.setModal(true);
703                 dlg.setVisible(true);
704             }
705         });
706         mnTool.add(itOption);
707
708         final JMenu mnHelp = new JMenu("ヘルプ(H)");
709         menuBar.add(mnHelp);
710
711         final JMenuItem itAbout = new JMenuItem("このソフトウェアについて(A)...", KeyEvent.VK_A);
712         itAbout.addActionListener(new ActionListener() {
713
714             @Override
715             public void actionPerformed(ActionEvent e) {
716                 MainFrame_AboutBox dlg = new MainFrame_AboutBox(MainFrame.this);
717                 dlg.pack();
718                 dlg.setLocationRelativeTo(MainFrame.this);
719                 dlg.setModal(true);
720                 dlg.setVisible(true);
721             }
722         });
723         mnHelp.add(itAbout);
724
725         return menuBar;
726     }
727
728     private class DownloadProgressListener implements WorkerListener<DownloadResult, DownloadProgress> {
729
730         @Override
731         public void process(DownloadProgress progress) {
732             throw new UnsupportedOperationException("Not supported yet.");
733         }
734
735         @Override
736         public void cancelled() {
737             throw new UnsupportedOperationException("Not supported yet.");
738         }
739
740         @Override
741         public void done(DownloadResult result) {
742             throw new UnsupportedOperationException("Not supported yet.");
743         }
744
745         @Override
746         public void error(Throwable th) {
747             throw new UnsupportedOperationException("Not supported yet.");
748         }
749     }
750
751     private class ConvertProgressListener implements WorkerListener<ConvertResult, ConvertProgress> {
752
753         @Override
754         public void process(ConvertProgress progress) {
755             throw new UnsupportedOperationException("Not supported yet.");
756         }
757
758         @Override
759         public void cancelled() {
760             throw new UnsupportedOperationException("Not supported yet.");
761         }
762
763         @Override
764         public void done(ConvertResult result) {
765             throw new UnsupportedOperationException("Not supported yet.");
766         }
767
768         @Override
769         public void error(Throwable th) {
770             throw new UnsupportedOperationException("Not supported yet.");
771         }
772     }
773
774
775
776     private class DownloadListTransferHandler extends TransferHandler {
777
778         private static final long serialVersionUID = 1L;
779         private final Pattern movieIdPattern = Pattern.compile("(\\w\\w\\d+)");
780
781         @Override
782         public boolean canImport(TransferHandler.TransferSupport support) {
783             Transferable transferable = support.getTransferable();
784             if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)
785                     || transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
786                 return true;
787             }
788             return false;
789         }
790
791         @Override
792         public boolean importData(TransferHandler.TransferSupport support) {
793 //            try {
794 //                Transferable transferable = support.getTransferable();
795 //                if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
796 //                    @SuppressWarnings("unchecked")
797 //                    final List<File> data = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor);
798 //                    Collection<Target> targets = Target.from(data);
799 //                    targetModel.addTarget(targets);
800 //                } else if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
801 //                    String data = (String) transferable.getTransferData(DataFlavor.stringFlavor);
802 //                    Matcher matcher = movieIdPattern.matcher(data);
803 //                    if (matcher.find()) {
804 //                        String movieId = matcher.group(1);
805 //                        Target target = Target.fromId(movieId);
806 //                        targetModel.addTarget(target);
807 //                    } else {
808 //                        return false;
809 //                    }
810 //
811 //                }
812 //                return false;
813 //            } catch (Exception e) {
814 //                logger.log(Level.SEVERE, null, e);
815 //                return false;
816 //            }
817             // TODO 上記実装見直し(Locationは削除された)
818             return false;
819         }
820     }
821
822     private class TableTransferHandler extends DownloadListTransferHandler {
823
824         private static final long serialVersionUID = 1L;
825
826         @Override
827         public boolean canImport(TransferHandler.TransferSupport support) {
828             return super.canImport(support);
829         }
830
831         @Override
832         public boolean importData(TransferHandler.TransferSupport support) {
833             return super.importData(support);
834         }
835     }
836
837     /*
838      * ここからDownloadProfile作成用クラスの定義
839      */
840
841     private class InqubusDownloadProfile implements DownloadProfile {
842
843         private final LoginProfile loginProfile;
844         private final ProxyProfile proxyProfile;
845         private final VideoProfile videoProfile;
846         private final CommentProfile commentProfile;
847         private final GeneralProfile generalProfile;
848
849         private InqubusDownloadProfile() {
850             this.loginProfile = new InqubusLoginProfile();
851             this.proxyProfile = new InqubusProxyProfile();
852             this.videoProfile = new InqubusVideoProfile();
853             this.commentProfile = new InqubusCommentProfile();
854             this.generalProfile = new InqubusGeneralProfile();
855         }
856
857         @Override
858         public LoginProfile getLoginInfo() {
859             return this.loginProfile;
860         }
861
862         @Override
863         public ProxyProfile getProxyProfile() {
864             return this.proxyProfile;
865         }
866
867         @Override
868         public VideoProfile getVideoProfile() {
869             return this.videoProfile;
870         }
871
872         @Override
873         public CommentProfile getCommentProfile() {
874             return this.commentProfile;
875         }
876
877         @Override
878         public GeneralProfile getGeneralProfile() {
879             return this.generalProfile;
880         }
881
882         @Override
883         public String toString(){
884             return ToStringBuilder.reflectionToString(this);
885         }
886     }
887
888     private class InqubusLoginProfile implements LoginProfile {
889         private final String mail;
890         private final String password;
891
892         private InqubusLoginProfile(){
893             final Config p = Config.INSTANCE;
894             this.mail = p.getId();
895             this.password = p.getPassword();
896         }
897
898         @Override
899         public String getMail() {
900             return this.mail;
901         }
902
903         @Override
904         public String getPassword() {
905             return this.password;
906         }
907
908         @Override
909         public String toString(){
910             return ToStringBuilder.reflectionToString(this);
911         }
912     }
913
914     private class InqubusProxyProfile implements ProxyProfile {
915         private final boolean use;
916         private final String host;
917         private final int port;
918
919         private InqubusProxyProfile(){
920             final Config p = Config.INSTANCE;
921             this.use = p.getProxyUse();
922             this.host = p.getProxyHost();
923             final String pp = p.getProxyPort();
924             this.port = StringUtils.isBlank(pp) ? -1 : Integer.parseInt(pp);
925         }
926
927         @Override
928         public boolean use() {
929             return this.use;
930         }
931
932         @Override
933         public String getHost() {
934             return this.host;
935         }
936
937         @Override
938         public int getPort() {
939             return this.port;
940         }
941
942         @Override
943         public String toString(){
944             return ToStringBuilder.reflectionToString(this);
945         }
946     }
947
948     private class InqubusVideoProfile implements VideoProfile {
949         private final boolean download;
950         private final File dir;
951         private final String fileName;
952         private final File localFile;
953
954         private InqubusVideoProfile(){
955             final Config p = Config.INSTANCE;
956             this.download = !cbVideoLocal.isSelected();
957             if (this.download) {
958                 this.dir = new File(p.getVideoDir());
959                 this.fileName = fldVideo.getText();
960                 this.localFile = null;
961             } else {
962                 this.dir = null;
963                 this.fileName = null;
964                 this.localFile = new File(fldVideo.getText());
965             }
966         }
967
968         @Override
969         public boolean isDownload() {
970             return this.download;
971         }
972
973         @Override
974         public File getDir() {
975             return this.dir;
976         }
977
978         @Override
979         public String getFileName() {
980             return this.fileName;
981         }
982
983         @Override
984         public File getLocalFile() {
985             return this.localFile;
986         }
987
988         @Override
989         public String toString(){
990             return ToStringBuilder.reflectionToString(this);
991         }
992     }
993
994     private class InqubusCommentProfile implements CommentProfile {
995         private final boolean download;
996         private final File dir;
997         private final String fileName;
998         private final File localFile;
999         private final int lengthRelatedCommentSize;
1000         private final boolean disablePerMinComment;
1001         private final int perMinCommentSize;
1002         private final long backLogPoint;
1003
1004         private InqubusCommentProfile() {
1005             final Config p = Config.INSTANCE;
1006             this.download = !cbCommentLocal.isSelected();
1007             if (this.download) {
1008                 this.dir = new File(p.getCommentDir());
1009                 this.fileName = fldComment.getText();
1010                 this.localFile = null;
1011             } else {
1012                 this.dir = null;
1013                 this.fileName = null;
1014                 this.localFile = new File(fldComment.getText());
1015             }
1016
1017             if(cbBackLog.isSelected()) {
1018                 try {
1019                     this.backLogPoint = WayBackTimeParser.parse(fldBackLog.getText());
1020                 } catch (IOException ex) {
1021                     throw new IllegalArgumentException("過去ログ時刻指定が誤っています。", ex);
1022                 }
1023             } else {
1024                 this.backLogPoint = -1L;
1025             }
1026
1027             this.disablePerMinComment = cbBackLogReduce.isSelected();
1028             this.lengthRelatedCommentSize
1029                     = (p.getCommentSizeAutosize()) ? -1 : Integer.parseInt(p.getCommentSizeManual());
1030             this.perMinCommentSize
1031                     = (p.getCommentMinSizeAutosize()) ? -1 : Integer.parseInt(p.getCommentMinSizeManual());
1032         }
1033
1034         @Override
1035         public boolean isDownload() {
1036             return this.download;
1037         }
1038
1039         @Override
1040         public File getDir() {
1041             return this.dir;
1042         }
1043
1044         @Override
1045         public String getFileName() {
1046             return this.fileName;
1047         }
1048
1049         @Override
1050         public File getLocalFile() {
1051             return this.localFile;
1052         }
1053
1054         @Override
1055         public int getLengthRelatedCommentSize() {
1056             return this.lengthRelatedCommentSize;
1057         }
1058
1059         @Override
1060         public boolean isDisablePerMinComment() {
1061             return this.disablePerMinComment;
1062         }
1063
1064         @Override
1065         public int getPerMinCommentSize() {
1066             return this.perMinCommentSize;
1067         }
1068
1069         @Override
1070         public long getBackLogPoint() {
1071             return this.backLogPoint;
1072         }
1073
1074         @Override
1075         public String toString(){
1076             return ToStringBuilder.reflectionToString(this);
1077         }
1078     }
1079
1080     private class InqubusGeneralProfile implements GeneralProfile {
1081         private final String replaceFrom;
1082         private final String replaceTo;
1083         private InqubusGeneralProfile() {
1084             final Config p = Config.INSTANCE;
1085             this.replaceFrom = p.getReplaceFrom();
1086             this.replaceTo = p.getReplaceTo();
1087         }
1088
1089         @Override
1090         public String getReplaceFrom() {
1091             return this.replaceFrom;
1092         }
1093
1094         @Override
1095         public String getReplaceTo() {
1096             return this.replaceTo;
1097         }
1098
1099         @Override
1100         public String toString(){
1101             return ToStringBuilder.reflectionToString(this);
1102         }
1103     }
1104
1105     /*
1106      * ここからConvertProfile作成用クラスの定義
1107      */
1108     private class InqubusConvertProfile implements ConvertProfile {
1109         private final OutputProfile outputProfile;
1110         private final GeneralProfile generalProfile;
1111         private final FfmpegProfile ffmpegProfile;
1112         private final boolean convert;
1113         private final File ffmpeg;
1114         private final boolean vhookDisabled;
1115         private final boolean commentOverlay;
1116         private final File vhook;
1117         private final File tmpDir;
1118         private final File font;
1119         private final int fontIndex;
1120         private final boolean commentOpaque;
1121         private final boolean disableFontSizeArrange;
1122         private final int shadowIndex;
1123         private final boolean showConvrting;
1124         private final int maxNumOfComment;
1125         private final HideCondition ngSetting;
1126
1127         private InqubusConvertProfile() throws IOException {
1128             final Config p = Config.INSTANCE;
1129             this.outputProfile = new InqubusOutputProfile();
1130             this.generalProfile = new InqubusGeneralProfile();
1131             this.ffmpegProfile = new InqubusFfmpegProfile();
1132             this.convert = cbOutputEnable.isSelected();
1133             this.ffmpeg = new File(p.getFfmpegPath());
1134             // TODO コンフィグに設定なし
1135             this.vhookDisabled = false;
1136             this.commentOverlay = p.getOutputCommentOverlay();
1137             this.vhook = new File(p.getFfmpegDllPath());
1138             this.tmpDir = new File(p.getSystemTempDir());
1139             this.font = new File(p.getFontPath());
1140             this.fontIndex = Integer.parseInt(p.getFontIndex());
1141             this.commentOpaque = p.getCommentOpaque();
1142             this.disableFontSizeArrange = p.getFontSizeArrangeDisable();
1143             this.shadowIndex = p.getFontShadow();
1144             // TODO コンフィグに設定なし
1145             this.showConvrting = true;
1146             this.maxNumOfComment = (p.getCommentDisplaySizeDefault()) ? -1 : Integer.parseInt(p.
1147                     getCommentDisplaySizeManual());
1148             this.ngSetting = new InqubusHideCondition();
1149         }
1150
1151         @Override
1152         public OutputProfile getOutputProfile() {
1153             return this.outputProfile;
1154         }
1155
1156         @Override
1157         public GeneralProfile getGeneralProfile() {
1158             return this.generalProfile;
1159         }
1160
1161         @Override
1162         public FfmpegProfile getFfmpegOption() {
1163             return this.ffmpegProfile;
1164         }
1165
1166         @Override
1167         public boolean isConvert() {
1168             return this.convert;
1169         }
1170
1171         @Override
1172         public File getFfmpeg() {
1173             return this.ffmpeg;
1174         }
1175
1176         @Override
1177         public boolean isVhookDisabled() {
1178             return this.vhookDisabled;
1179         }
1180
1181         @Override
1182         public boolean isCommentOverlay() {
1183             return this.commentOverlay;
1184         }
1185
1186         @Override
1187         public File getVhook() {
1188             return this.vhook;
1189         }
1190
1191         @Override
1192         public File getTempDir() {
1193             return this.tmpDir;
1194         }
1195
1196         @Override
1197         public File getFont() {
1198             return this.font;
1199         }
1200
1201         @Override
1202         public int getFontIndex() {
1203             return this.fontIndex;
1204         }
1205
1206         @Override
1207         public boolean isCommentOpaque() {
1208             return this.commentOpaque;
1209         }
1210
1211         @Override
1212         public boolean isDisableFontSizeArrange() {
1213             return this.disableFontSizeArrange;
1214         }
1215
1216         @Override
1217         public int getShadowIndex() {
1218             return this.shadowIndex;
1219         }
1220
1221         @Override
1222         public boolean isShowConverting() {
1223             return this.showConvrting;
1224         }
1225
1226         @Override
1227         public int getMaxNumOfComment() {
1228             return this.maxNumOfComment;
1229         }
1230
1231         @Override
1232         public HideCondition getNgSetting() {
1233             return this.ngSetting;
1234         }
1235
1236         @Override
1237         public String toString(){
1238             return ToStringBuilder.reflectionToString(this);
1239         }
1240     }
1241
1242     private class InqubusOutputProfile implements OutputProfile {
1243         private final File dir;
1244         private final String fileName;
1245         private final String videoId;
1246         private final String title;
1247
1248
1249         private InqubusOutputProfile(){
1250             final Config p = Config.INSTANCE;
1251             this.dir = new File(p.getOutputDir());
1252             this.fileName = fldOutput.getText();
1253             // TODO この時点でのID/Titleはどうするか…
1254             this.videoId = "";
1255             this.title = "";
1256         }
1257
1258         @Override
1259         public File getDir() {
1260             return this.dir;
1261         }
1262
1263         @Override
1264         public String getFileName() {
1265             return this.fileName;
1266         }
1267
1268         @Override
1269         public String getVideoId() {
1270             return this.videoId;
1271         }
1272
1273         @Override
1274         public String getTitile() {
1275             return this.title;
1276         }
1277
1278         @Override
1279         public String toString(){
1280             return ToStringBuilder.reflectionToString(this);
1281         }
1282     }
1283
1284     private class InqubusFfmpegProfile implements FfmpegProfile {
1285         private final String extOption;
1286         private final String inOption;
1287         private final String mainOption;
1288         private final String outOption;
1289         private final String avOption;
1290         private final boolean resize;
1291         private final int resizeWidth;
1292         private final int resizeHeight;
1293         private final boolean adjustRatio;
1294
1295         private InqubusFfmpegProfile() throws IOException {
1296             final File file = pnlInputFfmpeg.mdlFfmpegOption.getSelectedFile();
1297             if (file != null) {
1298                 final FfmpegOption ffop = FfmpegOption.load(file);
1299                 this.extOption = ffop.getExtOption();
1300                 this.inOption = ffop.getInOption();
1301                 this.mainOption = ffop.getMainOption();
1302                 this.outOption = ffop.getMainOption();
1303                 this.avOption = ffop.getAvfilterOption();
1304                 this.resize = ffop.isResize();
1305                 this.resizeWidth = ffop.getResizeWidth();
1306                 this.resizeHeight = ffop.getResizeHeight();
1307                 this.adjustRatio = ffop.isAdjustRatio();
1308             } else {
1309                 this.extOption = pnlInputFfmpeg.fldFfmpegOptionExtension.getText();
1310                 this.inOption = pnlInputFfmpeg.fldFfmpegOptionIn.getText();
1311                 this.mainOption = pnlInputFfmpeg.fldFfmpegOptionMain.getText();
1312                 this.outOption = pnlInputFfmpeg.fldFfmpegOptionOut.getText();
1313                 this.avOption = pnlInputFfmpeg.fldFfmpegOptionAv.getText();
1314                 this.resize = pnlInputFfmpeg.cbFfmpegOptionResize.isSelected();
1315                 this.resizeWidth = Integer.parseInt(pnlInputFfmpeg.fldFfmpegOptionResizeWidth.getText());
1316                 this.resizeHeight = Integer.parseInt(pnlInputFfmpeg.fldFfmpegOptionResizeHeight.getText());
1317                 this.adjustRatio = pnlInputFfmpeg.cbFfmpegOptionKeepAspect.isSelected();
1318             }
1319         }
1320
1321         @Override
1322         public String getExtOption() {
1323             return this.extOption;
1324         }
1325
1326         @Override
1327         public String getInOption() {
1328             return this.inOption;
1329         }
1330
1331         @Override
1332         public String getMainOption() {
1333             return this.mainOption;
1334         }
1335
1336         @Override
1337         public String getOutOption() {
1338             return this.outOption;
1339         }
1340
1341         @Override
1342         public String getAvfilterOption() {
1343             return this.avOption;
1344         }
1345
1346         @Override
1347         public boolean isResize() {
1348             return this.resize;
1349         }
1350
1351         @Override
1352         public int getResizeWidth() {
1353             return this.resizeWidth;
1354         }
1355
1356         @Override
1357         public int getResizeHeight() {
1358             return this.resizeHeight;
1359         }
1360
1361         @Override
1362         public boolean isAdjustRatio() {
1363             return this.adjustRatio;
1364         }
1365
1366         @Override
1367         public String toString(){
1368             return ToStringBuilder.reflectionToString(this);
1369         }
1370     }
1371
1372     private class InqubusHideCondition implements ConvertProfile.HideCondition{
1373
1374         @Override
1375         public String getWord() {
1376             // TODO
1377             return "";
1378         }
1379
1380         @Override
1381         public String getId() {
1382             // TODO
1383             return "";
1384         }
1385
1386         @Override
1387         public String toString(){
1388             return ToStringBuilder.reflectionToString(this);
1389         }
1390     }
1391 }