• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

タイニー番組ナビゲータ本体


コミットメタ情報

リビジョン1e3bc14df288b716bd0614166ab29d5207a82500 (tree)
日時2021-06-04 22:03:41
作者Masahiko Kimura <mkimura@u01....>
コミッターMasahiko Kimura

ログメッセージ

Ver.1.13.0 (2021/6/4)
1. [プラグイン]REGZA DBR-T1008に対応する
2. [キーワード検索の設定][予約ダイアログ][新聞形式の表示設定][色見本]フォントサイズに応じて画面を大きくする
3. [各種設定]表示フォントを「24」まで選択できるようにする
4. [タイトル情報]番組情報の行数が多い場合に上下にスクロールして表示できるようにする
5. [本体予約一覧]予約に対応する番組は重なりの最も多い番組とする
6. [タイトル一覧]チャンネル名が取得できない場合はコードを表示する
7. [その他]検索ボックスのプルダウンに最大64個まで検索が表示されるようにする(envs.txtのmaxSearchWordNumで変更可能)

変更サマリ

差分

--- a/TinyBannavi/src/tainavi/AbsKeywordDialog.java
+++ b/TinyBannavi/src/tainavi/AbsKeywordDialog.java
@@ -857,67 +857,91 @@ abstract class AbsKeywordDialog extends JEscCancelDialog {
857857
858858 jPanel.setLayout(new SpringLayout());
859859
860- int y = SEP_HEIGHT;
861- int x = SEP_WIDTH;
862-
863- x = SEP_WIDTH;
864- CommonSwingUtils.putComponentOn(jPanel, getJLabel_label("設定名"), LABEL_WIDTH_S, PARTS_HEIGHT, x, y);
865- CommonSwingUtils.putComponentOn(jPanel, getJTextField_label(), TEXT_WIDTH, PARTS_HEIGHT, x+=LABEL_WIDTH_S, y);
866-
867- int xz = PANEL_WIDTH-(BUTTON_WIDTH+SEP_WIDTH);
868- CommonSwingUtils.putComponentOn(jPanel, getJButton_label("登録"), BUTTON_WIDTH, PARTS_HEIGHT, xz, y);
869- CommonSwingUtils.putComponentOn(jPanel, getJButton_cancel("キャンセル"), BUTTON_WIDTH, PARTS_HEIGHT, xz, y+(SEP_HEIGHT_NARROW+PARTS_HEIGHT));
870- CommonSwingUtils.putComponentOn(jPanel, getJButton_preview("プレビュー"), BUTTON_WIDTH, PARTS_HEIGHT, xz, y+(SEP_HEIGHT_NARROW+PARTS_HEIGHT)*2);
871-
872- y += PARTS_HEIGHT+SEP_HEIGHT;
873- x = SEP_WIDTH;
874- CommonSwingUtils.putComponentOn(jPanel, getJComboBox_target(), TARGET_WIDTH, PARTS_HEIGHT, x, y);
875- CommonSwingUtils.putComponentOn(jPanel, getJTextField_regex(), REGEX_WIDTH, PARTS_HEIGHT, x+=TARGET_WIDTH+SEP_WIDTH, y);
876- CommonSwingUtils.putComponentOn(jPanel, getJComboBox_contain(), TARGET_WIDTH, PARTS_HEIGHT, x+=REGEX_WIDTH+SEP_WIDTH, y);
877-
878- y += PARTS_HEIGHT+SEP_HEIGHT_NARROW;
879- CommonSwingUtils.putComponentOn(jPanel, getJCheckBox_caseSensitive("文字列比較は完全一致で",CHECKLABEL_WIDTH,false), CHECKBOX_WIDTH, PARTS_HEIGHT, x, y);
880-
881- x = SEP_HEIGHT+TABLE_WIDTH/2;
882- CommonSwingUtils.putComponentOn(jPanel, getJButton_add("↓追加"), BUTTON_WIDTH, PARTS_HEIGHT, x-(BUTTON_WIDTH+SEP_WIDTH*2) , y);
883- CommonSwingUtils.putComponentOn(jPanel, getJButton_replace("↓置換"), BUTTON_WIDTH, PARTS_HEIGHT, x+(SEP_WIDTH*2), y);
884-
885-
886- y += PARTS_HEIGHT+SEP_HEIGHT_NARROW;
887- CommonSwingUtils.putComponentOn(jPanel, getJComboBox_condition(), CONDITION_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
888- CommonSwingUtils.putComponentOn(jPanel, getJComboBox_infection(), CONDITION_WIDTH, PARTS_HEIGHT, TABLE_WIDTH-CONDITION_WIDTH+SEP_WIDTH, y);
889-
890- y += PARTS_HEIGHT+SEP_HEIGHT_NARROW;
891- CommonSwingUtils.putComponentOn(jPanel, getJScrollPane_keywords(), TABLEPANE_WIDTH, TABLE_HEIGHT, SEP_WIDTH, y);
892-
893- int yz = y + (TABLE_HEIGHT/2-(PARTS_HEIGHT+SEP_HEIGHT/2));
894- CommonSwingUtils.putComponentOn(jPanel, getJButton_up("↑"), BUTTON_WIDTH, PARTS_HEIGHT, xz, yz);
895- CommonSwingUtils.putComponentOn(jPanel, getJButton_down("↓"), BUTTON_WIDTH, PARTS_HEIGHT, xz, yz+=SEP_HEIGHT+PARTS_HEIGHT);
896- CommonSwingUtils.putComponentOn(jPanel, getJButton_remove("削除"), BUTTON_WIDTH, PARTS_HEIGHT, xz, yz+=SEP_HEIGHT*2+PARTS_HEIGHT);
897-
898- y += TABLE_HEIGHT+SEP_HEIGHT;
899- x = SEP_WIDTH;
900- CommonSwingUtils.putComponentOn(jPanel, getJLabel_sortBy("リストのソート列"), LABEL_WIDTH_L, PARTS_HEIGHT, x, y);
901- CommonSwingUtils.putComponentOn(jPanel, getJComboBox_sortBy(), SELECTION_WIDTH, PARTS_HEIGHT, x+=LABEL_WIDTH_L+SEP_WIDTH, y);
902- CommonSwingUtils.putComponentOn(jPanel, getJLabel_okiniiri("お気に入り度"), LABEL_WIDTH_L, PARTS_HEIGHT, x+=SELECTION_WIDTH+SEP_WIDTH, y);
903- CommonSwingUtils.putComponentOn(jPanel, getJComboBox_okiniiri(), SELECTION_WIDTH, PARTS_HEIGHT, x+=LABEL_WIDTH_L+SEP_WIDTH, y);
904-
905- y += PARTS_HEIGHT+SEP_HEIGHT;
906- x = SEP_WIDTH;
907- CommonSwingUtils.putComponentOn(jPanel, getJLabel_sortDir("同ソート方向"), LABEL_WIDTH_L, PARTS_HEIGHT, x, y);
908- CommonSwingUtils.putComponentOn(jPanel, getJComboBox_sortDir(), SELECTION_WIDTH, PARTS_HEIGHT, x+=LABEL_WIDTH_L+SEP_WIDTH, y);
909- CommonSwingUtils.putComponentOn(jPanel, getJLabel_group("グループ"), LABEL_WIDTH_L, PARTS_HEIGHT, x+=SELECTION_WIDTH+SEP_WIDTH, y);
910- CommonSwingUtils.putComponentOn(jPanel, getJComboBox_group(), SELECTION_WIDTH, PARTS_HEIGHT, x+=LABEL_WIDTH_L+SEP_WIDTH, y);
911-
912- CommonSwingUtils.putComponentOn(jPanel, getJCheckBox_showInStandby("予約待機に表示する",CHECKLABEL_WIDTH,true), CHECKBOX_WIDTH, PARTS_HEIGHT, PANEL_WIDTH-CHECKBOX_WIDTH-SEP_WIDTH, y);
913-
914- y += PARTS_HEIGHT+SEP_HEIGHT;
915-
916- jPanel.setPreferredSize(new Dimension(PANEL_WIDTH, y));
860+ int sh = ZMSIZE(SEP_HEIGHT);
861+ int sw = ZMSIZE(SEP_WIDTH);
862+ int shn = ZMSIZE(SEP_HEIGHT_NARROW);
863+ int lws = ZMSIZE(LABEL_WIDTH_S);
864+ int ph = ZMSIZE(PARTS_HEIGHT);
865+ int pw = ZMSIZE(PANEL_WIDTH);
866+ int bw = ZMSIZE(BUTTON_WIDTH);
867+ int tw = ZMSIZE(TEXT_WIDTH);
868+ int ttw = ZMSIZE(TARGET_WIDTH);
869+ int rw = ZMSIZE(REGEX_WIDTH);
870+ int clw = ZMSIZE(CHECKLABEL_WIDTH);
871+ int cbw = ZMSIZE(CHECKBOX_WIDTH);
872+ int cdw = ZMSIZE(CONDITION_WIDTH);
873+ int tbw = ZMSIZE(TABLE_WIDTH);
874+ int tpw = ZMSIZE(TABLEPANE_WIDTH);
875+ int th = ZMSIZE(TABLE_HEIGHT);
876+ int lwl = ZMSIZE(LABEL_WIDTH_L);
877+ int slw = ZMSIZE(SELECTION_WIDTH);
878+
879+ int y = sh;
880+ int x = sw;
881+
882+ x = sw;
883+ CommonSwingUtils.putComponentOn(jPanel, getJLabel_label("設定名"), lws, ph, x, y);
884+ CommonSwingUtils.putComponentOn(jPanel, getJTextField_label(), tw, ph, x+=lws, y);
885+
886+ int xz = pw-(bw+sw);
887+ CommonSwingUtils.putComponentOn(jPanel, getJButton_label("登録"), bw, ph, xz, y);
888+ CommonSwingUtils.putComponentOn(jPanel, getJButton_cancel("キャンセル"), bw, ph, xz, y+(shn+ph));
889+ CommonSwingUtils.putComponentOn(jPanel, getJButton_preview("プレビュー"), bw, ph, xz, y+(shn+ph)*2);
890+
891+ y += ph+sh;
892+ x = sw;
893+ CommonSwingUtils.putComponentOn(jPanel, getJComboBox_target(), ttw, ph, x, y);
894+ CommonSwingUtils.putComponentOn(jPanel, getJTextField_regex(), rw, ph, x+=ttw+sw, y);
895+ CommonSwingUtils.putComponentOn(jPanel, getJComboBox_contain(), ttw, ph, x+=rw+sw, y);
896+
897+ y += ph+shn;
898+ CommonSwingUtils.putComponentOn(jPanel, getJCheckBox_caseSensitive("文字列比較は完全一致で",clw,false), cbw, ph, x, y);
899+
900+ x = sh+tbw/2;
901+ CommonSwingUtils.putComponentOn(jPanel, getJButton_add("↓追加"), bw, ph, x-(bw+sw*2) , y);
902+ CommonSwingUtils.putComponentOn(jPanel, getJButton_replace("↓置換"), bw, ph, x+(sw*2), y);
903+
904+
905+ y += ph+shn;
906+ CommonSwingUtils.putComponentOn(jPanel, getJComboBox_condition(), cdw, ph, sw, y);
907+ CommonSwingUtils.putComponentOn(jPanel, getJComboBox_infection(), cdw, ph, tbw-cdw+sw, y);
908+
909+ y += ph+shn;
910+ CommonSwingUtils.putComponentOn(jPanel, getJScrollPane_keywords(), tpw, th, sw, y);
911+
912+ int yz = y + (th/2-(ph+sh/2));
913+ CommonSwingUtils.putComponentOn(jPanel, getJButton_up("↑"), bw, ph, xz, yz);
914+ CommonSwingUtils.putComponentOn(jPanel, getJButton_down("↓"), bw, ph, xz, yz+=sh+ph);
915+ CommonSwingUtils.putComponentOn(jPanel, getJButton_remove("削除"), bw, ph, xz, yz+=sh*2+ph);
916+
917+ y += th+sh;
918+ x = sw;
919+ CommonSwingUtils.putComponentOn(jPanel, getJLabel_sortBy("リストのソート列"), lwl, ph, x, y);
920+ CommonSwingUtils.putComponentOn(jPanel, getJComboBox_sortBy(), slw, ph, x+=lwl+sw, y);
921+ CommonSwingUtils.putComponentOn(jPanel, getJLabel_okiniiri("お気に入り度"), lwl, ph, x+=slw+sw, y);
922+ CommonSwingUtils.putComponentOn(jPanel, getJComboBox_okiniiri(), slw, ph, x+=lwl+sw, y);
923+
924+ y += ph+sh;
925+ x = sw;
926+ CommonSwingUtils.putComponentOn(jPanel, getJLabel_sortDir("同ソート方向"), lwl, ph, x, y);
927+ CommonSwingUtils.putComponentOn(jPanel, getJComboBox_sortDir(), slw, ph, x+=lwl+sw, y);
928+ CommonSwingUtils.putComponentOn(jPanel, getJLabel_group("グループ"), lwl, ph, x+=slw+sw, y);
929+ CommonSwingUtils.putComponentOn(jPanel, getJComboBox_group(), slw, ph, x+=lwl+sw, y);
930+
931+ CommonSwingUtils.putComponentOn(jPanel, getJCheckBox_showInStandby("予約待機に表示する",clw,true), cbw, ph, pw-cbw-sw, y);
932+
933+ y += ph+sh;
934+
935+ jPanel.setPreferredSize(new Dimension(pw, y));
917936 }
918937 return jPanel;
919938 }
920939
940+ /*
941+ * フォントサイズを考慮した長さを取得する
942+ */
943+ private int ZMSIZE(int size){ return Env.ZMSIZE(size); }
944+
921945 //
922946 private JLabel getJLabel_label(String s) {
923947 if (jLabel_label == null) {
@@ -1235,7 +1259,7 @@ abstract class AbsKeywordDialog extends JEscCancelDialog {
12351259 if ( rc.getIniWidth() < 0 ) {
12361260 continue;
12371261 }
1238- columnModel.getColumn(rc.ordinal()).setPreferredWidth(rc.getIniWidth());;
1262+ columnModel.getColumn(rc.ordinal()).setPreferredWidth(ZMSIZE(rc.getIniWidth()));
12391263 }
12401264
12411265 // 行を選択したら入力に値を戻す
--- a/TinyBannavi/src/tainavi/AbsListedView.java
+++ b/TinyBannavi/src/tainavi/AbsListedView.java
@@ -4207,6 +4207,7 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
42074207 jTree_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
42084208 jTree_tree.setRootVisible(env.getRootNodeVisible());
42094209 jTree_tree.setCellRenderer(new VWTreeCellRenderer()); // 検索結果が存在するノードの色を変える
4210+ jTree_tree.setRowHeight(jTree_tree.getFont().getSize()+1);
42104211
42114212 // ノードの作成
42124213 jTree_tree.setModel(new DefaultTreeModel(getTreeNodes()));
@@ -4231,6 +4232,7 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
42314232
42324233 // ノードの作成
42334234 jTree_tree.setModel(new DefaultTreeModel(getTreeNodes()));
4235+ jTree_tree.setRowHeight(jTree_tree.getFont().getSize()+1);
42344236
42354237 // ツリーの展開状態の復帰
42364238 undoTreeExpansion();
--- a/TinyBannavi/src/tainavi/AbsPaperColorsDialog.java
+++ b/TinyBannavi/src/tainavi/AbsPaperColorsDialog.java
@@ -16,6 +16,7 @@ import java.util.ArrayList;
1616 import javax.swing.DefaultCellEditor;
1717 import javax.swing.JButton;
1818 import javax.swing.JCheckBox;
19+import javax.swing.JComponent;
1920 import javax.swing.JDialog;
2021 import javax.swing.JLabel;
2122 import javax.swing.JPanel;
@@ -87,7 +88,7 @@ abstract class AbsPaperColorsDialog extends JEscCancelDialog {
8788 private static final int SEP_HEIGHT_NARROW = 2;
8889
8990 //private static final int PARTS_WIDTH = 900;
90- private static final int PARTS_HEIGHT = 30;
91+ private static final int PARTS_HEIGHT = 25;
9192
9293 private static final int LABEL_WIDTH = 125;
9394 private static final int ITEM_WIDTH = 250;
@@ -95,7 +96,7 @@ abstract class AbsPaperColorsDialog extends JEscCancelDialog {
9596
9697 private static final int BUTTON_WIDTH = 100;
9798
98- private static final int PANEL_WIDTH = LABEL_WIDTH+ITEM_WIDTH+SEP_WIDTH*2;
99+ private static int PANEL_WIDTH = LABEL_WIDTH+ITEM_WIDTH+SEP_WIDTH*2;
99100 private static int PANEL_HEIGHT = 0;
100101
101102 private static final int TABLE_WIDTH = PANEL_WIDTH-SEP_WIDTH*2;
@@ -365,15 +366,23 @@ abstract class AbsPaperColorsDialog extends JEscCancelDialog {
365366
366367 jPanel_buttons.setLayout(new SpringLayout());
367368
368- int y = SEP_HEIGHT;
369- int x = (PANEL_WIDTH - (BUTTON_WIDTH*3+SEP_WIDTH*2))/2;
370- CommonSwingUtils.putComponentOn(jPanel_buttons, getJButton_preview("プレビュー"), BUTTON_WIDTH, PARTS_HEIGHT, x, y);
371- CommonSwingUtils.putComponentOn(jPanel_buttons, getJButton_update("登録"), BUTTON_WIDTH, PARTS_HEIGHT, x+=BUTTON_WIDTH+SEP_WIDTH, y);
372- CommonSwingUtils.putComponentOn(jPanel_buttons, getJButton_cancel("キャンセル"), BUTTON_WIDTH, PARTS_HEIGHT, x+=BUTTON_WIDTH+SEP_WIDTH, y);
369+ int sw = ZMSIZE(SEP_WIDTH);
370+ int bw = ZMSIZE(BUTTON_WIDTH);
373371
374- y += PARTS_HEIGHT+SEP_HEIGHT;
372+ int ph = ZMSIZE(PARTS_HEIGHT);
373+ int sh = ZMSIZE(SEP_HEIGHT);
375374
376- jPanel_buttons.setPreferredSize(new Dimension(PANEL_WIDTH, y));
375+ int pw = ZMSIZE(PANEL_WIDTH);
376+
377+ int y = sh;
378+ int x = (pw - (bw*3+sw*2))/2;
379+ CommonSwingUtils.putComponentOn(jPanel_buttons, getJButton_preview("プレビュー"), bw, ph, x, y);
380+ CommonSwingUtils.putComponentOn(jPanel_buttons, getJButton_update("登録"), bw, ph, x+=bw+sw, y);
381+ CommonSwingUtils.putComponentOn(jPanel_buttons, getJButton_cancel("キャンセル"), bw, ph, x+=bw+sw, y);
382+
383+ y += ph+sh;
384+
385+ jPanel_buttons.setPreferredSize(new Dimension(pw, y));
377386 }
378387 return jPanel_buttons;
379388 }
@@ -431,44 +440,63 @@ abstract class AbsPaperColorsDialog extends JEscCancelDialog {
431440
432441 jPanel_pColors.setLayout(new SpringLayout());
433442
434- int y = SEP_HEIGHT_NARROW;
435- int x = SEP_WIDTH;
436-
437- CommonSwingUtils.putComponentOn(jPanel_pColors, new JTitleLabel("ジャンル別背景色"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
438- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
439- CommonSwingUtils.putComponentOn(jPanel_pColors, getJScrollPane_list(), TABLE_WIDTH, ZMSIZE(TABLE_HEIGHT), SEP_WIDTH, y);
440-
441- y += ZMSIZE(TABLE_HEIGHT)+SEP_HEIGHT;
442- CommonSwingUtils.putComponentOn(jPanel_pColors, new JTitleLabel("タイムバーの色"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
443- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
444- CommonSwingUtils.putComponentOn(jPanel_pColors, jLabel_timebar = new JCCLabel("6~11", origenv.getTimebarColor(),true,this,ccwin), TIMEBAR_WIDTH, PARTS_HEIGHT, x, y);
445- CommonSwingUtils.putComponentOn(jPanel_pColors, jLabel_timebar2 = new JCCLabel("12~17", origenv.getTimebarColor2(),true,this,ccwin), TIMEBAR_WIDTH, PARTS_HEIGHT, x+=TIMEBAR_WIDTH, y);
446- CommonSwingUtils.putComponentOn(jPanel_pColors, jLabel_timebar3 = new JCCLabel("18~23", origenv.getTimebarColor3(),true,this,ccwin), TIMEBAR_WIDTH, PARTS_HEIGHT, x+=TIMEBAR_WIDTH, y);
447- CommonSwingUtils.putComponentOn(jPanel_pColors, jLabel_timebar4 = new JCCLabel("24~5", origenv.getTimebarColor4(),true,this,ccwin), TIMEBAR_WIDTH, PARTS_HEIGHT, x+=TIMEBAR_WIDTH, y);
448-
449- y += (PARTS_HEIGHT+SEP_HEIGHT);
450- CommonSwingUtils.putComponentOn(jPanel_pColors, new JTitleLabel("予約バーの色"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
451- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
452- x = SEP_WIDTH;
453- CommonSwingUtils.putComponentOn(jPanel_pColors, jLabel_restimebar1 = new JCCLabel("1", origenv.getResTimebarColor1(),true,this,ccwin), TIMEBAR_WIDTH, PARTS_HEIGHT, x, y);
454- CommonSwingUtils.putComponentOn(jPanel_pColors, jLabel_restimebar2 = new JCCLabel("2", origenv.getResTimebarColor2(),true,this,ccwin), TIMEBAR_WIDTH, PARTS_HEIGHT, x+=TIMEBAR_WIDTH, y);
455- CommonSwingUtils.putComponentOn(jPanel_pColors, jLabel_restimebar3 = new JCCLabel("最大", origenv.getResTimebarColor3(),true,this,ccwin), TIMEBAR_WIDTH, PARTS_HEIGHT, x+=TIMEBAR_WIDTH, y);
456- CommonSwingUtils.putComponentOn(jPanel_pColors, jLabel_restimebar4 = new JCCLabel(">最大", origenv.getResTimebarColor4(),true,this,ccwin), TIMEBAR_WIDTH, PARTS_HEIGHT, x+=TIMEBAR_WIDTH, y);
457-
458- y += (PARTS_HEIGHT+SEP_HEIGHT);
459- CommonSwingUtils.putComponentOn(jPanel_pColors, new JTitleLabel("マウスオーバー時のハイライト色"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
460- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
461- CommonSwingUtils.putComponentOn(jPanel_pColors, jCBP_highlight = new JCheckBoxPanel("有効",LABEL_WIDTH/2), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
462- CommonSwingUtils.putComponentOn(jPanel_pColors, jLabel_highlight = new JCCLabel("ハイライト",origenv.getHighlightColor(),true,this,ccwin), ITEM_WIDTH, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
463-
464- y += (PARTS_HEIGHT+SEP_HEIGHT*2);
443+ int tw = ZMSIZE(TITLE_WIDTH);
444+ int lw = ZMSIZE(LABEL_WIDTH);
445+ int iw = ZMSIZE(ITEM_WIDTH);
446+ int sw = ZMSIZE(SEP_WIDTH);
447+ int swn = ZMSIZE(SEP_WIDTH_NARROW);
448+ int tbw = ZMSIZE(TIMEBAR_WIDTH);
449+ int pw = ZMSIZE(PANEL_WIDTH);
450+
451+ int ph = ZMSIZE(PARTS_HEIGHT);
452+ int sh = ZMSIZE(SEP_HEIGHT);
453+ int shn = ZMSIZE(SEP_HEIGHT_NARROW);
454+ int th = ZMSIZE(TABLE_HEIGHT);
455+
456+ int y = shn;
457+ int x = sw;
458+
459+ addc(new JTitleLabel("ジャンル別背景色"), tw, ph, swn, y);
460+ y += (ph+shn);
461+ addc(getJScrollPane_list(), tw, th, sw, y);
462+
463+ y += th+sh;
464+ addc(new JTitleLabel("タイムバーの色"), tw, ph, swn, y);
465+ y += (ph+shn);
466+ addc(jLabel_timebar = new JCCLabel("6~11", origenv.getTimebarColor(), true,this,ccwin), tbw, ph, x, y);
467+ addc(jLabel_timebar2 = new JCCLabel("12~17", origenv.getTimebarColor2(),true,this,ccwin), tbw, ph, x+=tbw, y);
468+ addc(jLabel_timebar3 = new JCCLabel("18~23", origenv.getTimebarColor3(),true,this,ccwin), tbw, ph, x+=tbw, y);
469+ addc(jLabel_timebar4 = new JCCLabel("24~5", origenv.getTimebarColor4(),true,this,ccwin), tbw, ph, x+=tbw, y);
470+
471+ y += (ph+sh);
472+ addc(new JTitleLabel("予約バーの色"), tw, ph, swn, y);
473+ y += (ph+shn);
474+ x = sw;
475+ addc(jLabel_restimebar1 = new JCCLabel("1", origenv.getResTimebarColor1(),true,this,ccwin), tbw, ph, x, y);
476+ addc(jLabel_restimebar2 = new JCCLabel("2", origenv.getResTimebarColor2(),true,this,ccwin), tbw, ph, x+=tbw, y);
477+ addc(jLabel_restimebar3 = new JCCLabel("最大", origenv.getResTimebarColor3(),true,this,ccwin), tbw, ph, x+=tbw, y);
478+ addc(jLabel_restimebar4 = new JCCLabel(">最大",origenv.getResTimebarColor4(),true,this,ccwin), tbw, ph, x+=tbw, y);
479+
480+ y += (ph+sh);
481+ addc(new JTitleLabel("マウスオーバー時のハイライト色"), tw, ph, swn, y);
482+ y += (ph+shn);
483+ addc(jCBP_highlight = new JCheckBoxPanel("有効",lw/2), lw, ph, sw, y);
484+ addc(jLabel_highlight = new JCCLabel("ハイライト",origenv.getHighlightColor(),true,this,ccwin), iw, ph, lw+sw, y);
485+
486+ y += (ph+sh*2);
465487
466488 if (PANEL_HEIGHT < y) PANEL_HEIGHT = y;
467489
468- jPanel_pColors.setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
490+ jPanel_pColors.setPreferredSize(new Dimension(pw, PANEL_HEIGHT));
469491 }
470492 return jPanel_pColors;
471493 }
494+
495+ private void addc(JComponent c, int width, int height, int x, int y) {
496+ CommonSwingUtils.putComponentOn(jPanel_pColors, c, width, height, x, y);
497+ }
498+
499+
472500 private void setColors() {
473501 //
474502 for (int i=jTableModel_list.getRowCount()-1; i>=0; i--) {
@@ -510,11 +538,11 @@ abstract class AbsPaperColorsDialog extends JEscCancelDialog {
510538 if (jTable_list == null) {
511539 //
512540 String[] colname = {"ジャンル", "色"};
513- int[] colwidth = {TABLE_WIDTH-100,100};
541+ int[] colwidth = {ZMSIZE(TABLE_WIDTH-100),ZMSIZE(100)};
514542 //
515543 jTableModel_list = new DefaultTableModel(colname, 0);
516544 jTable_list = new JNETable(jTableModel_list, false);
517- jTable_list.setRowHeight(ZMSIZE(jTable_list.getRowHeight()));
545+// jTable_list.setRowHeight(ZMSIZE(jTable_list.getRowHeight()));
518546 jTable_list.setAutoResizeMode(JNETable.AUTO_RESIZE_OFF);
519547 DefaultTableColumnModel columnModel = (DefaultTableColumnModel)jTable_list.getColumnModel();
520548 TableColumn column = null;
@@ -582,62 +610,78 @@ abstract class AbsPaperColorsDialog extends JEscCancelDialog {
582610
583611 jPanel_fonts.setLayout(new SpringLayout());
584612
585- int y = SEP_HEIGHT_NARROW;
613+ int tw = ZMSIZE(TITLE_WIDTH);
614+ int lw = ZMSIZE(LABEL_WIDTH);
615+ int iw = ZMSIZE(ITEM_WIDTH);
616+ int sw = ZMSIZE(SEP_WIDTH);
617+ int swn = ZMSIZE(SEP_WIDTH_NARROW);
618+ int pw = ZMSIZE(PANEL_WIDTH);
586619
587- CommonSwingUtils.putComponentOn(jPanel_fonts, new JTitleLabel("開始時刻欄の設定"), TITLE_WIDTH, PARTS_HEIGHT, SEP_HEIGHT_NARROW, y);
620+ int ph = ZMSIZE(PARTS_HEIGHT);
621+ int sh = ZMSIZE(SEP_HEIGHT);
622+ int shn = ZMSIZE(SEP_HEIGHT_NARROW);
623+ int sth = ZMSIZE(STYLETABLE_HEIGHT);
588624
589- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
590- CommonSwingUtils.putComponentOn(jPanel_fonts, jCBP_showStart = new JCheckBoxPanel("表示する",LABEL_WIDTH), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
625+ int y = shn;
626+ addf(new JTitleLabel("開始時刻欄の設定"), tw, ph, shn, y);
627+
628+ y += (ph+shn);
629+ addf(jCBP_showStart = new JCheckBoxPanel("表示する",lw), tw, ph, sw, y);
591630 //jCBP_showStart.addActionListener(fal);
592631
593- y += (PARTS_HEIGHT+SEP_HEIGHT);
594- CommonSwingUtils.putComponentOn(jPanel_fonts, new JTitleLabel("番組名のフォント設定"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
632+ y += (ph+sh);
633+ addf(new JTitleLabel("番組名のフォント設定"), tw, ph, swn, y);
595634
596- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
597- CommonSwingUtils.putComponentOn(jPanel_fonts, jCBX_titleFont = new JComboBoxPanel("フォント",LABEL_WIDTH,ITEM_WIDTH,true), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
635+ y += (ph+shn);
636+ addf(jCBX_titleFont = new JComboBoxPanel("フォント",lw,iw,true), lw+iw, ph, sw, y);
598637
599- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
600- CommonSwingUtils.putComponentOn(jPanel_fonts, jSP_titleFontSize = new JSliderPanel("サイズ",LABEL_WIDTH,6,24,ITEM_WIDTH), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
638+ y += (ph+shn);
639+ addf(jSP_titleFontSize = new JSliderPanel("サイズ",lw,ZMSIZE(6),ZMSIZE(24),iw), lw+iw, ph, sw, y);
601640
602- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
603- CommonSwingUtils.putComponentOn(jPanel_fonts, new JLabel("文字色"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
604- CommonSwingUtils.putComponentOn(jPanel_fonts, jLabel_titleFontColor = new JCCLabel("番組名", origenv.getTitleFontColor(),false,this,ccwin), ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH+LABEL_WIDTH, y);
641+ y += (ph+shn);
642+ addf(new JLabel("文字色"), lw, ph, sw, y);
643+ addf(jLabel_titleFontColor = new JCCLabel("番組名", origenv.getTitleFontColor(),false,this,ccwin), iw, ph, sw+lw, y);
605644
606- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
607- CommonSwingUtils.putComponentOn(jPanel_fonts, new JLabel("スタイル"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
608- CommonSwingUtils.putComponentOn(jPanel_fonts, jScrollPane_titleFontStyle = getJScrollPane_fontstyle(), ITEM_WIDTH, ZMSIZE(STYLETABLE_HEIGHT), SEP_WIDTH+LABEL_WIDTH, y);
645+ y += (ph+shn);
646+ addf(new JLabel("スタイル"), lw, ph, sw, y);
647+ addf(jScrollPane_titleFontStyle = getJScrollPane_fontstyle(), iw, sth, sw+lw, y);
609648
610- y += ZMSIZE(STYLETABLE_HEIGHT)+10;
611- CommonSwingUtils.putComponentOn(jPanel_fonts, new JTitleLabel("番組詳細のフォント設定"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
649+ y += sth+sh;
650+ addf(new JTitleLabel("番組詳細のフォント設定"), tw, ph, swn, y);
612651
613- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
614- CommonSwingUtils.putComponentOn(jPanel_fonts, jCBP_showDetail = new JCheckBoxPanel("表示する",LABEL_WIDTH), TITLE_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
652+ y += (ph+shn);
653+ addf(jCBP_showDetail = new JCheckBoxPanel("表示する",lw), tw+iw, ph, sw, y);
615654
616- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
617- CommonSwingUtils.putComponentOn(jPanel_fonts, jCBX_detailFont = new JComboBoxPanel("フォント",LABEL_WIDTH,ITEM_WIDTH,true), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
655+ y += (ph+shn);
656+ addf(jCBX_detailFont = new JComboBoxPanel("フォント",lw,iw,true), lw+iw, ph, sw, y);
618657
619- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
620- CommonSwingUtils.putComponentOn(jPanel_fonts, jSP_detailFontSize = new JSliderPanel("サイズ",LABEL_WIDTH,6,24,ITEM_WIDTH), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
658+ y += (ph+shn);
659+ addf(jSP_detailFontSize = new JSliderPanel("サイズ",lw,ZMSIZE(6),ZMSIZE(24),iw), lw+iw, ph, sw, y);
621660
622- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
623- CommonSwingUtils.putComponentOn(jPanel_fonts, new JLabel("文字色"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
624- CommonSwingUtils.putComponentOn(jPanel_fonts, jLabel_detailFontColor = new JCCLabel("番組詳細", origenv.getDetailFontColor(),false,this,ccwin), ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH+LABEL_WIDTH, y);
661+ y += (ph+shn);
662+ addf(new JLabel("文字色"), lw, ph, sw, y);
663+ addf(jLabel_detailFontColor = new JCCLabel("番組詳細", origenv.getDetailFontColor(),false,this,ccwin), iw, ph, sw+lw, y);
625664
626- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
627- CommonSwingUtils.putComponentOn(jPanel_fonts, new JLabel("スタイル"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
628- CommonSwingUtils.putComponentOn(jPanel_fonts, jScrollPane_detailFontStyle = getJScrollPane_fontstyle(), ITEM_WIDTH, ZMSIZE(STYLETABLE_HEIGHT), SEP_WIDTH+LABEL_WIDTH, y);
665+ y += (ph+shn);
666+ addf(new JLabel("スタイル"), lw, ph, sw, y);
667+ addf(jScrollPane_detailFontStyle = getJScrollPane_fontstyle(), iw, sth, sw+lw, y);
629668
630- y += ZMSIZE(STYLETABLE_HEIGHT)+SEP_HEIGHT_NARROW;
631- CommonSwingUtils.putComponentOn(jPanel_fonts, jSP_detailTab = new JSliderPanel("左余白",LABEL_WIDTH,0,24,ITEM_WIDTH), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
669+ y += sth+shn;
670+ addf(jSP_detailTab = new JSliderPanel("左余白",lw,0,ZMSIZE(24),iw), lw+iw, ph, sw, y);
632671
633- y += (PARTS_HEIGHT+SEP_HEIGHT*3);
672+ y += (ph+sh);
634673
635674 if (PANEL_HEIGHT < y) PANEL_HEIGHT = y;
636675
637- jPanel_fonts.setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
676+ jPanel_fonts.setPreferredSize(new Dimension(pw, PANEL_HEIGHT));
638677 }
639678 return jPanel_fonts;
640679 }
680+
681+ private void addf(JComponent c, int width, int height, int x, int y) {
682+ CommonSwingUtils.putComponentOn(jPanel_fonts, c, width, height, x, y);
683+ }
684+
641685 private void setFonts() {
642686 //
643687 jCBP_showStart.setSelected(origenv.getShowStart());
@@ -688,7 +732,7 @@ abstract class AbsPaperColorsDialog extends JEscCancelDialog {
688732
689733 // ヘッダの設定
690734 String[] colname = {"チェック", "スタイル"};
691- int[] colwidth = {50,ITEM_WIDTH-50};
735+ int[] colwidth = {ZMSIZE(50),ZMSIZE(ITEM_WIDTH-50)};
692736
693737 //
694738 DefaultTableModel model = new DefaultTableModel(colname, 0);
@@ -701,7 +745,7 @@ abstract class AbsPaperColorsDialog extends JEscCancelDialog {
701745 return (column == 0);
702746 }
703747 };
704- jTable.setRowHeight(ZMSIZE(jTable.getRowHeight()));
748+// jTable.setRowHeight(ZMSIZE(jTable.getRowHeight()));
705749 jTable.setAutoResizeMode(JNETable.AUTO_RESIZE_OFF);
706750 DefaultTableColumnModel columnModel = (DefaultTableColumnModel)jTable.getColumnModel();
707751 TableColumn column = null;
@@ -768,70 +812,84 @@ abstract class AbsPaperColorsDialog extends JEscCancelDialog {
768812
769813 jPanel_bounds.setLayout(new SpringLayout());
770814
771- int y = SEP_HEIGHT_NARROW;
815+ int tw = ZMSIZE(TITLE_WIDTH);
816+ int lw = ZMSIZE(LABEL_WIDTH);
817+ int iw = ZMSIZE(ITEM_WIDTH);
818+ int sw = ZMSIZE(SEP_WIDTH);
819+ int swn = ZMSIZE(SEP_WIDTH_NARROW);
820+ int pw = ZMSIZE(PANEL_WIDTH);
772821
773- CommonSwingUtils.putComponentOn(jPanel_bounds, new JTitleLabel("サイズの設定"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
822+ int ph = ZMSIZE(PARTS_HEIGHT);
823+ int sh = ZMSIZE(SEP_HEIGHT);
824+ int shn = ZMSIZE(SEP_HEIGHT_NARROW);
774825
775- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
776- CommonSwingUtils.putComponentOn(jPanel_bounds, jSP_width = new JSliderPanel("幅",LABEL_WIDTH,50,300,ITEM_WIDTH), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
826+ int y = shn;
827+ addb(new JTitleLabel("サイズの設定"), tw, ph, swn, y);
777828
778- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
779- CommonSwingUtils.putComponentOn(jPanel_bounds, jSP_height = new JSliderPanel("高さ(pt/H)",LABEL_WIDTH,30,600,STEPBY,ITEM_WIDTH), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
829+ y += (ph+shn);
830+ addb(jSP_width = new JSliderPanel("幅",lw,ZMSIZE(50),ZMSIZE(300),iw), lw+iw, ph, sw, y);
780831
781- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
782- CommonSwingUtils.putComponentOn(jPanel_bounds, jSP_timebarPosition = new JSliderPanel("現在時刻線(分)",LABEL_WIDTH,1,180,ITEM_WIDTH), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
832+ y += (ph+shn);
833+ addb(jSP_height = new JSliderPanel("高さ(pt/H)",lw,ZMSIZE(30),ZMSIZE(600),ZMSIZE(STEPBY),iw), lw+iw, ph, sw, y);
783834
784- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
785- CommonSwingUtils.putComponentOn(jPanel_bounds, jSP_restimebar= new JSliderPanel("予約バー幅",LABEL_WIDTH,0,12,ITEM_WIDTH), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
835+ y += (ph+shn);
836+ addb(jSP_timebarPosition = new JSliderPanel("現在時刻線(分)",lw,1,ZMSIZE(180),iw), lw+iw, ph, sw, y);
786837
787- y += (PARTS_HEIGHT+SEP_HEIGHT);
788- CommonSwingUtils.putComponentOn(jPanel_bounds, new JTitleLabel("予約枠の設定"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
838+ y += (ph+shn);
839+ addb(jSP_restimebar= new JSliderPanel("予約バー幅",lw,0,ZMSIZE(12),iw), lw+iw, ph, sw, y);
789840
790- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
791- CommonSwingUtils.putComponentOn(jPanel_bounds, jLabel_execon = new JCCLabel("実行ONの文字色",origenv.getExecOnFontColor(),false,this,ccwin), ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH+LABEL_WIDTH, y);
841+ y += (ph+sh);
842+ addb(new JTitleLabel("予約枠の設定"), tw, ph, swn, y);
792843
793- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
794- CommonSwingUtils.putComponentOn(jPanel_bounds, jLabel_execoff = new JCCLabel("実行OFFの文字色",origenv.getExecOffFontColor(),false,this,ccwin), ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH+LABEL_WIDTH, y);
844+ y += (ph+shn);
845+ addb(jLabel_execon = new JCCLabel("実行ONの文字色",origenv.getExecOnFontColor(),false,this,ccwin), iw, ph, sw+lw, y);
795846
796- y += (PARTS_HEIGHT+SEP_HEIGHT);
797- CommonSwingUtils.putComponentOn(jPanel_bounds, new JTitleLabel("ピックアップ枠の設定"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
847+ y += (ph+shn);
848+ addb(jLabel_execoff = new JCCLabel("実行OFFの文字色",origenv.getExecOffFontColor(),false,this,ccwin), iw, ph, sw+lw, y);
798849
799- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
800- CommonSwingUtils.putComponentOn(jPanel_bounds, jLabel_pickup = new JCCLabel("ピックアップの枠色",origenv.getPickedColor(),true,this,ccwin), ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH+LABEL_WIDTH, y);
850+ y += (ph+sh);
851+ addb(new JTitleLabel("ピックアップ枠の設定"), tw, ph, swn, y);
801852
802- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
803- CommonSwingUtils.putComponentOn(jPanel_bounds, jLabel_pickupFont = new JCCLabel("ピックアップの文字色",origenv.getPickedFontColor(),false,this,ccwin), ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH+LABEL_WIDTH, y);
853+ y += (ph+shn);
854+ addb(jLabel_pickup = new JCCLabel("ピックアップの枠色",origenv.getPickedColor(),true,this,ccwin), iw, ph, sw+lw, y);
804855
805- y += (PARTS_HEIGHT+SEP_HEIGHT);
806- CommonSwingUtils.putComponentOn(jPanel_bounds, new JTitleLabel("予約待機枠の設定"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
856+ y += (ph+shn);
857+ addb(jLabel_pickupFont = new JCCLabel("ピックアップの文字色",origenv.getPickedFontColor(),false,this,ccwin), iw, ph, sw+lw, y);
807858
808- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
809- CommonSwingUtils.putComponentOn(jPanel_bounds, jSP_matchedBorderThickness = new JSliderPanel("太さ",LABEL_WIDTH,1,16,ITEM_WIDTH), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
859+ y += (ph+sh);
860+ addb(new JTitleLabel("予約待機枠の設定"), tw, ph, swn, y);
810861
811- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
812- CommonSwingUtils.putComponentOn(jPanel_bounds, jLabel_matchedBorderColor = new JCCLabel("予約待機枠(番組追跡)",origenv.getMatchedBorderColor(),true,this,ccwin), ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH+LABEL_WIDTH, y);
862+ y += (ph+shn);
863+ addb(jSP_matchedBorderThickness = new JSliderPanel("太さ",lw,1,16,iw), lw+iw, ph, sw, y);
813864
814- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
815- CommonSwingUtils.putComponentOn(jPanel_bounds, jLabel_matchedKeywordBorderColor = new JCCLabel("予約待機枠(キーワード検索)",origenv.getMatchedKeywordBorderColor(),true,this,ccwin), ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH+LABEL_WIDTH, y);
865+ y += (ph+shn);
866+ addb(jLabel_matchedBorderColor = new JCCLabel("予約待機枠(番組追跡)",origenv.getMatchedBorderColor(),true,this,ccwin), iw, ph, sw+lw, y);
816867
817- y += (PARTS_HEIGHT+SEP_HEIGHT);
818- CommonSwingUtils.putComponentOn(jPanel_bounds, new JTitleLabel("フォントのアンチエイリアス設定"), TITLE_WIDTH, PARTS_HEIGHT, SEP_WIDTH_NARROW, y);
868+ y += (ph+shn);
869+ addb(jLabel_matchedKeywordBorderColor = new JCCLabel("予約待機枠(キーワード検索)",origenv.getMatchedKeywordBorderColor(),true,this,ccwin), iw, ph, sw+lw, y);
819870
820- y += (PARTS_HEIGHT+SEP_HEIGHT_NARROW);
821- CommonSwingUtils.putComponentOn(jPanel_bounds, jCBX_aaMode = new JComboBoxPanel("アンチエイリアス",LABEL_WIDTH,ITEM_WIDTH,true), LABEL_WIDTH+ITEM_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
871+ y += (ph+sh);
872+ addb(new JTitleLabel("フォントのアンチエイリアス設定"), tw, ph, swn, y);
873+
874+ y += (ph+shn);
875+ addb(jCBX_aaMode = new JComboBoxPanel("アンチエイリアス",lw,iw,true), lw+iw, ph, sw, y);
822876 for ( AAMode aam : AAMode.values() ) {
823877 jCBX_aaMode.addItem(aam);
824878 }
825879
826- y += (PARTS_HEIGHT+SEP_HEIGHT*2);
880+ y += (ph+sh);
827881
828882 if (PANEL_HEIGHT < y) PANEL_HEIGHT = y;
829883
830- jPanel_bounds.setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
884+ jPanel_bounds.setPreferredSize(new Dimension(pw, PANEL_HEIGHT));
831885 }
832886 return jPanel_bounds;
833887 }
834888
889+ private void addb(JComponent c, int width, int height, int x, int y) {
890+ CommonSwingUtils.putComponentOn(jPanel_bounds, c, width, height, x, y);
891+ }
892+
835893 private void setBounds() {
836894 jSP_width.setValue(origbnd.getBangumiColumnWidth());
837895 jSP_height.setValue(Math.round(origbnd.getPaperHeightMultiplier()*(float)60/(float)STEPBY));
--- a/TinyBannavi/src/tainavi/AbsPaperView.java
+++ b/TinyBannavi/src/tainavi/AbsPaperView.java
@@ -298,6 +298,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
298298 * Envの内容を反映する
299299 */
300300 public void reflectEnv(){
301+ jTree_tree.setRowHeight(jTree_tree.getFont().getSize()+1);
301302 initDetailHeight();
302303 }
303304
@@ -3258,6 +3259,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
32583259 jTree_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
32593260 jTree_tree.setCellRenderer(new TreeCellRenderer()); // 検索結果が存在するノードの色を変える
32603261 jTree_tree.setRootVisible(env.getRootNodeVisible());
3262+ jTree_tree.setRowHeight(jTree_tree.getFont().getSize()+1);
32613263
32623264 // ノードの作成
32633265 jTree_tree.setModel(new DefaultTreeModel(getTreeNodes()));
--- a/TinyBannavi/src/tainavi/AbsReserveListView.java
+++ b/TinyBannavi/src/tainavi/AbsReserveListView.java
@@ -648,17 +648,25 @@ public abstract class AbsReserveListView extends JPanel implements TickTimerList
648648 if (! pdl.Date.equals(date))
649649 continue;
650650
651+ long msecsLike = 0;
652+ ProgDetailList tvdLike = null;
653+
651654 // 日付内の番組についてループする
652655 for (ProgDetailList tvd : pdl.pdetail){
653656 int bse = tvd.startDateTime.compareTo(end);
654657 int bes = tvd.endDateTime.compareTo(start);
655658
656659 // 予約情報と時間が重なる場合はその番組情報を返す
657- if (bse * bes < 0)
658- return tvd;
660+ if (bse * bes < 0){
661+ long msecs = calcIntersectMillisecs(tvd.startDateTime, tvd.endDateTime, start, end);
662+ if (msecs > msecsLike ){
663+ tvdLike = tvd;
664+ msecsLike = msecs;
665+ }
666+ }
659667 }
660668
661- break;
669+ return tvdLike;
662670 }
663671
664672 break;
@@ -668,7 +676,26 @@ public abstract class AbsReserveListView extends JPanel implements TickTimerList
668676 }
669677
670678 /*
679+ * 2つの時間枠の重なり部分をミリ秒単位で取得する
680+ */
681+ static private long calcIntersectMillisecs(String start1, String end1, String start2, String end2){
682+ if (start1 == null || end1 == null || start2 == null || end2 == null)
683+ return -1;
684+
685+ GregorianCalendar cs1 = CommonUtils.getCalendar(start1);
686+ GregorianCalendar ce1 = CommonUtils.getCalendar(end1);
687+ GregorianCalendar cs2 = CommonUtils.getCalendar(start2);
688+ GregorianCalendar ce2 = CommonUtils.getCalendar(end2);
689+ if (cs1 == null || ce1 == null || cs2 == null || ce2 == null)
690+ return -1;
691+
692+ return Long.min(ce1.getTimeInMillis(), ce2.getTimeInMillis()) - Long.max(cs1.getTimeInMillis(), cs2.getTimeInMillis());
693+ }
694+
695+ /*
671696 * 予約の開始日時、終了時刻、長さをチェックする
697+ *
698+ * @return 0x01=開始日時が異なる、0x02=終了時刻が異なる、0x04=長さが異なる
672699 */
673700 private int checkReserveList(TVProgramIterator pli, ReserveList r, String date, String start, String end){
674701 // 予約を実行しない場合はチェックしない
--- a/TinyBannavi/src/tainavi/AbsSettingView.java
+++ b/TinyBannavi/src/tainavi/AbsSettingView.java
@@ -2919,7 +2919,7 @@ public abstract class AbsSettingView extends JScrollPane {
29192919 jComboBox_fontSize = new JComboBox();
29202920 DefaultComboBoxModel model = new DefaultComboBoxModel();
29212921 jComboBox_fontSize.setModel(model);
2922- for ( int i=6; i<=20; i++ ) {
2922+ for ( int i=6; i<=24; i++ ) {
29232923 model.addElement(String.valueOf(i));
29242924 }
29252925 if ( env.getFontSize() > 0) {
--- a/TinyBannavi/src/tainavi/AbsTitleDialog.java
+++ b/TinyBannavi/src/tainavi/AbsTitleDialog.java
@@ -136,6 +136,7 @@ abstract class AbsTitleDialog extends JDialog {
136136
137137 private JLabel jLabel_prog = null;
138138 private JTextAreaWithPopup jTextArea_prog = null;
139+ private JScrollPane jScrollPane_prog = null;
139140
140141 private JLabel jLabel_folder = null;
141142 private JList jList_folder = null;
@@ -277,6 +278,7 @@ abstract class AbsTitleDialog extends JDialog {
277278 // 番組情報が見つかったら、タイトルと詳細をセットする
278279 if (pdl != null){
279280 jTextArea_prog.setText(pdl.prefix_mark + pdl.title + pdl.postfix_mark + "\r\n" + pdl.detail);
281+ jTextArea_prog.setCaretPosition(0);
280282 }
281283
282284 }
@@ -435,18 +437,15 @@ abstract class AbsTitleDialog extends JDialog {
435437 * サブタイトルを取得する
436438 */
437439 protected String getSubtitle(String title, ProgDetailList pdl){
438- String subc = searchSubtitleCombo(pdl.title + " " + pdl.detail);
440+ String title2 = pdl.title + " " + pdl.detail;
441+ String subc = searchSubtitleCombo(title2);
439442 if (subc != null)
440443 return subc;
441444
442- String sub1 = searchSubtitle(title);
445+ String sub1 = searchSubtitle(title2);
443446 if (sub1 != null)
444447 return sub1;
445448
446- String sub2 = searchSubtitle(pdl.title + " " + pdl.detail);
447- if (sub2 != null)
448- return sub2;
449-
450449 return "";
451450 }
452451
@@ -855,7 +854,7 @@ abstract class AbsTitleDialog extends JDialog {
855854 jPanel.add(label);
856855
857856 y += PARTS_HEIGHT;
858- JTextAreaWithPopup area = getJTextArea_prog();
857+ JScrollPane area = getJScrollPane_prog();
859858 area.setBounds(x, y, TEXT_WIDTH, RESERV_HEIGHT);
860859 jPanel.add(area);
861860 if (folderOnly)
@@ -947,12 +946,22 @@ abstract class AbsTitleDialog extends JDialog {
947946 }
948947
949948 //
949+ private JScrollPane getJScrollPane_prog() {
950+ if (jScrollPane_prog == null) {
951+ jScrollPane_prog = new JScrollPane(getJTextArea_prog(),JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
952+
953+ jScrollPane_prog.setBorder(jComboBox_title.getBorder());
954+ }
955+
956+ return(jScrollPane_prog);
957+ }
958+
950959 private JTextAreaWithPopup getJTextArea_prog() {
951960 if (jTextArea_prog == null) {
952961 jTextArea_prog = new JTextAreaWithPopup();
953962 jTextArea_prog.setLineWrap(true);
954963 jTextArea_prog.addKeyListener(kl_cancel);
955- jTextArea_prog.setBorder(jComboBox_title.getBorder());
964+// jTextArea_prog.setBorder(jComboBox_title.getBorder());
956965 jTextArea_prog.setEditable(false);
957966 }
958967 return(jTextArea_prog);
--- a/TinyBannavi/src/tainavi/AbsTitleListView.java
+++ b/TinyBannavi/src/tainavi/AbsTitleListView.java
@@ -483,6 +483,10 @@ public abstract class AbsTitleListView extends JPanel {
483483 if (rec == null)
484484 return;
485485
486+ // タイトルに対応していないレコーダは何もしない
487+ if (!rec.isTitleListSupported())
488+ return;
489+
486490 titleUpdating = true;
487491 String device_id = getSelectedDeviceId();
488492 if (device_id == null)
@@ -616,6 +620,11 @@ public abstract class AbsTitleListView extends JPanel {
616620 HDDRecorder rec = getSelectedRecorder();
617621 if (rec == null)
618622 return;
623+
624+ // タイトルに対応していないレコーダは何もしない
625+ if (!rec.isTitleListSupported())
626+ return;
627+
619628 if (deviceUpdating)
620629 return;
621630
@@ -677,6 +686,10 @@ public abstract class AbsTitleListView extends JPanel {
677686 if (rec == null)
678687 return;
679688
689+ // タイトルに対応していないレコーダは何もしない
690+ if (!rec.isTitleListSupported())
691+ return;
692+
680693 String device_id = getSelectedDeviceId();
681694 String device_name = device_id != null ? rec.getDeviceName(device_id) : null;
682695 if (device_name != null)
@@ -904,6 +917,8 @@ public abstract class AbsTitleListView extends JPanel {
904917 if (ro.getRecording())
905918 sa.title += " (録画中)";
906919 sa.chname = ro.getCh_name();
920+ if (sa.chname == null ||sa.chname.isEmpty())
921+ sa.chname = ro.getChannel();
907922 sa.devname = ro.getRec_device();
908923 sa.folder = ro.getFolderNameList();
909924 sa.genre = ro.getGenreNameList();
--- a/TinyBannavi/src/tainavi/AbsToolBar.java
+++ b/TinyBannavi/src/tainavi/AbsToolBar.java
@@ -209,7 +209,6 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
209209 private static final String HELP_URL = "http://sourceforge.jp/projects/tainavi/wiki/FrontPage";
210210
211211 private static final int OPENING_WIAT = 500; // まあ起動時しか使わないんですけども
212- private static final int MAX_SEARCH_WORDS = 32;
213212
214213 // ログ関連
215214
@@ -1346,8 +1345,9 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
13461345 jComboBox_keyword.addItem("");
13471346
13481347 int num=0;
1348+ int max = env.getMaxSearchWordNuml();
13491349 for (SearchWordItem item : swlist.getWordList()){
1350- if (num >= MAX_SEARCH_WORDS)
1350+ if (max > 0 && num >= max)
13511351 break;
13521352
13531353 jComboBox_keyword.addItem(item.getLabel());
--- a/TinyBannavi/src/tainavi/Env.java
+++ b/TinyBannavi/src/tainavi/Env.java
@@ -14,6 +14,7 @@ import java.util.regex.Pattern;
1414 * @version 3.15.4β {@link #getAutoEventIdComplete()} 追加
1515 */
1616 public class Env {
17+ public static Env TheEnv = null;
1718
1819 /*******************************************************************************
1920 * 定数とか
@@ -64,6 +65,8 @@ public class Env {
6465 private static final Color RESTIMEBAR_COLOR_4 = new Color(255,0,255); // MAGENTA;
6566 private static final int RESTIMEBAR_WIDTH = 4;
6667
68+ private static final int MAX_SEARCH_WORD_NUM = 64;
69+
6770 // この記述は…どうなの?
6871 private static final String TV_SITE = "Dimora";
6972 private static final String CS_SITE = "Gガイド.テレビ王国(スカパー!)";
@@ -982,7 +985,7 @@ public class Env {
982985 public void setFontSize(int f) { fontSize = f; }
983986 private int fontSize = 12;
984987
985- public int ZMSIZE(int size){ return size*fontSize/12; }
988+ public static int ZMSIZE(int size){ return TheEnv != null ? size*TheEnv.fontSize/12 : size; }
986989
987990 public boolean getUseGTKRC() { return useGTKRC; }
988991 public void setUseGTKRC(boolean b) { useGTKRC = b; }
@@ -1014,6 +1017,11 @@ public class Env {
10141017 public void setHolidayFetchInterval(int n){ holidayFetchInterval = n; }
10151018 private int holidayFetchInterval = 90;
10161019
1020+ // 検索キーワードの最大数
1021+ public int getMaxSearchWordNuml(){ return maxSearchWordNum; }
1022+ public void setMaxSearchWordNum(int n){ maxSearchWordNum = n; }
1023+ private int maxSearchWordNum = MAX_SEARCH_WORD_NUM;
1024+
10171025 /*******************************************************************************
10181026 * 作ったけど使ってないもの
10191027 ******************************************************************************/
--- a/TinyBannavi/src/tainavi/JNETable.java
+++ b/TinyBannavi/src/tainavi/JNETable.java
@@ -23,12 +23,19 @@ public class JNETable extends JTable {
2323 // 行ごとに色を変える
2424 protected boolean isSepRowColor = true;
2525 public void setSepRowColor(boolean b) { isSepRowColor = b; }
26-
26+
2727 protected static final Color evenColor = new Color(240,240,255);
28-
28+
2929 @Override
3030 public Component prepareRenderer(TableCellRenderer tcr, int row, int column) {
31- Component c = super.prepareRenderer(tcr, row, column);
31+ Component c = null;
32+ try{
33+ c = super.prepareRenderer(tcr, row, column);
34+ }
35+ catch(ArrayIndexOutOfBoundsException e){
36+ return null;
37+ }
38+
3239 Color fgColor = null;
3340 Color bgColor = null;
3441 if(isRowSelected(row)) {
@@ -41,19 +48,19 @@ public class JNETable extends JTable {
4148 }
4249 if ( ! (tcr instanceof VWColorCharCellRenderer) && ! (tcr instanceof VWColorCharCellRenderer2) && ! (tcr instanceof VWColorCellRenderer)) {
4350 c.setForeground((this.isEnabled()) ? fgColor : Color.GRAY);
44- }
51+ }
4552 if ( ! (tcr instanceof VWColorCellRenderer)) {
4653 c.setBackground(bgColor);
4754 }
4855 return c;
4956 }
50-
57+
5158 // 列の表示・非表示
5259 private class ColumnData {
5360 TableColumn column;
5461 boolean visible;
5562 }
56-
63+
5764 private ColumnData[] colDat = null;
5865
5966 public void setColumnVisible(String name, boolean b) {
@@ -61,7 +68,7 @@ public class JNETable extends JTable {
6168 if ( name == null ) {
6269 return;
6370 }
64-
71+
6572 // 初回は情報を蓄える
6673 if ( colDat == null ) {
6774 colDat = new ColumnData[this.getColumnModel().getColumnCount()];
@@ -72,7 +79,7 @@ public class JNETable extends JTable {
7279 colDat[i] = cdat;
7380 }
7481 }
75-
82+
7683 // 列を検索する
7784 int idx = -1;
7885 for ( int i=0; i<colDat.length; i++ ) {
@@ -86,7 +93,7 @@ public class JNETable extends JTable {
8693 if ( idx == -1 ) {
8794 return;
8895 }
89-
96+
9097 if ( ! b ) {
9198 // 削除する
9299 colDat[idx].visible = false;
@@ -120,14 +127,14 @@ public class JNETable extends JTable {
120127 this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
121128 }
122129 this.getTableHeader().setReorderingAllowed(false);
123-
130+
124131 // フォントサイズ変更にあわせて行の高さを変える
125132 this.addPropertyChangeListener("font", new RowHeightChangeListener(4));
126133
127134 // 行の高さの初期値の設定
128135 this.firePropertyChange("font", "old", "new");
129136 }
130-
137+
131138 public JNETable(TableModel d, boolean b) {
132139 this(b);
133140 this.setModel(d);
--- a/TinyBannavi/src/tainavi/LikeReserveEditorPanel.java
+++ b/TinyBannavi/src/tainavi/LikeReserveEditorPanel.java
@@ -125,6 +125,8 @@ public class LikeReserveEditorPanel extends JScrollPane {
125125 Dimension d = new Dimension(LIKELIST_WIDTH, (int)(PARTS_HEIGHT*LIKELIST_ROWS+PARTS_HEIGHT*0.5));
126126 setPreferredSize(d);
127127
128+ jrhdr_likersv.setRowHeight(jtbl_likersv.getRowHeight());
129+
128130 // 選択行が表示されるよう自動で移動するようにする
129131 CommonSwingUtils.setSelectedRowShown(jtbl_likersv);
130132 }
@@ -210,7 +212,7 @@ public class LikeReserveEditorPanel extends JScrollPane {
210212 continue;
211213 }
212214 column = columnModel.getColumn(lc.ordinal());
213- column.setPreferredWidth(lc.getIniWidth());
215+ column.setPreferredWidth(ZMSIZE(lc.getIniWidth()));
214216 }
215217
216218 // 行選択した際のイベントリスナー
@@ -220,6 +222,8 @@ public class LikeReserveEditorPanel extends JScrollPane {
220222 return jtbl_likersv;
221223 }
222224
225+ private int ZMSIZE(int size){ return Env.ZMSIZE(size); }
226+
223227
224228 /*******************************************************************************
225229 *
--- a/TinyBannavi/src/tainavi/RecSettingEditorPanel.java
+++ b/TinyBannavi/src/tainavi/RecSettingEditorPanel.java
@@ -11,6 +11,7 @@ import java.awt.event.ItemListener;
1111 import java.util.ArrayList;
1212
1313 import javax.swing.JButton;
14+import javax.swing.JComponent;
1415 import javax.swing.JLabel;
1516 import javax.swing.JPanel;
1617 import javax.swing.SpringLayout;
@@ -115,6 +116,7 @@ public class RecSettingEditorPanel extends JPanel {
115116 public RecSettingEditorPanel() {
116117
117118 super();
119+
118120 setBorder(new LineBorder(Color.BLACK, 1));
119121
120122 addComponents();
@@ -140,80 +142,113 @@ public class RecSettingEditorPanel extends JPanel {
140142
141143 setLayout(new SpringLayout());
142144
145+ int lw = ZMSIZE(LABEL_WIDTH);
146+ int bw = ZMSIZE(BUTTON_WIDTH);
147+ int cw = ZMSIZE(COMBO_WIDTH);
148+ int cww = ZMSIZE(COMBO_WIDTH_WIDE);
149+ int sw = ZMSIZE(SEP_WIDTH);
150+ int swn = ZMSIZE(SEP_WIDTH_NARROW);
151+ int shn = ZMSIZE(SEP_HEIGHT_NALLOW);
152+
153+ int ph = ZMSIZE2(PARTS_HEIGHT);
154+ int ch = ZMSIZE2(COMBO_HEIGHT);
155+ int sh = ZMSIZE2(SEP_HEIGHT);
156+
157+ int lwi = ZMSIZE(110);
158+ int cwi = ZMSIZE(150);
159+ int cwn = ZMSIZE(110);
160+ int bwn = ZMSIZE(30);
161+ int cbw = ZMSIZE(75);
162+
163+ // 1行目(レコーダ、エンコーダ)
143164 int y = 0;
144- int x = SEP_WIDTH_NARROW;
165+ int x = swn;
145166
146- CommonSwingUtils.putComponentOn(this, jCBXPanel_recorder = new JComboBoxPanel("",RECORDER_WIDTH,RECORDER_WIDTH), RECORDER_WIDTH+5, COMBO_HEIGHT+SEP_HEIGHT, x, y);
147- CommonSwingUtils.putComponentOn(this, jCBXPanel_encoder = new JComboBoxPanel("",ENCODER_WIDTH,ENCODER_WIDTH), ENCODER_WIDTH+5, COMBO_HEIGHT+SEP_HEIGHT, x+=RECORDER_WIDTH+5+SEP_WIDTH, y);
148- CommonSwingUtils.putComponentOn(this, jLabel_encoderemptywarn = new JLabel(""), LABEL_WIDTH, PARTS_HEIGHT, x+=ENCODER_WIDTH+5+SEP_WIDTH+5, y+PARTS_HEIGHT);
167+ int rw = ZMSIZE(RECORDER_WIDTH);
168+ int ew = ZMSIZE(ENCODER_WIDTH);
169+ int sp = ZMSIZE(5);
170+ add(jCBXPanel_recorder = getComboBox(rw,rw), rw+sp, ch, x, y);
171+ add(jCBXPanel_encoder = getComboBox(ew,ew), ew+sp, ch, x+=rw+sp+sw, y);
172+ add(jLabel_encoderemptywarn = new JLabel(""), lw, ph, x+=ew+sp+sw+sp, y+ph);
149173
150174 jCBXPanel_recorder.getJComboBox().setForeground(Color.BLUE);
151175 jCBXPanel_encoder.getJComboBox().setForeground(Color.BLUE);
152176
153177 // ポップアップした時に追加される幅
154- jCBXPanel_recorder.addPopupWidth(100);
155- jCBXPanel_encoder.addPopupWidth(100);
156-
157- y += (COMBO_HEIGHT+SEP_HEIGHT)+SEP_HEIGHT;
158- x = SEP_WIDTH_NARROW;
159- CommonSwingUtils.putComponentOn(this, jCBXPanel_genre = new JComboBoxPanel("",110,150), COMBO_WIDTH_WIDE, COMBO_HEIGHT, x, y);
160- CommonSwingUtils.putComponentOn(this, jCBXPanel_subgenre = new JComboBoxPanel("",110,150), COMBO_WIDTH_WIDE, COMBO_HEIGHT, x+=(COMBO_WIDTH_WIDE+SEP_WIDTH), y);
161- CommonSwingUtils.putComponentOn(this, jCBXPanel_autodel = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x+=(COMBO_WIDTH+SEP_WIDTH)*2, y);
162- CommonSwingUtils.putComponentOn(this, jCBXPanel_xChapter = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x+=(COMBO_WIDTH+SEP_WIDTH), y);
163-
164- y += COMBO_HEIGHT;
165- x = SEP_WIDTH_NARROW;
166- CommonSwingUtils.putComponentOn(this, jCBXPanel_videorate = new JComboBoxPanel("",110,150), COMBO_WIDTH_WIDE, COMBO_HEIGHT, x, y);
167- CommonSwingUtils.putComponentOn(this, jCBXPanel_audiorate = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x+=(COMBO_WIDTH_WIDE+SEP_WIDTH), y);
168- CommonSwingUtils.putComponentOn(this, jCBXPanel_bvperf = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x+=(COMBO_WIDTH+SEP_WIDTH), y);
169- CommonSwingUtils.putComponentOn(this, jCBXPanel_lvoice = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x+=(COMBO_WIDTH+SEP_WIDTH), y);
170- CommonSwingUtils.putComponentOn(this, jCBXPanel_msChapter = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x+=(COMBO_WIDTH+SEP_WIDTH), y);
171-
172- y += COMBO_HEIGHT;
173- x = SEP_WIDTH_NARROW;
174- CommonSwingUtils.putComponentOn(this, getJButton_addFolder("新"), 30, PARTS_HEIGHT, x+COMBO_WIDTH_WIDE-60, y);
175- CommonSwingUtils.putComponentOn(this, getJButton_delFolder("削"), 30, PARTS_HEIGHT, x+COMBO_WIDTH_WIDE-30, y);
176- CommonSwingUtils.putComponentOn(this, jCBXPanel_folder = new JComboBoxPanel("",100,150), COMBO_WIDTH_WIDE, COMBO_HEIGHT, x, y);
177- CommonSwingUtils.putComponentOn(this, jCBXPanel_device = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x+=(COMBO_WIDTH_WIDE+SEP_WIDTH), y);
178- CommonSwingUtils.putComponentOn(this, jCBXPanel_dvdcompat = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x+=(COMBO_WIDTH+SEP_WIDTH), y);
179- CommonSwingUtils.putComponentOn(this, jCBXPanel_aspect = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x+=(COMBO_WIDTH+SEP_WIDTH), y);
180- CommonSwingUtils.putComponentOn(this, jCBXPanel_mvChapter = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x+=(COMBO_WIDTH+SEP_WIDTH), y);
181- jCBXPanel_folder.addPopupWidth(300);
182-
183- y += COMBO_HEIGHT;
184- x = SEP_WIDTH_NARROW;
185- CommonSwingUtils.putComponentOn(this, jCBXPanel_portable = new JComboBoxPanel("",110,150), COMBO_WIDTH_WIDE, COMBO_HEIGHT, x, y);
186- x += (COMBO_WIDTH_WIDE+SEP_WIDTH) + (COMBO_WIDTH+SEP_WIDTH)*3;
187- CommonSwingUtils.putComponentOn(this, jCBXPanel_pursues = new JComboBoxPanel("",110,110), COMBO_WIDTH, COMBO_HEIGHT, x, y);
188-
189- y += COMBO_HEIGHT;
190-
191- // 特殊配置
192- {
193- int spy = SEP_HEIGHT_NALLOW+(PARTS_HEIGHT+SEP_HEIGHT_NALLOW)*2;
194- x = SEP_WIDTH_NARROW+(COMBO_WIDTH_WIDE+SEP_WIDTH)+(COMBO_WIDTH+SEP_WIDTH)*4+SEP_WIDTH;
195-
196- CommonSwingUtils.putComponentOn(this, jLabel_rectype = new JLabel("ジャンル別の"), LABEL_WIDTH, PARTS_HEIGHT, x, spy);
197-
198- spy+=PARTS_HEIGHT-5;
199-
200- CommonSwingUtils.putComponentOn(this, new JLabel("録画設定の選択"), LABEL_WIDTH, PARTS_HEIGHT, x, spy);
201- CommonSwingUtils.putComponentOn(this, jButton_load = new JButton("開く"), BUTTON_WIDTH, PARTS_HEIGHT, x+SEP_WIDTH_NARROW, spy+=PARTS_HEIGHT);
202- CommonSwingUtils.putComponentOn(this, jButton_save = new JButton("保存"), BUTTON_WIDTH, PARTS_HEIGHT, x+SEP_WIDTH_NARROW, spy+=PARTS_HEIGHT);
203- CommonSwingUtils.putComponentOn(this, jButton_savedefault = new JButton("既定化"), BUTTON_WIDTH, PARTS_HEIGHT, x+SEP_WIDTH_NARROW, spy+=(PARTS_HEIGHT+SEP_HEIGHT));
204-
205- jButton_savedefault.setToolTipText(TEXT_SAVEDEFAULT);
206-
207- CommonSwingUtils.putComponentOn(this, jCheckBox_Exec = new JCheckBoxPanel("予約実行",75,true), 75, PARTS_HEIGHT, x+SEP_WIDTH_NARROW, spy+=(PARTS_HEIGHT+SEP_HEIGHT));
208- setExecValue(true);
209- }
210-
211- x+=BUTTON_WIDTH+SEP_WIDTH_NARROW*2;
178+ jCBXPanel_recorder.addPopupWidth(ZMSIZE(100));
179+ jCBXPanel_encoder.addPopupWidth(ZMSIZE(100));
180+
181+ // 2行目(ジャンル、サブジャンル、自動削除、無音部分チャプタ分割)
182+ y += ch;
183+ x = swn;
184+ int spy = y;
185+ add(jCBXPanel_genre = getComboBox(lwi,cwi), cww, ch, x, y);
186+ add(jCBXPanel_subgenre = getComboBox(lwi,cwi), cww, ch, x+=(cww+sw), y);
187+ add(jCBXPanel_autodel = getComboBox(lwi,cwn), cw, ch, x+=(cw+sw)*2, y);
188+ add(jCBXPanel_xChapter = getComboBox(lwi,cwn), cw, ch, x+=(cw+sw), y);
189+
190+ // 3行目(画質、音質、録画優先度、ライン音声選択、マジックチャプタ(シーン))
191+ y += ch;
192+ x = swn;
193+ add(jCBXPanel_videorate = getComboBox(lwi,cwi), cww, ch, x, y);
194+ add(jCBXPanel_audiorate = getComboBox(lwi,cwn), cw, ch, x+=(cww+sw), y);
195+ add(jCBXPanel_bvperf = getComboBox(lwi,cwn), cw, ch, x+=(cw+sw), y);
196+ add(jCBXPanel_lvoice = getComboBox(lwi,cwn), cw, ch, x+=(cw+sw), y);
197+ add(jCBXPanel_msChapter = getComboBox(lwi,cwn), cw, ch, x+=(cw+sw), y);
198+
199+ // 4行目(記録先フォルダ、記録先デバイス、BD/DVD、録画のりしろ、マジックチャプタ(本編))
200+ y += ch;
201+ x = swn;
202+ add(getJButton_addFolder("新"), bwn, ZMSIZE(17), x+cww-bwn*2, y);
203+ add(getJButton_delFolder("削"), bwn, ZMSIZE(17), x+cww-bwn, y);
204+ add(jCBXPanel_folder = getComboBox(lwi-10,cwi),cww, ch, x, y);
205+ add(jCBXPanel_device = getComboBox(lwi,cwn), cw, ch, x+=(cww+sw), y);
206+ add(jCBXPanel_dvdcompat = getComboBox(lwi,cwn), cw, ch, x+=(cw+sw), y);
207+ add(jCBXPanel_aspect = getComboBox(lwi,cwn), cw, ch, x+=(cw+sw), y);
208+ add(jCBXPanel_mvChapter = getComboBox(lwi,cwn), cw, ch, x+=(cw+sw), y);
209+ jCBXPanel_folder.addPopupWidth(ZMSIZE(300));
210+
211+ // 5行目(持ち出し、番組追従)
212+ y += ch;
213+ x = swn;
214+ add(jCBXPanel_portable = getComboBox(lwi,cwi), cww, ch, x, y);
215+ x += (cww+sw) + (cw+sw)*3;
216+ add(jCBXPanel_pursues = getComboBox(lwi,cwn), cw, ch, x, y);
217+
218+ y += ch;
219+
220+ // 特殊配置(開く、保存、既定化、予約実行)
221+ x = swn+(cww+sw)+(cw+sw)*4+sw;
222+ add(jLabel_rectype = new JLabel("ジャンル別の"), lw, ph, x, spy);
223+ spy += ph-ZMSIZE(5);
224+ add(new JLabel("録画設定の選択"), lw, ph, x, spy);
225+
226+ add(jButton_load = new JButton("開く"), bw, ph, x+swn, spy+=ph);
227+ add(jButton_save = new JButton("保存"), bw, ph, x+swn, spy+=ph);
228+ add(jButton_savedefault = new JButton("既定化"), bw, ph, x+swn, spy+=(ph+sh));
229+
230+ jButton_savedefault.setToolTipText(TEXT_SAVEDEFAULT);
231+
232+ add(jCheckBox_Exec = new JCheckBoxPanel("予約実行",cbw,true), cbw, ph, x+swn, spy+=(ph+sh));
233+ setExecValue(true);
234+
235+ x += bw+swn*2;
212236
213237 Dimension d = new Dimension(x,y);
214238 setPreferredSize(d);
215239 }
216240
241+ private int ZMSIZE(int size){ return Env.ZMSIZE(size); }
242+ private int ZMSIZE2(int size){ return ZMSIZE(size-20) + 20; }
243+
244+ private JComboBoxPanel getComboBox(int lwidth, int cwidth){
245+ return new JComboBoxPanel("", lwidth, cwidth);
246+ }
247+
248+ private void add(JComponent c, int width, int height, int x, int y) {
249+ CommonSwingUtils.putComponentOn(this, c, width, height, x, y);
250+ }
251+
217252 public void setRecSettingSelector(RecSettingSelectable o) {
218253 recsetsel = o;
219254 }
--- a/TinyBannavi/src/tainavi/TitleEditorPanel.java
+++ b/TinyBannavi/src/tainavi/TitleEditorPanel.java
@@ -11,6 +11,7 @@ import java.util.GregorianCalendar;
1111
1212 import javax.swing.JButton;
1313 import javax.swing.JComboBox;
14+import javax.swing.JComponent;
1415 import javax.swing.JLabel;
1516 import javax.swing.JPanel;
1617 import javax.swing.JScrollPane;
@@ -33,7 +34,7 @@ public class TitleEditorPanel extends JPanel {
3334 ******************************************************************************/
3435
3536 // レイアウト関連
36- private static final int PARTS_HEIGHT = 25;
37+ private static final int PARTS_HEIGHT = 20;
3738 private static final int SEP_WIDTH = 10;
3839 private static final int SEP_WIDTH_NARROW = 5;
3940 // private static final int SEP_HEIGHT = 10;
@@ -142,82 +143,94 @@ public class TitleEditorPanel extends JPanel {
142143
143144 setLayout(new SpringLayout());
144145
145- int y = SEP_HEIGHT_NALLOW;
146- int x = SEP_WIDTH_NARROW;
147-
148- CommonSwingUtils.putComponentOn(this, getJLabel_title("予約名"), 50, PARTS_HEIGHT, x, y);
149- CommonSwingUtils.putComponentOn(this, getJComboBox_title(), TITLE_WIDTH, PARTS_HEIGHT, x+SEP_WIDTH_NARROW, y+PARTS_HEIGHT);
150-
151- CommonSwingUtils.putComponentOn(this, getJButton_addDate("日付追加"), 100, PARTS_HEIGHT, x+SEP_WIDTH_NARROW+TITLE_WIDTH-125-SEP_WIDTH, y);
152-
153- CommonSwingUtils.putComponentOn(this, getJButton_ch("放送局"), 100, PARTS_HEIGHT, x+TITLE_WIDTH+SEP_WIDTH, y);
154- CommonSwingUtils.putComponentOn(this, getJComboBox_ch(), CHNAME_WIDTH, PARTS_HEIGHT, x+TITLE_WIDTH+SEP_WIDTH+SEP_WIDTH_NARROW, y+PARTS_HEIGHT);
155-
156- y += PARTS_HEIGHT*2+SEP_HEIGHT_NALLOW;
157-
158- {
159- int hmx = x;
160- CommonSwingUtils.putComponentOn(this, getJLabel_date("録画日付"), LABEL_WIDTH, PARTS_HEIGHT, hmx,y);
161- CommonSwingUtils.putComponentOn(this, getJComboBox_date(), DATE_WIDTH, PARTS_HEIGHT, hmx+=SEP_WIDTH_NARROW, y+PARTS_HEIGHT);
162-
163- hmx += DATE_WIDTH+SEP_WIDTH;
164- CommonSwingUtils.putComponentOn(this, getJLabel_aTime("開始時刻"), 75, PARTS_HEIGHT, hmx, y);
165- CommonSwingUtils.putComponentOn(this, getJTextField_ahh(), HOUR_WIDTH, PARTS_HEIGHT, hmx+=SEP_WIDTH_NARROW, y+PARTS_HEIGHT);
166- CommonSwingUtils.putComponentOn(this, getJLabel_asep(":"), 10, PARTS_HEIGHT, hmx+=HOUR_WIDTH, y+PARTS_HEIGHT);
167- CommonSwingUtils.putComponentOn(this, getJTextField_amm(), HOUR_WIDTH, PARTS_HEIGHT, hmx+=10, y+PARTS_HEIGHT);
168- CommonSwingUtils.putComponentOn(this, getJButton_amm_up(), 20, 12, hmx+=HOUR_WIDTH+2, y+PARTS_HEIGHT);
169- CommonSwingUtils.putComponentOn(this, getJButton_amm_down(), 20, 12, hmx, y+PARTS_HEIGHT+13);
170-
171- hmx += 20+SEP_WIDTH_NARROW;
172-
173- CommonSwingUtils.putComponentOn(this, getJLabel_zTime("終了時刻"), 75, PARTS_HEIGHT, hmx, y);
174- {
175- CommonSwingUtils.putComponentOn(this, new JLabel("録画時間"), 75, PARTS_HEIGHT, hmx, y+PARTS_HEIGHT*2+2);
176- }
177- CommonSwingUtils.putComponentOn(this, getJTextField_zhh(), HOUR_WIDTH, PARTS_HEIGHT, hmx+=SEP_WIDTH_NARROW, y+PARTS_HEIGHT);
178- CommonSwingUtils.putComponentOn(this, getJLabel_zsep(":"), 10, PARTS_HEIGHT, hmx+=HOUR_WIDTH, y+PARTS_HEIGHT);
179- CommonSwingUtils.putComponentOn(this, getJTextField_zmm(), HOUR_WIDTH, PARTS_HEIGHT, hmx+=10, y+PARTS_HEIGHT);
180- {
181- CommonSwingUtils.putComponentOn(this, getJLabel_recmin(""), HOUR_WIDTH+10, PARTS_HEIGHT-2, hmx-10, y+PARTS_HEIGHT*2+2+1);
182- }
183- CommonSwingUtils.putComponentOn(this, getJButton_zmm_up(), 20, 12, hmx+=HOUR_WIDTH+2, y+PARTS_HEIGHT);
184- CommonSwingUtils.putComponentOn(this, getJButton_zmm_down(), 20, 12, hmx, y+PARTS_HEIGHT+13);
185-
186- hmx += 20+SEP_WIDTH;
187-
188- CommonSwingUtils.putComponentOn(this, jCheckBox_Autocomplete = new JCheckBoxPanel("タイトル自動補完(RDのみ)",LABEL_WIDTH,true), 200, PARTS_HEIGHT, hmx, y);
189- CommonSwingUtils.putComponentOn(this, getJCheckBox_spoex_extend("延長警告での終了時刻延長",LABEL_WIDTH,true), 200, PARTS_HEIGHT, hmx, y+PARTS_HEIGHT);
190- CommonSwingUtils.putComponentOn(this, getJCheckBox_OverlapDown2("終了時刻1分短縮",LABEL_WIDTH,true), 200, PARTS_HEIGHT, hmx, y+PARTS_HEIGHT*2);
191- }
192-
193- y += PARTS_HEIGHT*2+SEP_WIDTH_NARROW;
194-
195- CommonSwingUtils.putComponentOn(this, getJLabel_detail("番組詳細"), 100, PARTS_HEIGHT, x, y);
196- CommonSwingUtils.putComponentOn(this, getJScrollPane_detail(), DETAIL_WIDTH, DETAIL_HEIGHT, x+SEP_WIDTH_NARROW, y+PARTS_HEIGHT);
197-
198- y += PARTS_HEIGHT;
199-
200-
201-
202- y += DETAIL_HEIGHT+SEP_HEIGHT_NALLOW;
146+ int lw = ZMSIZE(LABEL_WIDTH);
147+ int bw = ZMSIZE(BUTTON_WIDTH);
148+ int sw = ZMSIZE(SEP_WIDTH);
149+ int swn = ZMSIZE(SEP_WIDTH_NARROW);
150+ int shn = ZMSIZE(SEP_HEIGHT_NALLOW);
151+ int tw = ZMSIZE(TITLE_WIDTH);
152+
153+ int cw = ZMSIZE(CHNAME_WIDTH);
154+ int cbw = ZMSIZE(200);
155+ int dw = ZMSIZE(DATE_WIDTH);
156+ int hw = ZMSIZE(HOUR_WIDTH);
157+ int dtw = ZMSIZE(DETAIL_WIDTH);
158+ int dth = ZMSIZE(DETAIL_HEIGHT);
159+
160+ int ph = ZMSIZE(PARTS_HEIGHT);
161+
162+ // 1行目、2行目
163+ int y = shn;
164+ int x = swn;
165+ int abw = ZMSIZE(100);
166+ add(getJLabel_title("予約名"), lw, ph, x, y);
167+ add(getJComboBox_title(), tw, ph, x+=swn, y+ph);
168+ add(getJButton_addDate("日付追加"), abw, ph, x+=tw-abw*2-sw, y);
169+ add(getJButton_ch("放送局追加"), abw, ph, x+=abw+sw, y);
170+ add(getJComboBox_ch(), cw, ph, x+=abw+swn, y+ph);
171+
172+ // 3行目、4行目
173+ y += ph*2;
174+ x = swn;
175+ add(getJLabel_date("録画日付"), lw, ph, x, y);
176+ add(getJComboBox_date(), dw, ph, x+=swn, y+ph);
177+
178+ x += dw+swn;
179+ int hbw = ZMSIZE(20);
180+ int hbh = ZMSIZE(10);
181+ int hsw = ZMSIZE(10);
182+ add(getJLabel_aTime("開始時刻"), lw, ph, x, y);
183+ add(getJTextField_ahh(), hw, ph, x+=swn, y+ph);
184+ add(getJLabel_asep(":"), hsw, ph, x+=hw, y+ph);
185+ add(getJTextField_amm(), hw, ph, x+=hsw, y+ph);
186+ add(getJButton_amm_up(), hbw, hbh, x+=hw+2, y+ph);
187+ add(getJButton_amm_down(), hbw, hbh, x, y+ph+hbh+1);
188+
189+ add(getJLabel_zTime("終了時刻"), lw, ph, x+=hbw+swn, y);
190+ int xlrm = x;
191+ add(getJTextField_zhh(), hw, ph, x+=swn, y+ph);
192+ add(getJLabel_zsep(":"), hsw, ph, x+=hw, y+ph);
193+ add(getJTextField_zmm(), hw, ph, x+=hsw, y+ph);
194+ int xrm = x;
195+ add(getJButton_zmm_up(), hbw, hbh, x+=hw+2, y+ph);
196+ add(getJButton_zmm_down(), hbw, hbh, x, y+ph+hbh+1);
197+
198+ x += hbw+sw;
199+ add(getJCheckBox_Autocomplete("タイトル自動補完(RDのみ)",lw,true), cbw, ph, x, y);
200+ add(getJCheckBox_spoex_extend("延長警告での終了時刻延長",lw,true), cbw, ph, x, y+ph);
201+ add(getJCheckBox_OverlapDown2("終了時刻1分短縮",lw,true), cbw, ph, x, y+ph*2);
202+
203+ // 5行目、6行目
204+ y += ph*2;
205+ x = swn;
206+ add(getJLabel_detail("番組詳細"), lw, ph, x, y);
207+ add(getJScrollPane_detail(), dtw, dth, x+swn, y+ph);
208+ add(new JLabel("録画時間"), lw, ph, xlrm, y);
209+ add(getJLabel_recmin(""), hw, ph-2, xrm, y+1);
210+
211+ y += ph+dth+shn;
203212
204213 // 特殊配置
205- {
206- int spy = SEP_HEIGHT_NALLOW+PARTS_HEIGHT;
207- x = SEP_WIDTH_NARROW+DETAIL_WIDTH+SEP_WIDTH*2;
214+ int spy = shn+ph;
215+ x = swn+dtw+sw*2;
208216
209- CommonSwingUtils.putComponentOn(this, new JLabel("予約"), BUTTON_WIDTH, PARTS_HEIGHT, x, spy);
210- CommonSwingUtils.putComponentOn(this, getJButton_record("新規"), BUTTON_WIDTH, PARTS_HEIGHT, x+SEP_WIDTH_NARROW, spy+=PARTS_HEIGHT);
211- CommonSwingUtils.putComponentOn(this, getJButton_update("更新"), BUTTON_WIDTH, PARTS_HEIGHT, x+SEP_WIDTH_NARROW, spy+=PARTS_HEIGHT);
212- CommonSwingUtils.putComponentOn(this, getJButton_cancel("キャンセル"), BUTTON_WIDTH, PARTS_HEIGHT, x+SEP_WIDTH_NARROW, spy+=PARTS_HEIGHT);
213- }
217+ add(new JLabel("予約"), bw, ph, x, spy);
218+ add(getJButton_record("新規"), bw, ph, x+swn, spy+=ph);
219+ add(getJButton_update("更新"), bw, ph, x+swn, spy+=ph);
220+ add(getJButton_cancel("キャンセル"), bw, ph, x+swn, spy+=ph*2);
214221
215- x+=BUTTON_WIDTH+SEP_WIDTH_NARROW*2;
222+ x+=bw+swn*2;
216223
217224 Dimension d = new Dimension(x,y);
218225 setPreferredSize(d);
219226 }
220227
228+ private int ZMSIZE(int size){ return Env.ZMSIZE(size); }
229+
230+ private void add(JComponent c, int width, int height, int x, int y) {
231+ CommonSwingUtils.putComponentOn(this, c, width, height, x, y);
232+ }
233+
221234 public void setRecordExecuter(RecordExecutable o) {
222235 recexec = o;
223236 }
@@ -838,6 +851,14 @@ public class TitleEditorPanel extends JPanel {
838851 return(jCheckBox_OverlapDown2);
839852 }
840853
854+ private JCheckBoxPanel getJCheckBox_Autocomplete(String s, int labelWidth, boolean rev) {
855+
856+ if (jCheckBox_Autocomplete == null) {
857+ jCheckBox_Autocomplete = new JCheckBoxPanel(s,labelWidth,rev);
858+ }
859+ return(jCheckBox_Autocomplete);
860+ }
861+
841862 private JCheckBoxPanel getJCheckBox_spoex_extend(String s, int labelWidth, boolean rev) {
842863
843864 if (jCheckBox_spoex_extend == null) {
--- a/TinyBannavi/src/tainavi/VWColorChooserDialog.java
+++ b/TinyBannavi/src/tainavi/VWColorChooserDialog.java
@@ -22,6 +22,7 @@ import javax.swing.JDialog;
2222 import javax.swing.JLabel;
2323 import javax.swing.JPanel;
2424 import javax.swing.JTable;
25+import javax.swing.UIManager;
2526 import javax.swing.colorchooser.AbstractColorChooserPanel;
2627 import javax.swing.table.TableCellRenderer;
2728
@@ -31,16 +32,16 @@ public class VWColorChooserDialog extends JEscCancelDialog {
3132
3233 //
3334 private Color selectedColor = null;
34-
35+
3536 // コンストラクタ
36-
37+
3738 public VWColorChooserDialog() {
38-
39+
3940 super();
40-
41+
4142 this.setModal(true);
4243 this.setContentPane(getJPanel());
43-
44+
4445 // タイトルバーの高さも考慮する必要がある
4546 Dimension d = getJPanel().getPreferredSize();
4647 this.pack();
@@ -49,27 +50,27 @@ public class VWColorChooserDialog extends JEscCancelDialog {
4950 d.width+(this.getInsets().left+this.getInsets().right),
5051 d.height+(this.getInsets().top+this.getInsets().bottom)));
5152 this.setResizable(false);
52-*/
53+*/
5354 //
5455 this.setTitle("色見本");
5556 }
56-
57+
5758 // 公開メソッド
58-
59+
5960 @Override
6061 public void setVisible(boolean b) {
6162 super.setVisible(b);
6263 }
63-
64+
6465 public Color getSelectedColor() {
6566 return selectedColor;
6667 }
67-
68+
6869 public void setColor(Color c) {
6970 jColorChooser.setColor(c);
7071 selectedColor = null;
7172 }
72-
73+
7374 /*
7475 public void setPosition(int x, int y) {
7576 Rectangle r = this.getBounds();
@@ -78,17 +79,17 @@ public class VWColorChooserDialog extends JEscCancelDialog {
7879 this.setBounds(r);
7980 }
8081 */
81-
82+
8283 // 録画予約ウィンドウのコンポーネント
83-
84+
8485 private JPanel jPanel = null;
8586 private JColorChooser jColorChooser = null;
8687 private JPanel jPanel_buttons = null;
8788 private JButton jButton = null;
8889 private JButton jButton_cancel = null;
89-
90+
9091 // ほげほげ
91-
92+
9293 private JPanel getJPanel() {
9394 if (jPanel == null) {
9495 jPanel = new JPanel();
@@ -96,18 +97,18 @@ public class VWColorChooserDialog extends JEscCancelDialog {
9697 jPanel.add(getJColorChooser(), BorderLayout.CENTER);
9798 jPanel.add(getJPanel_buttons(), BorderLayout.SOUTH);
9899
99- Dimension d;
100- if ( CommonUtils.isLinux() ) {
101- d = new Dimension(600, 400);
102- }
103- else {
104- d = new Dimension(450, 400);
105- }
100+ Dimension d = new Dimension(Env.ZMSIZE(600), Env.ZMSIZE(400));
101+// if ( CommonUtils.isLinux() ) {
102+// d = new Dimension(600, 400);
103+// }
104+// else {
105+// d = new Dimension(450, 400);
106+// }
106107 jPanel.setPreferredSize(d);
107108 }
108109 return(jPanel);
109110 }
110-
111+
111112 private JPanel getJPanel_buttons() {
112113 if (jPanel_buttons == null) {
113114 jPanel_buttons = new JPanel();
@@ -117,7 +118,7 @@ public class VWColorChooserDialog extends JEscCancelDialog {
117118 }
118119 return(jPanel_buttons);
119120 }
120-
121+
121122 //
122123 private JColorChooser getJColorChooser() {
123124 if (jColorChooser == null) {
@@ -127,12 +128,14 @@ public class VWColorChooserDialog extends JEscCancelDialog {
127128 }
128129 else {
129130 System.out.println("[色選択ダイアログ] 標準ダイアログを使う: "+System.getProperty("java.version"));
131+ UIManager.put("ColorChooser.swatchesSwatchSize", new Dimension(Env.ZMSIZE(12), Env.ZMSIZE(12)));
132+ UIManager.put("ColorChooser.swatchesRecentSwatchSize", new Dimension(Env.ZMSIZE(12), Env.ZMSIZE(12)));
130133 jColorChooser = new JColorChooser();
131134 }
132135 }
133136 return jColorChooser;
134137 }
135-
138+
136139 private JButton getJButton(String s) {
137140 if (jButton == null) {
138141 jButton = new JButton(s);
@@ -147,7 +150,7 @@ public class VWColorChooserDialog extends JEscCancelDialog {
147150 }
148151 return(jButton);
149152 }
150-
153+
151154 private JButton getJButton_cancel(String s) {
152155 if (jButton_cancel == null) {
153156 jButton_cancel = new JButton(s);
@@ -160,13 +163,13 @@ public class VWColorChooserDialog extends JEscCancelDialog {
160163 }
161164 return(jButton_cancel);
162165 }
163-
166+
164167 @Override
165168 protected void doCancel() {
166169 selectedColor = null;
167170 setVisible(false);
168171 }
169-
172+
170173 /*
171174 * カスタムカラーチューザー
172175 */
@@ -182,22 +185,22 @@ public class VWColorChooserDialog extends JEscCancelDialog {
182185 public XColorChooser() {
183186 super();
184187 }
185-
188+
186189 @Override
187190 public void updateUI() {
188191 super.updateUI();
189192 customize();
190193 }
191-
194+
192195 @Override
193196 public void setPreviewPanel(JComponent preview) {
194197 // LookAndFeel変更でプレビューパネルが消えてしまうので
195198 if ( CommonUtils.isLinux() ) super.setPreviewPanel(preview); // Linuxでは死んでしまう
196199 }
197-
200+
198201 private void customize() {
199202 if ( CommonUtils.isLinux() ) return; // Linuxでは死んでしまう
200-
203+
201204 AbstractColorChooserPanel[] accp = this.getChooserPanels();
202205 for ( AbstractColorChooserPanel a : accp ) {
203206 this.removeChooserPanel(a);
@@ -211,20 +214,20 @@ public class VWColorChooserDialog extends JEscCancelDialog {
211214 this.addChooserPanel(new customColorChooserPanel2());
212215 this.addChooserPanel(new customColorChooserPanel());
213216 }
214-
217+
215218 private class customColorChooserPanel extends AbstractColorChooserPanel implements MouseListener {
216-
219+
217220 private static final long serialVersionUID = 1L;
218-
221+
219222 JTable jTable = null;
220-
223+
221224 @Override
222225 protected void buildChooser() {
223226 if (jTable == null) {
224227 jTable = new JTable(8,8) {
225-
228+
226229 private static final long serialVersionUID = 1L;
227-
230+
228231 @Override
229232 public boolean isCellEditable(int row, int column) {
230233 return false;
@@ -237,26 +240,26 @@ public class VWColorChooserDialog extends JEscCancelDialog {
237240 add(jTable);
238241 }
239242 }
240-
243+
241244 @Override
242245 public String getDisplayName() {
243246 return "鯛ナビ";
244247 }
245-
248+
246249 @Override
247250 public Icon getLargeDisplayIcon() {
248251 return null;
249252 }
250-
253+
251254 @Override
252255 public Icon getSmallDisplayIcon() {
253256 return null;
254257 }
255-
258+
256259 @Override
257260 public void updateChooser() {
258261 }
259-
262+
260263 @Override
261264 public void mouseClicked(MouseEvent e) {
262265 Point p = e.getPoint();
@@ -265,69 +268,69 @@ public class VWColorChooserDialog extends JEscCancelDialog {
265268 Color c = getColorFromTable(row, column);
266269 jColorChooser.setColor(c);
267270 }
268-
271+
269272 @Override
270273 public void mouseEntered(MouseEvent e) {
271274 }
272-
275+
273276 @Override
274277 public void mouseExited(MouseEvent e) {
275278 }
276-
279+
277280 @Override
278281 public void mousePressed(MouseEvent e) {
279282 }
280-
283+
281284 @Override
282285 public void mouseReleased(MouseEvent e) {
283286 }
284287 }
285-
288+
286289 private class customColorChooserPanel2 extends AbstractColorChooserPanel {
287-
290+
288291 private static final long serialVersionUID = 1L;
289-
292+
290293 JColorChooseSlider jCCS_Red = null;
291294 JColorChooseSlider jCCS_Blue = null;
292295 JColorChooseSlider jCCS_Green = null;
293296 JCheckBox jCB_Hex = null;
294-
297+
295298 @Override
296299 protected void buildChooser() {
297300 if (jCCS_Red == null) {
298-
301+
299302 jCCS_Red = new JColorChooseSlider("赤") {
300-
303+
301304 private static final long serialVersionUID = 1L;
302-
305+
303306 @Override
304307 void evHandle(int n) {
305308 myEvHandle(n);
306309 }
307310 };
308-
311+
309312 jCCS_Green = new JColorChooseSlider("緑") {
310-
313+
311314 private static final long serialVersionUID = 1L;
312-
315+
313316 @Override
314317 void evHandle(int n) {
315318 myEvHandle(n);
316319 }
317320 };
318-
321+
319322 jCCS_Blue = new JColorChooseSlider("青") {
320-
323+
321324 private static final long serialVersionUID = 1L;
322-
325+
323326 @Override
324327 void evHandle(int n) {
325328 myEvHandle(n);
326329 }
327330 };
328-
331+
329332 jCB_Hex = new JCheckBox("16進数(00-ff)で入力", false);
330-
333+
331334 jCB_Hex.addActionListener(new ActionListener() {
332335 @Override
333336 public void actionPerformed(ActionEvent arg0) {
@@ -336,7 +339,7 @@ public class VWColorChooserDialog extends JEscCancelDialog {
336339 jCCS_Blue.setHex(jCB_Hex.isSelected());
337340 }
338341 });
339-
342+
340343 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
341344 add(jCCS_Red);
342345 add(Box.createRigidArea(new Dimension(10,10)));
@@ -347,22 +350,22 @@ public class VWColorChooserDialog extends JEscCancelDialog {
347350 add(jCB_Hex);
348351 }
349352 }
350-
353+
351354 @Override
352355 public String getDisplayName() {
353356 return "RGB";
354357 }
355-
358+
356359 @Override
357360 public Icon getLargeDisplayIcon() {
358361 return null;
359362 }
360-
363+
361364 @Override
362365 public Icon getSmallDisplayIcon() {
363366 return null;
364367 }
365-
368+
366369 @Override
367370 public void updateChooser() {
368371 if ( jColorChooser != null ) {
@@ -372,29 +375,29 @@ public class VWColorChooserDialog extends JEscCancelDialog {
372375 jCCS_Blue.setValue(c.getBlue());
373376 }
374377 }
375-
378+
376379 private void myEvHandle(int n) {
377380 jColorChooser.setColor(new Color(jCCS_Red.getValue(),jCCS_Green.getValue(),jCCS_Blue.getValue()));
378381 }
379382 }
380-
383+
381384 private class labelRenderer extends JLabel implements TableCellRenderer {
382385 private static final long serialVersionUID = 1L;
383-
386+
384387 @Override
385388 public Component getTableCellRendererComponent(JTable table,
386389 Object value, boolean isSelected, boolean hasFocus, int row, int column) {
387390 this.setOpaque(true);
388-
391+
389392 Color c = getColorFromTable(row,column);
390393 this.setBackground(c);
391-
394+
392395 this.setToolTipText("("+c.getRed()+","+c.getGreen()+","+c.getBlue()+")");
393-
396+
394397 return this;
395398 }
396399 }
397-
400+
398401 private Color getColorFromTable(int row, int column) {
399402 int b = ((int)(column / 4)+((int)(row / 4))*2) * 85;
400403 int g = (column % 4) * 85;
--- a/TinyBannavi/src/tainavi/VersionInfo.java
+++ b/TinyBannavi/src/tainavi/VersionInfo.java
@@ -5,7 +5,7 @@ import java.util.regex.Pattern;
55
66
77 public class VersionInfo {
8- private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.12.25";
8+ private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.13.0";
99
1010 private static final String OSname = System.getProperty("os.name");
1111 private static final String OSvers = System.getProperty("os.version");
--- a/TinyBannavi/src/tainavi/Viewer.java
+++ b/TinyBannavi/src/tainavi/Viewer.java
@@ -113,8 +113,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
113113 */
114114
115115 // 設定値をいれるところ
116- private final Env env = new Env(); // 主要な設定
117- private final Bounds bounds = new Bounds(); // ウィンドウサイズとか動的に変化するもの
116+ private final Env env = Env.TheEnv = new Env(); // 主要な設定
117+ private final Bounds bounds = new Bounds(); // ウィンドウサイズとか動的に変化するもの
118118 private final ClipboardInfoList cbitems = new ClipboardInfoList(); // クリップボード対応機能でどの項目をコピーするかとかの設定
119119 private final ListedColumnInfoList lvitems = new ListedColumnInfoList(); // リスト形式ビューの表示項目
120120 private final ReserveListColumnInfoList rlitems = new ReserveListColumnInfoList();
@@ -352,9 +352,9 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
352352 // 起動時に固定で用意しておくもの
353353 private final VWStatusWindow stwin = new VWStatusWindow();
354354 private final VWStatusTextArea mwin = new VWStatusTextArea();
355- private final VWColorChooserDialog ccwin = new VWColorChooserDialog();
355+ private VWColorChooserDialog ccwin = null;
356356 private VWPaperColorsDialog pcwin = null;
357- private final VWReserveDialog rdialog = new VWReserveDialog(0, 0);
357+ private VWReserveDialog rdialog = null;
358358
359359 // 初期化処理の中で生成していくもの
360360 private VWMainWindow mainWindow = null;
@@ -4886,7 +4886,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
48864886 // ほにゃらら
48874887 toolBar.setDebug(env.getDebug());
48884888 autores.setDebug(env.getDebug());
4889- rdialog.setDebug(env.getDebug());
4889+ if (rdialog != null)
4890+ rdialog.setDebug(env.getDebug());
48904891
48914892 // PassedProgramListの設定変更
48924893 tvprograms.getPassed().setPassedDir(env.getPassedDir());
@@ -5738,8 +5739,10 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
57385739 SwingUtilities.updateComponentTreeUI(this);
57395740 SwingUtilities.updateComponentTreeUI(stwin);
57405741 SwingUtilities.updateComponentTreeUI(mwin);
5741- SwingUtilities.updateComponentTreeUI(rdialog);
5742- SwingUtilities.updateComponentTreeUI(ccwin);
5742+ if (rdialog != null)
5743+ SwingUtilities.updateComponentTreeUI(rdialog);
5744+ if (ccwin != null)
5745+ SwingUtilities.updateComponentTreeUI(ccwin);
57435746 }
57445747 catch ( Exception e ) {
57455748 // 落ちられると困るからトラップしておこうぜ
@@ -5762,7 +5765,9 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
57625765
57635766 // コンポーネント作成
57645767 {
5768+ ccwin = new VWColorChooserDialog();
57655769 pcwin = new VWPaperColorsDialog();
5770+ rdialog = new VWReserveDialog(0, 0);
57665771
57675772 // メインウィンドウの作成
57685773 mainWindow = new VWMainWindow(this);
--- a/TinyBannavi/src/tainavi/pluginrec/PlugIn_RecDBR_M2008.java
+++ b/TinyBannavi/src/tainavi/pluginrec/PlugIn_RecDBR_M2008.java
@@ -1262,7 +1262,12 @@ public class PlugIn_RecDBR_M2008 extends HDDRecorderUtils implements HDDRecorder
12621262
12631263 // 枝番有(branchexists,branchnum)
12641264 branchnum = text2value(tvsBranch, channel);
1265- branchexists = Integer.parseInt(branchnum) > 0 ? BRANCH_YES : BRANCH_NO;
1265+ try{
1266+ branchexists = Integer.parseInt(branchnum) > 0 ? BRANCH_YES : BRANCH_NO;
1267+ }
1268+ catch(NumberFormatException e){
1269+ branchexists = BRANCH_NO;
1270+ }
12661271
12671272 // ネットワーク(network)
12681273 String typ = text2value(chtype, channel);
--- /dev/null
+++ b/TinyBannavi/src/tainavi/pluginrec/PlugIn_RecDBR_T1008.java
@@ -0,0 +1,2795 @@
1+package tainavi.pluginrec;
2+
3+import java.io.File;
4+import java.io.UnsupportedEncodingException;
5+import java.net.Authenticator;
6+import java.net.URLEncoder;
7+import java.text.ParseException;
8+import java.text.SimpleDateFormat;
9+import java.util.ArrayList;
10+import java.util.Comparator;
11+import java.util.Date;
12+import java.util.HashMap;
13+import java.util.Locale;
14+import java.util.regex.Matcher;
15+import java.util.regex.Pattern;
16+
17+import tainavi.AribCharMap;
18+import tainavi.ChannelCode;
19+import tainavi.ChapterInfo;
20+import tainavi.CommonUtils;
21+import tainavi.DeviceInfo;
22+import tainavi.GetRDStatus;
23+import tainavi.HDDRecorder;
24+import tainavi.HDDRecorderUtils;
25+import tainavi.ReserveList;
26+import tainavi.TVProgram.ProgGenre;
27+import tainavi.TextValueSet;
28+import tainavi.TitleInfo;
29+import tainavi.TraceProgram;
30+
31+/**
32+ * REGZA DBR-T1008用のレコーダプラグインです。
33+ * @author original:tmskmr
34+ * @version x.xx.xx
35+ */
36+public class PlugIn_RecDBR_T1008 extends HDDRecorderUtils implements HDDRecorder,Cloneable {
37+ public PlugIn_RecDBR_T1008() {
38+ super();
39+ this.setTunerNum(3);
40+ setSettingFixed();
41+ }
42+
43+ public PlugIn_RecDBR_T1008 clone() {
44+ return (PlugIn_RecDBR_T1008) super.clone();
45+ }
46+
47+ private static final String thisEncoding = "UTF-8";
48+
49+ /*******************************************************************************
50+ * 種族の特性
51+ ******************************************************************************/
52+
53+ // 種族の特性
54+ @Override
55+ public String getRecorderId() { return "REGZA DBR-T1008"; }
56+ @Override
57+ public RecType getType() { return RecType.RECORDER; }
58+
59+ // chvalueを使っていいよ
60+ @Override
61+ public boolean isChValueAvailable() { return true; }
62+ // CHコードは入力しなくていい
63+ @Override
64+ public boolean isChCodeNeeded() { return false; }
65+
66+ // 録画タイトルに対応している
67+ @Override
68+ public boolean isTitleListSupported() { return true; }
69+
70+ // 持ち出しに対応している
71+ @Override
72+ public boolean isPortableSupported() { return true; }
73+
74+ // フォルダー作成に対応している
75+ @Override
76+ public boolean isFolderCreationSupported() { return true; }
77+
78+ /*******************************************************************************
79+ * 予約ダイアログなどのテキストのオーバーライド
80+ ******************************************************************************/
81+
82+ @Override
83+ public String getChDatHelp() { return
84+ "「レコーダの放送局名」はネットdeナビの録画予約一覧で表示される「CH」の欄の値を設定してください。\n"+
85+ "予約一覧取得が正常に完了していれば設定候補がコンボボックスで選択できるようになります。"
86+ ;
87+ }
88+
89+ /*******************************************************************************
90+ * 定数
91+ ******************************************************************************/
92+
93+ protected final String MSGID = "["+getRecorderId()+"] ";
94+ protected final String ERRID = "[ERROR]"+MSGID;
95+ protected final String DBGID = "[DEBUG]"+MSGID;
96+
97+ protected final String NETWORK_UVD = "0";
98+ protected final String NETWORK_BSD = "1";
99+ protected final String NETWORK_CSD = "2";
100+ protected final String NETWORK_L1 = "3";
101+ protected final String NETWORK_L2 = "4";
102+ protected final String NETWORK_L3 = "5";
103+ protected final String NETWORK_L4 = "6";
104+ protected final String NETWORK_NET = "7";
105+
106+ protected final String CHTYPE_UVD = "uvd";
107+ protected final String CHTYPE_BSD = "bsd";
108+ protected final String CHTYPE_CSD = "csd";
109+ protected final String CHTYPE_L1 = "L1";
110+ protected final String CHTYPE_L2 = "L2";
111+ protected final String CHTYPE_L3 = "L3";
112+ protected final String CHTYPE_L4 = "L4";
113+ protected final String CHTYPE_NET = "NET";
114+
115+ protected final String CHPREFIX_BS = "BS";
116+ protected final String CHPREFIX_CS = "CS";
117+ protected final String CH_L1 = "L1";
118+ protected final String CH_L2 = "L2";
119+ protected final String CH_L3 = "L3";
120+ protected final String CH_L4 = "L4";
121+ protected final String CH_NET = "NET";
122+
123+ protected final String OPTION_DATETIME = "1";
124+ protected final String OPTION_PROGRAM = "2";
125+
126+ protected final String REPEAT_NONE = "0";
127+
128+ protected final int RPTPTN_ID_TUE2SAT = 12;
129+
130+ protected final String EXEC_YES = "1";
131+ protected final String EXEC_NO = "0";
132+
133+ protected final String BRANCH_NO = "0";
134+ protected final String BRANCH_YES = "1";
135+
136+ protected final String DEVICE_HDD = "0";
137+ protected final String DEVICE_DISC = "1";
138+ protected final String FOLDER_NONE = "0";
139+ protected final String FOLDER_NAME_NONE = "指定なし";
140+
141+ protected final String RECMODE_DR = "0";
142+ protected final String RECMODE_NAME_DR = "[DR]";
143+
144+ protected final String MOCHIDASHI_NONE = "0";
145+
146+ protected final String RESULT_OK = "0";
147+ protected final String RESULT_OTHER = "1";
148+ protected final String RESULT_BUSY = "2";
149+ protected final String RESULT_INVALID_TITLE = "17";
150+
151+ protected final String ERRMSG_NORESPONSE = "レコーダーが反応しません";
152+ protected final String ERRMSG_INVALIDRESPONSE = "レコーダーからの応答が不正です。";
153+ protected final String ERRMSG_USB_BUSY = "USB HDDが使用中です。";
154+
155+ protected final double MIN_PER_MB = 171.777;
156+
157+ protected final String TITLE_NOCHANGED = "__NETdeNAVI_TitleNameNotChanged__";
158+
159+ /*******************************************************************************
160+ * CHコード設定、エラーメッセージ
161+ ******************************************************************************/
162+
163+ public ChannelCode getChCode() {
164+ return cc;
165+ }
166+
167+ private ChannelCode cc = new ChannelCode(getRecorderId());
168+
169+ protected void setErrmsg(String s) { errmsg = s; }
170+
171+ public String getErrmsg() {
172+ return(errmsg.replaceAll("\\\\r\\\\n", ""));
173+ }
174+
175+ private String errmsg = "";
176+
177+ /*******************************************************************************
178+ * 部品
179+ ******************************************************************************/
180+
181+ private GetRDStatus gs = new GetRDStatus();
182+
183+ private String rsvedFile = "";
184+ private String folderTFile = "";
185+ private String titleFile = "";
186+ private String devinfoTFile = "";
187+ private ArrayList<TextValueSet> tvsBranch = new ArrayList<TextValueSet>();
188+ private ArrayList<TextValueSet> tvsPatternCode = new ArrayList<TextValueSet>();
189+ private ArrayList<TextValueSet> tvsPatternName = new ArrayList<TextValueSet>();
190+
191+ /*******************************************************************************
192+ * コンストラクタ
193+ ******************************************************************************/
194+
195+ /*******************************************************************************
196+ * チャンネルリモコン機能
197+ ******************************************************************************/
198+
199+ /*******************************************************************************
200+ * レコーダーから各種設定情報を取得する
201+ ******************************************************************************/
202+ @Override
203+ public boolean GetRdSettings(boolean force) {
204+
205+ System.out.println("レコーダの各種設定情報を取得します.");
206+
207+ String myFileId = getIPAddr()+"_"+getPortNo()+"_"+getRecorderId();
208+
209+ String deviceTFile = "env/device."+myFileId+".xml";
210+ devinfoTFile = "env/devinfo."+myFileId+".xml";
211+ folderTFile = "env/folders."+myFileId+".xml";
212+ String chValueTFile = "env/chvalue."+myFileId+".xml";
213+ String chTypeTFile = "env/chtype."+myFileId+".xml";
214+ String branchTFile = "env/branch."+myFileId+".xml";
215+
216+ // 固定の各種設定情報を初期化する
217+ setSettingFixed();
218+
219+ File f = new File(deviceTFile);
220+ if ( !force){
221+ if (!f.exists())
222+ return(false);
223+
224+ // キャッシュから読み出し(録画設定ほか)
225+ device = TVSload(deviceTFile);
226+ setDeviceInfos(DeviceInfosFromFile(devinfoTFile));
227+ folder = TVSload(folderTFile);
228+ chvalue = TVSload(chValueTFile);
229+ chtype = TVSload(chTypeTFile);
230+ tvsBranch = TVSload(branchTFile);
231+
232+ // なぜか設定ファイルが空になっている場合があるので、その際は再取得する
233+ if (device.size() > 0 && chvalue.size() > 0 && chtype.size() > 0 && tvsBranch.size() > 0) {
234+ return(true);
235+ }
236+ }
237+
238+ // 各種設定情報をレコーダから取得する
239+ if (!setSettingVariable()){
240+ return (false);
241+ }
242+
243+ TVSsave(device, deviceTFile);
244+ saveDeviceInfos();
245+ saveFolders();
246+ TVSsave(chvalue, chValueTFile);
247+ TVSsave(chtype, chTypeTFile);
248+ TVSsave(tvsBranch, branchTFile);
249+
250+ return(true);
251+ }
252+
253+ /*******************************************************************************
254+ * レコーダーから予約一覧を取得する
255+ ******************************************************************************/
256+
257+ public boolean GetRdReserve(boolean force)
258+ {
259+ System.out.println("レコーダから予約一覧を取得します("+force+"): "+getRecorderId()+"("+getIPAddr()+":"+getPortNo()+")");
260+
261+ errmsg = "";
262+
263+ //
264+ String myFileId = getIPAddr()+"_"+getPortNo()+"_"+getRecorderId();
265+
266+ rsvedFile = "env/reserved."+myFileId+".xml";
267+
268+ File f = new File(rsvedFile);
269+ if ( !force && f.exists()) {
270+ // キャッシュから読み出し(予約一覧)
271+ setReserves(ReservesFromFile(rsvedFile));
272+
273+ // なぜか設定ファイルが空になっている場合があるので、その際は再取得する
274+ if (getReserves().size() > 0) {
275+ return(true);
276+ }
277+ }
278+
279+ // 録画予約の一覧をレコーダから取得する
280+ ArrayList<ReserveList> ra = getReserveList();
281+ if (ra == null){
282+ return(false);
283+ }
284+
285+ setReserves(ra);
286+
287+ // キャッシュに保存
288+ ReservesToFile(getReserves(), rsvedFile);
289+
290+ // 取得した情報の表示
291+ if (getDebug()){
292+ System.out.println("---Reserved List Start---");
293+ for ( int i = 0; i<getReserves().size(); i++ ) {
294+ // 詳細情報の取得
295+ ReserveList e = getReserves().get(i);
296+ System.out.println(String.format("[%s] %s\t%s\t%s\t%s:%s\t%s:%s\t%sm\t%s\t%s(%s)\t%s\t%s",
297+ (i+1), e.getId(), e.getRec_pattern(), e.getRec_nextdate(), e.getAhh(), e.getAmm(), e.getZhh(), e.getZmm(), e.getRec_min(), e.getRec_mode(), e.getTitle(), e.getTitlePop(), e.getChannel(), e.getCh_name()));
298+ }
299+ System.out.println("---Reserved List End---");
300+ }
301+
302+ return(true);
303+ }
304+
305+ /*******************************************************************************
306+ * 予約詳細情報の取得
307+ ******************************************************************************/
308+ @Override
309+ public boolean isThereAdditionalDetails() {
310+ return true;
311+ }
312+
313+ /*
314+ * 予約の詳細情報を取得する
315+ */
316+ @Override
317+ public boolean GetRdReserveDetails(){
318+ int rno = 0;
319+ ArrayList<ReserveList> ra = getReserves();
320+ for (ReserveList entry : ra) {
321+
322+ reportProgress("+番組詳細を取得します("+rno+"/"+ra.size()+").");
323+ getReserveDetail(entry);
324+
325+ // 放送局名変換
326+ entry.setCh_name(getChCode().getCH_REC2WEB(entry.getChannel()));
327+
328+ // TS->DR
329+ translateAttributeTuner(entry);
330+
331+ // タイトル自動補完フラグなど本体からは取得できない情報を引き継ぐ
332+ copyAttributesT2007(entry, getReserves());
333+
334+ rno++;
335+ }
336+
337+ // キャッシュに保存
338+ ReservesToFile(getReserves(), rsvedFile);
339+
340+ return(true);
341+ }
342+
343+ /*******************************************************************************
344+ * 新規予約
345+ ******************************************************************************/
346+ @Override
347+ public boolean PostRdEntry(ReserveList r) {
348+ errmsg = "";
349+
350+ String chcode = cc.getCH_WEB2CODE(r.getCh_name());
351+ if (chcode == null) {
352+ errmsg = "【警告】Web番組表の放送局名「"+r.getCh_name()+"」をCHコードに変換できません。CHコード設定を修正してください。" ;
353+ System.out.println(errmsg);
354+ return(false);
355+ }
356+
357+ // RDから予約登録画面の初期情報を取り出す。これを呼ばないと ERR_EXCLUSIVEエラーになる
358+ if ( !loadDialogInitData("0")){
359+ return(false);
360+ }
361+
362+ // RDへの情報作成
363+ String pstr = createPostData(r, "");
364+
365+ // RDへ情報送信
366+ reportProgress(MSGID+"レコーダーに新規予約を要求します.");
367+ String [] d = reqPOST("http://"+getIPAddr()+":"+getPortNo()+"/torunavi/DoReserve.php", pstr, null, thisEncoding);
368+// String header = d[0];
369+ String response = d[1];
370+
371+ // 登録結果の確認
372+ if ( !checkReserveResponse(r, response) ){
373+ return(false);
374+ }
375+
376+ // 予約情報の調整
377+ adjustReserve(r);
378+
379+ // 予約リストを更新
380+ getReserves().add(r);
381+
382+ // キャッシュに保存
383+ ReservesToFile(getReserves(), rsvedFile);
384+
385+ reportProgress(MSGID+"正常に登録できました。");
386+
387+ return(true);
388+ }
389+
390+ /*******************************************************************************
391+ * 予約更新
392+ ******************************************************************************/
393+ @Override
394+ public boolean UpdateRdEntry(ReserveList o, ReserveList r) {
395+ errmsg = "";
396+
397+ String chcode = cc.getCH_WEB2CODE(r.getCh_name());
398+ if (chcode == null) {
399+ errmsg = "【警告】Web番組表の放送局名「"+r.getCh_name()+"」をCHコードに変換できません。CHコード設定を修正してください。" ;
400+ System.out.println(errmsg);
401+ return(false);
402+ }
403+
404+ String id = o.getId();
405+
406+ // RDから予約登録画面の初期情報を取り出す。これを呼ばないと ERR_EXCLUSIVEエラーになる
407+ if ( !loadDialogInitData(id) ){
408+ return(false);
409+ }
410+
411+ // RDへの情報作成
412+ String pstr = createPostData(r, id);
413+
414+ // RDへ情報送信
415+ reportProgress(MSGID+"レコーダーに予約更新を要求します.");
416+ String [] d = reqPOST("http://"+getIPAddr()+":"+getPortNo()+"/torunavi/DoReserve.php", pstr, null, thisEncoding);
417+// String header = d[0];
418+ String response = d[1];
419+
420+ // 登録結果の確認
421+ if ( !checkReserveResponse(r, response) ){
422+ return(false);
423+ }
424+
425+ // 予約情報の調整
426+ adjustReserve(r);
427+
428+ // 情報置き換え
429+ getReserves().remove(o);
430+ getReserves().add(r);
431+
432+ // キャッシュに保存
433+ ReservesToFile(getReserves(), rsvedFile);
434+
435+ reportProgress(MSGID+"正常に更新できました。");
436+
437+ return(true);
438+ }
439+
440+ /*******************************************************************************
441+ * 予約削除
442+ ******************************************************************************/
443+ @Override
444+ public ReserveList RemoveRdEntry(String delid) {
445+ errmsg = "";
446+
447+ // 削除対象を探す
448+ ReserveList r = null;
449+ for ( ReserveList reserve : getReserves() ) {
450+ if (reserve.getId().equals(delid)) {
451+ r = reserve;
452+ break;
453+ }
454+ }
455+ if (r == null) {
456+ return(null);
457+ }
458+
459+ // RDから予約登録画面の初期情報を取り出す。これを呼ばないと ERR_EXCLUSIVEエラーになる
460+ if ( !loadDialogInitData(delid)){
461+ return(null);
462+ }
463+
464+ // RDへの情報作成
465+ String pstr = createPostData(r, delid);
466+
467+ // RDへ情報送信
468+ reportProgress(MSGID+"レコーダーに予約削除を要求します.");
469+ String [] d = reqPOST("http://"+getIPAddr()+":"+getPortNo()+"/torunavi/DeleteReserve.php", pstr, null, thisEncoding);
470+// String header = d[0];
471+ String response = d[1];
472+
473+ if ( !checkGeneralResponse( "予約削除", response) ){
474+ return(null);
475+ }
476+
477+ // 予約リストを更新
478+ getReserves().remove(r);
479+
480+ // キャッシュに保存
481+ ReservesToFile(getReserves(), rsvedFile);
482+
483+ reportProgress(MSGID+"正常に削除できました。");
484+ System.out.printf("\n<<< Message from RD >>> \"%s\"\n\n", "正常に削除できました。");
485+ return(r);
486+ }
487+
488+ /*******************************************************************************
489+ * フォルダー作成
490+ ******************************************************************************/
491+ @Override
492+ public boolean CreateRdFolder(String device_id, String folder_name) {
493+ return setFolderName( device_id, null, folder_name );
494+ }
495+
496+ /*******************************************************************************
497+ * フォルダー名更新
498+ ******************************************************************************/
499+ @Override
500+ public boolean UpdateRdFolderName(String device_id, String folder_id, String folder_name) {
501+ return setFolderName( device_id, folder_id, folder_name );
502+ }
503+
504+ /*******************************************************************************
505+ * フォルダー削除
506+ ******************************************************************************/
507+ @Override
508+ public boolean RemoveRdFolder(String device_id, String fol_id) {
509+ errmsg = "";
510+
511+ String action = "フォルダ削除";
512+ String folder_id = extractFolderID(fol_id);
513+
514+ String pstr =
515+ "drive_id=" + device_id + "&" +
516+ "folder_id=" + folder_id;
517+
518+ for (int n=0; n<3; n++){
519+ // おまじない
520+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
521+
522+ // RDへ情報送信
523+ reportProgress(MSGID+"レコーダーに" + action + "を要求します.");
524+ String [] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/folderset/DeleteFolder.php?" + pstr, null, thisEncoding);
525+// String header = d[0];
526+ String response = d[1];
527+
528+ // レスポンスから処理結果を取得する
529+ String [] rc = getReasonFromResponse( response );
530+ if (rc == null) {
531+ errmsg = ERRID+ERRMSG_NORESPONSE;
532+ return(false);
533+ }
534+
535+ String result = rc[0];
536+ String reason = rc[1];
537+
538+ if (result.equals(RESULT_OK))
539+ break;
540+
541+ if (result.equals(RESULT_OTHER) || result.equals(RESULT_BUSY)){
542+ if (mountUsbDrive(device_id))
543+ continue;
544+ }
545+
546+ errmsg = ERRID+action+"に失敗しました。(result=" + result + ",reason=" + reason + ")";
547+ return(false);
548+ }
549+
550+ // フォルダ一覧を取得し直す
551+ setSettingFolders();
552+ saveFolders();
553+
554+ return true;
555+ }
556+
557+ /*******************************************************************************
558+ * タイトル一覧取得
559+ ******************************************************************************/
560+ @Override
561+ public boolean GetRdTitles(String device_id, boolean force, boolean detail, boolean mountedOnly) {
562+ System.out.println("レコーダからタイトル一覧を取得します("+force+"): "+getRecorderId()+"("+getIPAddr()+":"+getPortNo()+")");
563+
564+ errmsg = "";
565+
566+ DEVICE_ID = device_id;
567+
568+ String myFileId = getIPAddr()+"_"+getPortNo()+"_"+getRecorderId();
569+
570+ ArrayList<TitleInfo> list = new ArrayList<TitleInfo>();
571+
572+ for (DeviceInfo di : getDeviceInfos() ) {
573+ String devid = di.getId();
574+ if (devid.equals(DEVICE_ALL))
575+ continue;
576+ if (!device_id.equals(DEVICE_ALL) && !device_id.equals(devid))
577+ continue;
578+
579+ titleFile = "env/title."+myFileId+"." + devid + ".xml";
580+
581+ if (!force){
582+ File f = new File(titleFile);
583+ if (!f.exists())
584+ return(false);
585+
586+ // キャッシュから読み出し(タイトル一覧)
587+ ArrayList<TitleInfo> ta = TitlesFromFile(titleFile);
588+
589+ list.addAll(ta);
590+ }
591+ else{
592+ // タイトル一覧をレコーダから取得する
593+ ArrayList<TitleInfo> ta = getTitleList(devid, mountedOnly);
594+ if (ta == null){
595+ if (errmsg.length() > 0)
596+ return(false);
597+
598+ File f = new File(titleFile);
599+ // キャッシュから読み出し(タイトル一覧)
600+ if (f.exists())
601+ ta = TitlesFromFile(titleFile);
602+ }
603+ else{
604+ if (ta.isEmpty()){
605+ reportProgress("0件だったので念のため再度取得します...");
606+ ta = getTitleList(devid, mountedOnly);
607+ if (ta == null)
608+ return false;
609+ }
610+
611+ // タイトルの詳細情報を取得し、内容を調整する
612+ for (TitleInfo entry : ta) {
613+ // 放送局名変換
614+ entry.setCh_name(getChCode().getCH_REC2WEB(entry.getChannel()));
615+ }
616+
617+ if (detail){
618+ getTitleDetails(devid, ta, false);
619+ }
620+ }
621+
622+ list.addAll(ta);
623+ }
624+ }
625+
626+ setTitles(list);
627+
628+ // キャッシュに保存
629+ if (force){
630+ saveTitles(device_id);
631+
632+ // 取得した情報の表示
633+ if (getDebug()){
634+ System.out.println("---Title List Start---");
635+ for ( int i = 0; i<getTitles().size(); i++ ) {
636+ // 詳細情報の取得
637+ TitleInfo t = getTitles().get(i);
638+ System.out.println(String.format("[%s] %s\t%s\t%s:%s\t%s:%s\t%sm\t%s\t%s\t%s",
639+ (i+1), t.getId(), t.getRec_date(), t.getAhh(), t.getAmm(), t.getZhh(), t.getZmm(), t.getRec_min(),
640+ t.getTitle(), t.getChannel(), t.getCh_name()));
641+ }
642+ System.out.println("---Title List End---");
643+ }
644+
645+ // 各種設定情報をレコーダから取得する
646+ if (setSettingDevice()){
647+ saveDeviceInfos();
648+ }
649+ }
650+
651+ return(true);
652+ }
653+
654+ /*******************************************************************************
655+ * タイトル詳細情報取得
656+ ******************************************************************************/
657+ @Override
658+ public boolean GetRdTitleDetails(String devid, boolean force){
659+ errmsg = "";
660+
661+ ArrayList<TitleInfo> ta = getTitles();
662+
663+ getTitleDetails(devid, ta, force);
664+
665+ // キャッシュに保存
666+ saveTitles(devid);
667+
668+ return(true);
669+ }
670+
671+ /*
672+ * タイトル詳細情報を取得する
673+ */
674+ private boolean getTitleDetails(String devid, ArrayList<TitleInfo>ta, boolean force){
675+ int tno = 0;
676+
677+ for (TitleInfo ti : ta){
678+ tno++;
679+
680+ if (ti.getDetailLoaded() && !ti.getRecording() && !force)
681+ continue;
682+
683+ reportProgress("+タイトル詳細を取得します("+tno+"/"+ta.size()+").");
684+ getTitleDetail(ti);
685+ }
686+
687+ return(true);
688+ }
689+
690+ /*******************************************************************************
691+ * タイトル詳細情報取得
692+ ******************************************************************************/
693+ @Override
694+ public boolean GetRdTitleDetail(TitleInfo t) {
695+ errmsg = "";
696+
697+ if (t == null)
698+ return(false);
699+
700+ if (!getTitleDetail(t))
701+ return(false);
702+
703+ // キャッシュに保存
704+ saveTitles(t.getRec_device());
705+
706+ return(true);
707+ }
708+
709+ /*******************************************************************************
710+ * タイトル更新
711+ ******************************************************************************/
712+ @Override
713+ public boolean UpdateRdTitleInfo(String device_id, TitleInfo o, TitleInfo t) {
714+ errmsg = "";
715+
716+ if (t == null) {
717+ return(false);
718+ }
719+
720+ for (int n=0; n<3; n++){
721+ // タイトルの編集をレコーダに通知する
722+ notifyTitleEdit(device_id, t.getId());
723+
724+ // おまじない
725+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
726+
727+ // RDへの情報作成
728+ String pstr = createTitlePostData(t, o, device_id);
729+
730+ // RDへ情報送信
731+ reportProgress(MSGID+"レコーダーにタイトル更新を要求します:"+device_id);
732+ String [] d = reqPOST("http://"+getIPAddr()+":"+getPortNo()+"/titlelist/UpdateTitleInfo.php", pstr, null, thisEncoding);
733+// String header = d[0];
734+ String response = d[1];
735+
736+ // レスポンスから処理結果を取得する
737+ String [] rc = getReasonFromResponse( response );
738+ if (rc == null) {
739+ errmsg = ERRID+ERRMSG_NORESPONSE;
740+ return(false);
741+ }
742+
743+ String result = rc[0];
744+ String reason = rc[1];
745+
746+ if (result.equals(RESULT_OK))
747+ break;
748+
749+ if (result.equals(RESULT_OTHER)){
750+ if (mountUsbDrive(device_id))
751+ continue;
752+ }
753+
754+ errmsg = ERRID+"タイトル更新に失敗しました。(result=" + result + ",reason=" + reason + ")";
755+ return(false);
756+ }
757+
758+ // 録画タイトルリストを更新
759+ ArrayList<TitleInfo> list = getTitles();
760+ list.remove(o);
761+ list.add(t);
762+ list.sort(new TitleInfoComparator());
763+
764+ // キャッシュに保存
765+ saveTitles(t.getRec_device());
766+
767+ // 各種設定情報をレコーダから取得する
768+ if (setSettingDevice()){
769+ saveDeviceInfos();
770+ }
771+
772+ reportProgress(MSGID+"正常に更新できました。");
773+ System.out.printf("\n<<< Message from RD >>> \"%s\"\n\n", "正常に更新できました。");
774+
775+ return(true);
776+ }
777+
778+ /*******************************************************************************
779+ * タイトル削除
780+ ******************************************************************************/
781+ @Override
782+ public TitleInfo RemoveRdTitle(String device_id, String title_id) {
783+ errmsg = "";
784+
785+ // 削除対象を探す
786+ TitleInfo t = null;
787+ for ( TitleInfo ttl : getTitles() ) {
788+ if (ttl.getId().equals(title_id)) {
789+ t = ttl;
790+ break;
791+ }
792+ }
793+ if (t == null) {
794+ return(null);
795+ }
796+
797+ for (int n=0; n<3; n++){
798+ // おまじない
799+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
800+
801+ // RDへの情報作成
802+ String pstr = "drive_id=" + device_id + "&title_id=" + title_id;
803+
804+ // RDへ情報送信
805+ reportProgress(MSGID+"レコーダーにタイトル削除を要求します.");
806+ String [] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/titlelist/DeleteTitle.php?"+pstr, null, thisEncoding);
807+// String header = d[0];
808+ String response = d[1];
809+
810+ // レスポンスから処理結果を取得する
811+ String [] rc = getReasonFromResponse( response );
812+ if (rc == null) {
813+ errmsg = ERRID+ERRMSG_NORESPONSE;
814+ return(null);
815+ }
816+
817+ String result = rc[0];
818+ String reason = rc[1];
819+
820+ if (result.equals(RESULT_OK))
821+ break;
822+
823+ if (result.equals(RESULT_OTHER) || result.equals(RESULT_INVALID_TITLE)){
824+ if (mountUsbDrive(device_id))
825+ continue;
826+ }
827+
828+ errmsg = ERRID+"タイトル削除に失敗しました。(result=" + result + ",reason=" + reason + ")";
829+ return(null);
830+ }
831+
832+ // タイトルリストを更新
833+ getTitles().remove(t);
834+
835+ // キャッシュに保存
836+ saveTitles(t.getRec_device());
837+
838+ setSettingDevice();
839+ saveDeviceInfos();
840+
841+ reportProgress(MSGID+"正常に削除できました。");
842+ System.out.printf("\n<<< Message from RD >>> \"%s\"\n\n", "正常に削除できました。");
843+ return(t);
844+ }
845+
846+ /*******************************************************************************
847+ * タイトル再生の開始・終了
848+ ******************************************************************************/
849+ @Override
850+ public boolean StartStopPlayRdTitle(String device_id, String title_id, boolean start) {
851+ errmsg = "";
852+
853+ // RDへのURL
854+ String action = start ? "タイトル再生開始" : "タイトル再生終了";
855+ String url = start ? "/titlelist/PlayTitle.php" : "/titlelist/PlayStop.php";
856+
857+ // RDへの情報作成
858+ String pstr = "drive_id=" + device_id + "&title_id=" + title_id;
859+
860+ for (int n=0; n<3; n++){
861+ // おまじない
862+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
863+
864+ // RDへ情報送信
865+ reportProgress(MSGID+"レコーダーに" + action + "を要求します.");
866+ String [] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+url+ "?"+pstr, null, thisEncoding);
867+// String header = d[0];
868+ String response = d[1];
869+
870+ // レスポンスから処理結果を取得する
871+ String [] rc = getReasonFromResponse( response );
872+ if (rc == null) {
873+ errmsg = ERRID+ERRMSG_NORESPONSE;
874+ return(false);
875+ }
876+
877+ String result = rc[0];
878+ String reason = rc[1];
879+
880+ if (result.equals(RESULT_OK))
881+ break;
882+
883+ if (result.equals(RESULT_OTHER)){
884+ if (mountUsbDrive(device_id))
885+ continue;
886+ }
887+
888+ errmsg = ERRID+action+"に失敗しました。(result=" + result + ",reason=" + reason + ")";
889+ return(false);
890+ }
891+
892+ reportProgress(MSGID+"正常に" + action + "できました。");
893+
894+ return(true);
895+ }
896+
897+ /* ここまで */
898+
899+ /* 個別コード-ここから最後まで */
900+ /*******************************************************************************
901+ * 非公開メソッド
902+ ******************************************************************************/
903+ /*
904+ * 録画予約の一覧を取得する
905+ */
906+ protected ArrayList<ReserveList> getReserveList() {
907+ // おまじない
908+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
909+
910+ // RDから予約一覧を取り出す
911+ reportProgress(MSGID+"予約一覧を取得します.");
912+ String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/torunavi/LoadReserveList.php",null, thisEncoding);
913+// String header = d[0];
914+ String response= d[1];
915+
916+ if (response == null) {
917+ errmsg = ERRID+ERRMSG_NORESPONSE;
918+ return(null);
919+ }
920+
921+ // 先頭部分をチェックする
922+ Matcher mr = Pattern.compile("\\{\"NETdeNAVI\"").matcher(response);
923+ if ( ! mr.find()) {
924+ errmsg = ERRID+ERRMSG_INVALIDRESPONSE;
925+ return (null);
926+ }
927+
928+ ArrayList<ReserveList> list = new ArrayList<ReserveList>();
929+
930+ Matcher ma = Pattern.compile("\\{" +
931+ "\"num\":(\\d+)," + // 1
932+ "\"id\":(\\d+)," + // 2
933+ "\"exec\":(\\d+)," + // 3
934+ "\"option\":(\\d+)," + // 4
935+ "\"eventname\":\"([^\"]+)\"," + // 5
936+ "\"network\":(\\d+)," + // 6
937+ "\"ch\":\"([^\"]+)\"," + // 7
938+ "\"repeat\":(\\d+)," + // 8
939+ "\"datetime\":(\\d+)," + // 9
940+ "\"duration\":(\\d+)," + // 10
941+ "\"conflictstart\":(\\d+)," + // 11
942+ "\"conflictend\":(\\d+)," + // 12
943+ "\"recording\":(\\d+)," + // 13
944+ "\"last\":(\\d+)," + // 14
945+ "\"mochidashi\":(\\d+)\\}") // 15
946+ .matcher(response);
947+
948+ while ( ma.find() ) {
949+ // 個々のデータを取り出す
950+ ReserveList entry = new ReserveList();
951+
952+ String id = ma.group(2);
953+ String exec = ma.group(3);
954+ String option = ma.group(4);
955+ String eventname = ma.group(5);
956+ String network = ma.group(6);
957+ String ch = ma.group(7);
958+ String repeat = ma.group(8);
959+ String datetime = ma.group(9);
960+ String duration = ma.group(10);
961+
962+ // 予約ID
963+ entry.setId(id);
964+
965+ // 基本情報をセットする
966+ setReserveBasicInfo(entry, exec, option, eventname, network, ch, repeat, datetime, duration);
967+
968+ // 予約情報を保存
969+ list.add(entry.clone());
970+ }
971+
972+ return(list);
973+ }
974+
975+ /***
976+ * 予約の基本情報をセットする
977+ */
978+ protected void setReserveBasicInfo(ReserveList entry, String exec, String option, String eventname,
979+ String network, String ch, String repeat, String datetime, String duration){
980+ // 実行ON/OFF
981+ entry.setExec(exec.equals(EXEC_YES));
982+
983+ // オプション(1=日付指定, 2=PGM指定)
984+ entry.setRec_option(option);
985+
986+ // 開始日、終了日
987+ int nbsecs = Integer.parseInt(datetime); // 開始日時(UNIX時間/1000)
988+ int secs = Integer.parseInt(duration); // 録画時間(sec)
989+ int nesecs = nbsecs + secs; // 終了日時(UNIX時間/1000)
990+ Date bdate = new Date(nbsecs*1000L); // 開始日時(Date)
991+ Date edate = new Date(nesecs*1000L); // 終了日時(Date)
992+
993+ SimpleDateFormat sfd = new SimpleDateFormat("yyyy/MM/dd(E)", Locale.JAPAN);
994+ String pattern = sfd.format(bdate);
995+
996+ // 繰り返しパターン
997+ String pid = String.valueOf(RPTPTN_ID_BYDATE);
998+
999+ if (!repeat.equals(REPEAT_NONE)){
1000+ pattern = value2text(tvsPatternName, repeat);
1001+ pid = value2text(tvsPatternCode, repeat);
1002+ }
1003+
1004+ entry.setRec_pattern_id(Integer.parseInt(pid));
1005+ entry.setRec_pattern(pattern);
1006+
1007+ // 開始、終了時刻
1008+ SimpleDateFormat sfh = new SimpleDateFormat("HH");
1009+ SimpleDateFormat sfm = new SimpleDateFormat("mm");
1010+ String ahh = sfh.format(bdate);
1011+ String amm = sfm.format(bdate);
1012+ String zhh = sfh.format(edate);
1013+ String zmm = sfm.format(edate);
1014+ entry.setAhh(ahh);
1015+ entry.setAmm(amm);
1016+ entry.setZhh(zhh);
1017+ entry.setZmm(zmm);
1018+
1019+ // 次の録画日などを計算する
1020+ entry.setRec_nextdate(CommonUtils.getNextDate(entry));
1021+ entry.setRec_min(String.valueOf(secs/60));
1022+ getStartEndDateTime(entry);
1023+
1024+ // チューナーは固定
1025+ entry.setTuner("R1");
1026+
1027+ // 録画モードもとりあえず固定(後で詳細情報で上書きする)
1028+ entry.setRec_mode(RECMODE_NAME_DR);
1029+
1030+ // タイトル
1031+ String title = unescapeJavaString(eventname);
1032+ entry.setTitle(title);
1033+ entry.setTitlePop(TraceProgram.replacePop(title));
1034+
1035+ // チャンネル
1036+ switch(network){
1037+ case NETWORK_UVD:
1038+ break;
1039+ case NETWORK_BSD:
1040+ ch = CHPREFIX_BS + ch;
1041+ break;
1042+ case NETWORK_CSD:
1043+ ch = CHPREFIX_CS + ch;
1044+ break;
1045+ case NETWORK_L1:
1046+ ch = CH_L1;
1047+ break;
1048+ case NETWORK_L2:
1049+ ch = CH_L2;
1050+ break;
1051+ case NETWORK_L3:
1052+ ch = CH_L3;
1053+ break;
1054+ case NETWORK_L4:
1055+ ch = CH_L4;
1056+ break;
1057+ case NETWORK_NET:
1058+ ch = CH_NET;
1059+ break;
1060+ }
1061+
1062+ entry.setChannel(ch);
1063+
1064+ // 放送局名変換
1065+ entry.setCh_name(getChCode().getCH_REC2WEB(entry.getChannel()));
1066+ }
1067+
1068+ /*
1069+ * 予約詳細情報を取得する
1070+ */
1071+ protected boolean getReserveDetail( ReserveList r) {
1072+ // おまじない
1073+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
1074+
1075+ String id = r.getId();
1076+
1077+ String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/torunavi/LoadReserveDetailData.php?reserve_id=" + id, null, thisEncoding);
1078+// String header = d[0];
1079+ String response= d[1];
1080+
1081+ if (response == null) {
1082+ errmsg = ERRID+ERRMSG_NORESPONSE;
1083+ System.out.println(errmsg);
1084+ return(false);
1085+ }
1086+
1087+ Matcher ma = Pattern.compile("\\{" +
1088+ "\"id\":(\\d+)," + // 1
1089+ "\"exec\":(\\d+)," + // 2
1090+ "\"option\":(\\d+)," + // 3
1091+ "\"eventname\":\"([^\"]+)\"," + // 4
1092+ "\"network\":(\\d+)," + // 5
1093+ "\"chnum\":(\\d+)," + // 6
1094+ "\"branchexists\":(false|true)," + // 7
1095+ "\"branchnum\":(\\d+)," + // 8
1096+ "\"ch\":\"([^\"]+)\"," + // 9
1097+ "\"repeat\":(\\d+)," + // 10
1098+ "\"datetime\":(\\d+)," + // 11
1099+ "\"duration\":(\\d+)," + // 12
1100+ "\"conflictstart\":(\\d+)," + // 13
1101+ "\"conflictend\":(\\d+)," + // 14
1102+ "\"drive_id\":(\\d+)," + // 15
1103+ "\"folder_id\":(\\d+)," + // 16
1104+ "\"recmode\":(\\d+)," + // 17
1105+ "\"mochidashi\":(\\d+)," + // 18
1106+ "\"video_es\":(\\d+)," + // 19
1107+ "\"audio_es\":(\\d+)," + // 20
1108+ "\"data_es\":(\\d+)," + // 21
1109+ "\"recording\":(\\d+)\\}") // 22
1110+ .matcher(response);
1111+
1112+ if ( !ma.find() ) {
1113+ reportProgress(ERRID+"予約詳細情報が取得できません.ID=" + id);
1114+ return (false);
1115+ }
1116+
1117+ String exec = ma.group(2);
1118+ String option = ma.group(3);
1119+ String eventname = ma.group(4);
1120+ String network = ma.group(5);
1121+ // chnum
1122+ // branchexists
1123+ // branchnum
1124+ String ch = ma.group(9);
1125+ String repeat = ma.group(10);
1126+ String datetime = ma.group(11);
1127+ String duration = ma.group(12);
1128+ // conflictstart
1129+ // conflictend
1130+ String device_id = ma.group(15);
1131+ String folder_id = ma.group(16);
1132+ String recmode = ma.group(17);
1133+ String mochidashi = ma.group(18);
1134+ // video_es
1135+ // audio_es
1136+ // data_es
1137+ // recording
1138+
1139+ // 基本情報をセットする
1140+ String tuner = r.getTuner();
1141+ setReserveBasicInfo(r, exec, option, eventname, network, ch, repeat, datetime, duration);
1142+ // チューナはそのまま
1143+ r.setTuner(tuner);
1144+
1145+ // 保存先ドライブ
1146+ String device_name = value2text(device, device_id);
1147+ r.setRec_device(device_name);
1148+
1149+ // 保存先フォルダー
1150+ String folder_name = value2text(folder, device_id + ":" + folder_id);
1151+ r.setRec_folder(folder_name);
1152+
1153+ // 録画モード
1154+ String recmode_name = value2text(vrate, recmode);
1155+ r.setRec_mode(recmode_name);
1156+
1157+ // 持ち出し
1158+ String portable_name = value2text(portable, mochidashi);
1159+ r.setRec_portable(portable_name);
1160+
1161+ return(true);
1162+ }
1163+
1164+ /**
1165+ * レコーダーから取得できない情報は直接コピー(既存のリストから探して)
1166+ */
1167+ protected void copyAttributesT2007(ReserveList to, ArrayList<ReserveList> fromlist) {
1168+ ReserveList olde = null;
1169+ for ( ReserveList from : fromlist ) {
1170+ if ( from.getId() != null && from.getId().equals(to.getId()) ) {
1171+ copyAttributeT2007(to, olde = from);
1172+ break;
1173+ }
1174+ }
1175+
1176+ // DIGAの終了時間"未定"対応だけど、別にDIGAかどうか確認したりはしない。
1177+ setAttributesDiga(to,olde);
1178+ }
1179+
1180+ /**
1181+ * レコーダーから取得できない情報は直接コピー(既存エントリから直に)
1182+ */
1183+ protected void copyAttributeT2007(ReserveList to, ReserveList from) {
1184+ // 鯛ナビの内部フラグ
1185+ to.setAutocomplete(from.getAutocomplete());
1186+
1187+ // 予約一覧からは取得できない情報
1188+ to.setDetail(from.getDetail());
1189+ to.setRec_genre(from.getRec_genre());
1190+ to.setRec_autodel(from.getRec_autodel());
1191+
1192+ // BZ700以降の取得一覧から取得できない画質の対応
1193+ if (to.getRec_mode().equals("")) {
1194+ to.setRec_mode(from.getRec_mode());
1195+ }
1196+ }
1197+
1198+ //
1199+ protected void translateAttributeTuner(ReserveList entry) {
1200+ if (entry.getTuner().startsWith("TS")) {
1201+ entry.setTuner(entry.getTuner().replaceFirst("^TS", "DR"));
1202+ }
1203+ }
1204+
1205+ /*
1206+ * 登録/削除要求のPOSTデータを生成する
1207+ */
1208+ protected String createPostData(ReserveList r, String idBefore) {
1209+
1210+ String id = idBefore;
1211+ String exec = EXEC_YES;
1212+ String option = OPTION_PROGRAM;
1213+ String eventname = "";
1214+ String network = NETWORK_UVD;
1215+ String chnum = "0";
1216+ String branchexists = BRANCH_NO;
1217+ String branchnum = "0";
1218+ String ch = "";
1219+ String repeat = REPEAT_NONE;
1220+ String datetime = "";
1221+ String duration = "";
1222+ String conflictstart = "0";
1223+ String conflictend = "0";
1224+ String drive_id = DEVICE_HDD;
1225+ String folder_id = FOLDER_NONE;
1226+ String recmode = RECMODE_DR;
1227+ String mochidashi = MOCHIDASHI_NONE;
1228+ String video_es = "0";
1229+ String audio_es = "0";
1230+ String data_es = "0";
1231+ String recording = "0";
1232+
1233+ boolean bUpdate = !idBefore.equals("");
1234+
1235+ // スキップ
1236+ if (!r.getExec())
1237+ exec = EXEC_NO;
1238+
1239+ // オプション
1240+ if (bUpdate)
1241+ option = r.getRec_option();
1242+
1243+ // タイトル(eventname)
1244+ try {
1245+ if (!r.getAutocomplete())
1246+ eventname = URLEncoder.encode(CommonUtils.substringrb(r.getTitle(),80), thisEncoding);
1247+ } catch (UnsupportedEncodingException e) {
1248+ // TODO Auto-generated catch block
1249+ e.printStackTrace();
1250+ }
1251+
1252+ // チャンネル(ch)
1253+ String channel = cc.getCH_WEB2CODE(r.getCh_name());
1254+ ch = cc.getCH_CODE2REC(channel);
1255+
1256+ // 枝番有(branchexists,branchnum)
1257+ branchnum = text2value(tvsBranch, channel);
1258+ try{
1259+ branchexists = Integer.parseInt(branchnum) > 0 ? BRANCH_YES : BRANCH_NO;
1260+ }
1261+ catch(NumberFormatException e){
1262+ branchnum = "0";
1263+ }
1264+
1265+ // ネットワーク(network)
1266+ String typ = text2value(chtype, channel);
1267+ switch(typ){
1268+ case CHTYPE_UVD:
1269+ network = NETWORK_UVD; // 地上デジタル
1270+ break;
1271+ case CHTYPE_BSD:
1272+ network = NETWORK_BSD; // BSデジタル
1273+ ch = ch.substring(CHPREFIX_BS.length());
1274+ break;
1275+ case CHTYPE_CSD:
1276+ network = NETWORK_CSD; // 110度CSデジタル
1277+ ch = ch.substring(CHPREFIX_CS.length());
1278+ break;
1279+ case CHTYPE_L1:
1280+ network = NETWORK_L1; // 外部入力(L1)
1281+ break;
1282+ case CHTYPE_L2:
1283+ network = NETWORK_L2; // 外部入力(L2)
1284+ break;
1285+ case CHTYPE_L3:
1286+ network = NETWORK_L3; // 外部入力(L3)
1287+ break;
1288+ case CHTYPE_L4:
1289+ network = NETWORK_L4; // 外部入力(L4)
1290+ break;
1291+ case CHTYPE_NET:
1292+ network = NETWORK_NET; // 外部入力(NET)
1293+ break;
1294+ default:
1295+ // 普通ここには落ちない
1296+ if (ch.startsWith("C")) {
1297+ network = NETWORK_L1; // "C***"は外部入力(L1)
1298+ }
1299+ else if (ch.startsWith("SP")) {
1300+ network = NETWORK_L3; // "SP***"は外部入力(L3)
1301+ }
1302+ else {
1303+ network = NETWORK_L2; // 未定義は全部外部入力(L2)
1304+ }
1305+ break;
1306+ }
1307+
1308+ chnum = ch;
1309+
1310+ // 繰り返しパターン(repeat)
1311+ String pattern = r.getRec_pattern();
1312+ repeat = text2value(tvsPatternName, pattern);
1313+ if (repeat.equals(""))
1314+ repeat = REPEAT_NONE; // 繰り返しなし
1315+
1316+ // 開始日時(datetime)
1317+ if (!repeat.equals(REPEAT_NONE)){
1318+ String pid = value2text(tvsPatternCode, repeat);
1319+ r.setRec_pattern_id(Integer.parseInt(pid));
1320+
1321+ pattern = CommonUtils.getNextDate(r);
1322+ }
1323+
1324+ Matcher ma = Pattern.compile("^(\\d+)/(\\d+)/(\\d+)").matcher(pattern);
1325+ if (ma.find()){
1326+ String startDateTime = String.format("%04d%02d%02d %02d:%02d:00",
1327+ Integer.parseInt(ma.group(1)),
1328+ Integer.parseInt(ma.group(2)),
1329+ Integer.parseInt(ma.group(3)),
1330+ Integer.parseInt(r.getAhh()),
1331+ Integer.parseInt(r.getAmm()));
1332+
1333+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
1334+
1335+ // Date型に変換する
1336+ Date date = new Date();
1337+ try {
1338+ date = sdf.parse(startDateTime);
1339+ } catch (ParseException e) {
1340+ // TODO 自動生成された catch ブロック
1341+ e.printStackTrace();
1342+ }
1343+
1344+ // UNIX時刻/1000を取得する(単位秒)
1345+ datetime = String.valueOf(date.getTime()/1000);
1346+ }
1347+
1348+ // 録画時間(duration)(単位秒)
1349+ String min = CommonUtils.getRecMin(r.getAhh(),r.getAmm(),r.getZhh(),r.getZmm());
1350+ duration = String.valueOf(Integer.parseInt(min)*60);
1351+
1352+ // ドライブ(drive_id)/フォルダ(folder_id)
1353+ drive_id = text2value(device, r.getRec_device());
1354+ String s = text2value(folder, r.getRec_folder());
1355+
1356+ // <drive_id>:<folder_id> から<folder_id>を取り出す。ただし「指定なし」は"0"
1357+ int idx = s.indexOf(':');
1358+ if (idx != -1)
1359+ folder_id = s.substring(idx+1);
1360+
1361+ // 録画モード(recmode)
1362+ recmode = text2value(vrate, r.getRec_mode());
1363+
1364+ // 持ち出し
1365+ mochidashi = text2value(portable, r.getRec_portable());
1366+
1367+ String postData =
1368+ "reserveInfo[id]=" + id + "&" +
1369+ "reserveInfo[exec]=" + exec + "&" +
1370+ "reserveInfo[option]=" + option + "&" +
1371+ "reserveInfo[eventname]=" + eventname + "&" +
1372+ "reserveInfo[network]=" + network + "&" +
1373+ "reserveInfo[chnum]=" + chnum + "&" +
1374+ "reserveInfo[branchnum]=" + branchnum + "&" +
1375+ "reserveInfo[branchexists]=" + branchexists + "&" +
1376+ "reserveInfo[ch]=" + ch + "&" +
1377+ "reserveInfo[repeat]=" + repeat + "&" +
1378+ "reserveInfo[datetime]=" + datetime + "&" +
1379+ "reserveInfo[duration]=" + duration + "&" +
1380+ "reserveInfo[conflictstart]=" + conflictstart + "&" +
1381+ "reserveInfo[conflictend]=" + conflictend + "&" +
1382+ "reserveInfo[drive_id]=" + drive_id + "&" +
1383+ "reserveInfo[folder_id]=" + folder_id + "&" +
1384+ "reserveInfo[recmode]=" + recmode + "&" +
1385+ "reserveInfo[mochidashi]=" + mochidashi + "&" +
1386+ "reserveInfo[video_es]=" + video_es + "&" +
1387+ "reserveInfo[audio_es]=" + audio_es + "&" +
1388+ "reserveInfo[data_es]=" + data_es + "&" +
1389+ "reserveInfo[recording]=" + recording;
1390+
1391+ if (getDebug())
1392+ System.out.println("PostData=[" + postData + "]");
1393+
1394+ return postData;
1395+ }
1396+
1397+ /*
1398+ * 予約登録画面の初期化情報を取得する。これを呼ばないと、後で登録要求した時にERR_EXCLUSIVEエラーになる
1399+ */
1400+ protected boolean loadDialogInitData( String id) {
1401+ // おまじない
1402+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
1403+
1404+ reportProgress(MSGID+"予約登録画面を初期化します.");
1405+ String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/torunavi/LoadDialogInitializationData.php?schId=" + id, null, thisEncoding);
1406+// String header = d[0];
1407+ String response= d[1];
1408+
1409+ if (response == null) {
1410+ errmsg = ERRID+ERRMSG_NORESPONSE;
1411+ System.out.println(errmsg);
1412+ return(false);
1413+ }
1414+
1415+ return(true);
1416+ }
1417+
1418+ /*
1419+ * 登録要求の応答をチェックする
1420+ */
1421+ protected boolean checkReserveResponse( ReserveList r, String response ) {
1422+ if (response == null) {
1423+ errmsg = ERRID+ERRMSG_NORESPONSE;
1424+ return(false);
1425+ }
1426+
1427+ // {"result":24,"reason":"ERR_EXCLUSIVE","schid":"0"}
1428+ Matcher ma = Pattern.compile("\\{" +
1429+ "\"result\":(\\d+)," +
1430+ "\"reason\":\"([^\"]*)\"," +
1431+ "\"schid\":\"(\\d+)\"\\}").matcher(response);
1432+
1433+ if ( ma.find() ) {
1434+ String result = ma.group(1);
1435+ String reason = ma.group(2);
1436+ String schid = ma.group(3);
1437+
1438+ switch(result){
1439+ case RESULT_OK:
1440+ break;
1441+ case "3":
1442+ reportProgress("3:番組が見つからなかったため、日時指定予約として登録しました。");
1443+ break;
1444+ case "4":
1445+ reportProgress("4:予約が重複しています。");
1446+ break;
1447+ case "5":
1448+ reportProgress("5:持ち出し変換の上限を超えているため、持ち出し設定を「なし」として登録しました。");
1449+ break;
1450+ case "6":
1451+ reportProgress("6:持ち出し変換の上限を超えているため、持ち出し設定を「なし」として登録しました。");
1452+ break;
1453+ case "7":
1454+ reportProgress("7:番組が見つからなかったため、日時指定予約として登録しました。");
1455+ break;
1456+ case "8":
1457+ reportProgress("8:番組が見つからなかったため、日時指定予約として登録しました。\n" +
1458+ "持ち出し変換の上限を超えているため、持ち出し設定を「なし」として登録しました。");
1459+ break;
1460+ case "9":
1461+ reportProgress("9:番組が見つからなかったため、日時指定予約として登録しました。\n" +
1462+ "持ち出し変換の上限を超えているため、持ち出し設定を「なし」として登録しました。");
1463+ break;
1464+ default:
1465+ errmsg = ERRID+"予約登録に失敗しました。(result=" + result + ",reason=" + reason + ")";
1466+ reportProgress(errmsg);
1467+ return(false);
1468+ }
1469+
1470+ if (! schid.equals("0")){
1471+ r.setId(schid);
1472+ reportProgress(MSGID+"予約IDは"+r.getId()+"です。");
1473+ }
1474+
1475+ if (!result.equals(RESULT_OK))
1476+ getReserveDetail(r);
1477+ }
1478+ else{
1479+ errmsg = ERRID+ERRMSG_INVALIDRESPONSE;
1480+ reportProgress(errmsg);
1481+ return(false);
1482+ }
1483+
1484+ return(true);
1485+ }
1486+
1487+ /*
1488+ * 予約内容を調整する
1489+ */
1490+ protected void adjustReserve(ReserveList r) {
1491+ // 予約パターンID
1492+ r.setRec_pattern_id(getRec_pattern_Id(r.getRec_pattern()));
1493+
1494+ // 次回予定日
1495+ r.setRec_nextdate(CommonUtils.getNextDate(r));
1496+
1497+ // 録画長
1498+ r.setRec_min(CommonUtils.getRecMin(r.getAhh(),r.getAmm(),r.getZhh(),r.getZmm()));
1499+
1500+ // 開始日時・終了日時
1501+ getStartEndDateTime(r);
1502+ }
1503+
1504+ /*
1505+ * フォルダの作成ないしフォルダ名称を変更する
1506+ */
1507+ protected boolean setFolderName(String device_id, String fol_id, String folder_name) {
1508+ String action = fol_id != null ? "フォルダ名更新" : "フォルダ作成";
1509+ String folder_id = extractFolderID(fol_id);
1510+
1511+ String fnameEnc = "";
1512+ try {
1513+ fnameEnc = URLEncoder.encode(CommonUtils.substringrb(folder_name,80), thisEncoding);
1514+ } catch (UnsupportedEncodingException e) {
1515+ // TODO 自動生成された catch ブロック
1516+ e.printStackTrace();
1517+ }
1518+
1519+ String pstr =
1520+ "drive_id=" + device_id + "&" +
1521+ "folder_id=" + (folder_id != null ? folder_id : "NEWFOLDER") + "&" +
1522+ "folder_name=" + fnameEnc;
1523+
1524+ for (int n=0; n<3; n++){
1525+ // おまじない
1526+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
1527+
1528+ // RDへ情報送信
1529+ reportProgress(MSGID+"レコーダーに" + action + "を要求します.");
1530+ String [] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/folderset/SetFolderName.php?" + pstr, null, thisEncoding);
1531+// String header = d[0];
1532+ String response = d[1];
1533+
1534+ // レスポンスから処理結果を取得する
1535+ String [] rc = getReasonFromResponse( response );
1536+ if (rc == null) {
1537+ errmsg = ERRID+ERRMSG_NORESPONSE;
1538+ return(false);
1539+ }
1540+
1541+ String result = rc[0];
1542+ String reason = rc[1];
1543+
1544+ if (result.equals(RESULT_OK))
1545+ break;
1546+
1547+ if (result.equals(RESULT_OTHER) || result.equals(RESULT_BUSY)){
1548+ if (mountUsbDrive(device_id))
1549+ continue;
1550+ }
1551+
1552+ errmsg = ERRID+action+"に失敗しました。(result=" + result + ",reason=" + reason + ")";
1553+ return(false);
1554+ }
1555+
1556+ // フォルダ一覧を取得し直す
1557+ setSettingFolders();
1558+ saveFolders();
1559+
1560+ // タイトルに含まれるフォルダ名を更新する
1561+ updateFolderNameOfTitles();
1562+
1563+ return (true);
1564+ }
1565+
1566+ /*
1567+ * タイトルに含まれるフォルダ名を更新する
1568+ */
1569+ protected void updateFolderNameOfTitles(){
1570+ ArrayList<TitleInfo> list = getTitles();
1571+
1572+ for (TitleInfo ti : list){
1573+ ArrayList<TextValueSet> ts = ti.getRec_folder();
1574+
1575+ for (TextValueSet t : ts){
1576+ t.setText(value2text(folder, t.getValue()));
1577+ }
1578+
1579+ ti.setRec_folder(ts);
1580+ }
1581+
1582+ setTitles(list);
1583+
1584+ saveTitles(DEVICE_ID);
1585+ }
1586+ /*
1587+ * USB-HDDをマウントする
1588+ */
1589+ protected boolean mountUsbDrive(String device_id) {
1590+ reportProgress(MSGID+"ドライブをマウントします:"+device_id);
1591+
1592+ String pstr = "drive_id=" + device_id;
1593+
1594+ // おまじない
1595+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
1596+
1597+ // RDへ情報送信
1598+ String [] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/titlelist/ChangeMountedUSB.php?" + pstr, null, thisEncoding);
1599+// String header = d[0];
1600+ String response = d[1];
1601+
1602+ // 結果の確認
1603+ if ( !checkGeneralResponse( "USB HDDのマウント", response) ){
1604+ return(false);
1605+ }
1606+
1607+ return true;
1608+ }
1609+
1610+ /*
1611+ * 一般的な応答をチェックする
1612+ */
1613+ protected boolean checkGeneralResponse( String action, String response){
1614+ String [] rc = getReasonFromResponse( response );
1615+
1616+ if (rc == null) {
1617+ errmsg = ERRID+ERRMSG_NORESPONSE;
1618+ return(false);
1619+ }
1620+
1621+ String result = rc[0];
1622+ String reason = rc[1];
1623+
1624+ if (! result.equals(RESULT_OK)){
1625+ errmsg = action + "に失敗しました。(result=" + result + ",reason=" + reason + ")";
1626+ reportProgress(errmsg);
1627+ return(false);
1628+ }
1629+
1630+ return(true);
1631+ }
1632+
1633+ /*
1634+ * 応答メッセージから結果を取得する
1635+ */
1636+ protected String[] getReasonFromResponse( String response){
1637+ if (response == null) {
1638+ return(null);
1639+ }
1640+
1641+ // 先頭部分をチェックする
1642+ Matcher mh = Pattern.compile("\\{\"NETdeNAVI\"").matcher(response);
1643+ if ( ! mh.find()) {
1644+ return (null);
1645+ }
1646+
1647+ // 応答メッセージをパースする
1648+ // {"result":24,"reason":"ERR_EXCLUSIVE"}
1649+ Matcher ma = Pattern.compile("\\{" +
1650+ "\"result\":(\\d+)," +
1651+ "\"reason\":\"([^\"]*)\"\\}").matcher(response);
1652+ if ( !ma.find() )
1653+ return(null);
1654+
1655+ String [] rc = new String[2];
1656+
1657+ rc[0] = ma.group(1);
1658+ rc[1] = ma.group(2);
1659+
1660+ return(rc);
1661+ }
1662+
1663+ /*
1664+ * TitleInfoを startDateTime, cotent_id順にソートする
1665+ *
1666+ */
1667+ public class TitleInfoComparator implements Comparator<TitleInfo>{
1668+
1669+ @Override
1670+ public int compare(TitleInfo p1, TitleInfo p2) {
1671+ int rc = p1.getStartDateTime().compareTo(p2.getStartDateTime());
1672+ if (rc != 0){
1673+ return rc;
1674+ }
1675+
1676+ return p1.getSerial() - p2.getSerial();
1677+ }
1678+ }
1679+ /*
1680+ * タイトル一覧を取得する
1681+ */
1682+ protected ArrayList<TitleInfo> getTitleList(String device_id, boolean mountedOnly) {
1683+ String str = "drive=" + device_id + "&org_pl=0";
1684+
1685+ String response = "";
1686+
1687+ for (int n=0; n<3; n++){
1688+ // おまじない
1689+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
1690+
1691+ // RDからタイトル一覧を取り出す
1692+ reportProgress(MSGID+"タイトル一覧を取得します:"+device_id);
1693+ String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/titlelist/LoadTitleList.php?" + str, null, thisEncoding);
1694+// String header = d[0];
1695+ response= d[1];
1696+
1697+ if (response == null) {
1698+ errmsg = ERRID+ERRMSG_NORESPONSE;
1699+ return(null);
1700+ }
1701+
1702+ // 先頭部分をチェックする
1703+ Matcher mh = Pattern.compile("\\{\"NETdeNAVI\"").matcher(response);
1704+ if ( ! mh.find()) {
1705+ errmsg = ERRID+ERRMSG_INVALIDRESPONSE;
1706+ return(null);
1707+ }
1708+
1709+ // 応答メッセージをパースする
1710+ // {"result":24,"reason":"ERR_EXCLUSIVE"}
1711+ Matcher mr = Pattern.compile("\\{" +
1712+ "\"result\":(\\d+)," +
1713+ "\"reason\":\"([^\"]*)\"\\}").matcher(response);
1714+
1715+ if ( !mr.find() )
1716+ break;
1717+
1718+ String result = mr.group(1);
1719+ String reason = mr.group(2);
1720+
1721+ if (result.equals("1")){
1722+ if (mountedOnly){
1723+ reportProgress(MSGID+"ドライブがマウントされていないので取得を中止します:"+device_id);
1724+ return(null);
1725+ }
1726+
1727+ if (mountUsbDrive(device_id))
1728+ continue;
1729+
1730+ return(null);
1731+ }
1732+
1733+ errmsg = "録画タイトルの取得に失敗しました。(result=" + result + ",reason=" + reason + ")";
1734+ reportProgress(errmsg);
1735+ return(null);
1736+ }
1737+
1738+ ArrayList<TitleInfo> list = new ArrayList<TitleInfo>();
1739+
1740+ // {"num":4,"id":"51a6a4900016","titlename":"[映][SS]スティーヴン・キング 骨の袋[前編]",
1741+ // "folders":[{"folder_id":9}],"genres":[{"genrecode":15}],"ch":"BS201",
1742+ // "datetime":1369843200,"duration":4858,"newflag":true,"autorecflag":false},
1743+ Matcher ma = Pattern.compile("\\{" +
1744+ "\"num\":(\\d+)," + // 1
1745+ "\"id\":\"([^\"]+)\"," + // 2
1746+ "\"titlename\":\"([^\"]+)\"," + // 3
1747+ "\"folders\":\\[([^\\]]*)\\]," + // 4
1748+ "\"genres\":\\[([^\\]]*)\\]," + // 5
1749+ "\"network\":(\\d+)," + // 6
1750+ "\"ch\":\"([^\"]+)\"," + // 7
1751+ "\"datetime\":(\\d+)," + // 8
1752+ "\"duration\":(\\d+)," + // 9
1753+ "\"newflag\":(false|true)," + // 10
1754+ "\"autorecflag\":(false|true)," + // 11
1755+ "\"autodelflag\":(false|true)," + // 12
1756+ "\"protection\":(false|true)," + // 13
1757+ "\"mochidashiState\":(\\d+)," + // 14
1758+ "\"recmode\":(\\d+)," + // 15
1759+ "\"recording\":(false|true)\\}") // 16
1760+ .matcher(response);
1761+
1762+ int serial = 0;
1763+
1764+ while ( ma.find() ) {
1765+ // 個々のデータを取り出す
1766+ TitleInfo entry = new TitleInfo();
1767+
1768+ String id = ma.group(2);
1769+ String titlename = unescapeJavaString(ma.group(3));
1770+ String folders = ma.group(4);
1771+ String genres = ma.group(5);
1772+ String network = ma.group(6);
1773+ String ch = ma.group(7);
1774+ String datetime = ma.group(8);
1775+ String duration = ma.group(9);
1776+ String newflag = ma.group(10);
1777+ boolean autorecflag = ma.group(11).equals("true");
1778+ boolean autodelflag = ma.group(12).equals("true");
1779+ boolean protection = ma.group(13).equals("true");
1780+ String mochidashiState = ma.group(14);
1781+ String recmode = ma.group(15);
1782+ boolean recording = ma.group(16).equals("true");
1783+
1784+ // タイトルID
1785+ entry.setId(id);
1786+
1787+ // すでに同じIDのタイトルがある場合はその情報を引き継ぐ
1788+ TitleInfo tiOld = getTitleInfo(id);
1789+ if (tiOld != null)
1790+ entry = tiOld.clone();
1791+
1792+ // 基本情報をセットする
1793+ entry.setSerial(++serial);
1794+ setTitleBasicInfo(entry, titlename, network, ch, datetime, duration, device_id, folders, genres);
1795+
1796+ // 予約情報を保存
1797+ list.add(entry.clone());
1798+ }
1799+
1800+ list.sort(new TitleInfoComparator());
1801+
1802+ return(list);
1803+ }
1804+
1805+ /***
1806+ * タイトルの基本情報をセットする
1807+ */
1808+ protected void setTitleBasicInfo(TitleInfo entry, String titlename, String network,
1809+ String ch, String datetime, String duration, String device_id, String folders, String genres){
1810+
1811+ // 開始日、終了日
1812+ int nbsecs = Integer.parseInt(datetime); // 開始日時(UNIX時間/1000)
1813+ int secs = Integer.parseInt(duration); // 録画時間(sec)
1814+ int nesecs = nbsecs + secs; // 終了日時(UNIX時間/1000)
1815+ Date bdate = new Date(nbsecs*1000L); // 開始日時(Date)
1816+ Date edate = new Date(nesecs*1000L); // 終了日時(Date)
1817+
1818+ SimpleDateFormat sfdm = new SimpleDateFormat("yyyy/MM/dd HH:mm", Locale.JAPAN);
1819+ entry.setStartDateTime(sfdm.format(bdate));
1820+ entry.setEndDateTime(sfdm.format(edate));
1821+
1822+ // 開始、終了時刻
1823+ SimpleDateFormat sfh = new SimpleDateFormat("HH");
1824+ SimpleDateFormat sfm = new SimpleDateFormat("mm");
1825+ String ahh = sfh.format(bdate);
1826+ String amm = sfm.format(bdate);
1827+ String zhh = sfh.format(edate);
1828+ String zmm = sfm.format(edate);
1829+ entry.setAhh(ahh);
1830+ entry.setAmm(amm);
1831+ entry.setZhh(zhh);
1832+ entry.setZmm(zmm);
1833+
1834+
1835+ // 次の録画日などを計算する
1836+ SimpleDateFormat sfd = new SimpleDateFormat("yyyy/MM/dd(E)", Locale.JAPAN);
1837+ entry.setRec_date(sfd.format(bdate));
1838+ entry.setRec_min(String.valueOf(secs/60));
1839+
1840+ // タイトル
1841+ entry.setTitle(titlename);
1842+
1843+ // チャンネル
1844+ entry.setChannel(ch);
1845+
1846+ // デバイス
1847+ String device_name = value2text(device, device_id);
1848+ entry.setRec_device(device_name);
1849+
1850+ // フォルダー
1851+ entry.setRec_folder(parseFolders(device_id, folders));
1852+
1853+ // ジャンル
1854+ entry.setRec_genre(parseGenres(genres));
1855+ }
1856+
1857+ /*
1858+ * タイトル詳細情報を取得する
1859+ */
1860+ protected boolean getTitleDetail( TitleInfo t) {
1861+
1862+ String id = t.getId();
1863+ String device_name = t.getRec_device();
1864+ String device_id = text2value(device, device_name);
1865+ String title_id = t.getId();
1866+ String str = "drive_id=" + device_id + "&title_id=" + title_id;
1867+ String response = "";
1868+
1869+ for (int n=0; n<3; n++){
1870+ // おまじない
1871+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
1872+
1873+ String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/titlelist/LoadTitleDetailData.php?" + str, null, thisEncoding);
1874+// String header = d[0];
1875+ response= d[1];
1876+
1877+ if (response == null) {
1878+ errmsg = ERRID+ERRMSG_NORESPONSE;
1879+ System.out.println(errmsg);
1880+ return(false);
1881+ }
1882+
1883+ // 先頭部分をチェックする
1884+ Matcher mh = Pattern.compile("\\{\"NETdeNAVI\"").matcher(response);
1885+ if ( ! mh.find()) {
1886+ errmsg = ERRID+ERRMSG_INVALIDRESPONSE;
1887+ return (false);
1888+ }
1889+
1890+ // 応答メッセージをパースする
1891+ // {"result":24,"reason":"ERR_EXCLUSIVE"}
1892+ Matcher mr = Pattern.compile("\\{" +
1893+ "\"result\":(\\d+)," +
1894+ "\"reason\":\"([^\"]*)\"\\}").matcher(response);
1895+
1896+ if ( !mr.find() )
1897+ break;
1898+
1899+ String result = mr.group(1);
1900+ String reason = mr.group(2);
1901+
1902+ if (result.equals("1")){
1903+ if (mountUsbDrive(device_id))
1904+ continue;
1905+ }
1906+
1907+ errmsg = "タイトル詳細情報の取得に失敗しました。(result=" + result + ",reason=" + reason + ")";
1908+ reportProgress(errmsg);
1909+ return(false);
1910+ }
1911+
1912+ Matcher ma = Pattern.compile("\\{" +
1913+ "\"id\":\"([^\"]+)\"," + // 1
1914+ "\"unique_id\":\"([^\"]+)\"," + // 2
1915+ "\"titlename\":\"([^\"]+)\"," + // 3
1916+ "\"folders\":\\[([^\\]]*)\\]," + // 4
1917+ "\"network\":(\\d+)," + // 5
1918+ "\"chNum\":\"([^\"]+)\"," + // 6
1919+ "\"branchNum\":(\\d+)," + // 7
1920+ "\"branchNumExists\":(false|true)," + // 8
1921+ "\"ch\":\"([^\"]+)\"," + // 9
1922+ "\"recmode\":\\{([^\\]]*)\\}," + // 10
1923+ "\"genres\":\\[([^\\]]*)\\]," + // 11
1924+ "\"datetime\":(\\d+)," + // 12
1925+ "\"duration\":(\\d+)," + // 13
1926+ "\"copycount\":(\\d+)," + // 14
1927+ "\"dlnaObjectID\":\"([^\"]*)\"," + // 15
1928+ "\"rating\":(\\d+)," + // 16
1929+ "\"recording\":(false|true)," + // 17
1930+ "\"chapter\":\\[([^\\]]*)\\]," + // 18
1931+ "\"autodel\":(false|true)," + // 19
1932+ "\"protection\":(false|true)," + // 20
1933+ "\"mochidashiContentId\":\"([^\"]+)\"," + // 21
1934+ "\"resumeTime\":(\\d+)," + // 22
1935+ "\"shortTimeInfo\":\\[([^\\]]*)\\]," + // 23
1936+ "\"detailDescription\":\"([^\"]*)\"," + // 24
1937+ "\"profiles\":\\[([^\\]]*)\\]," + // 25
1938+ "\"mochidashiState\":(\\d+)," + // 26
1939+ "\"defective\":(false|true)\\}") // 27
1940+ .matcher(response);
1941+
1942+ if ( !ma.find() ) {
1943+ reportProgress(ERRID+"タイトル詳細情報が取得できません.ID=" + id);
1944+ return (false);
1945+ }
1946+
1947+ String unique_id = ma.group(2);
1948+ String titlename = unescapeJavaString(ma.group(3));
1949+ String folders = ma.group(4);
1950+ String network = ma.group(5);
1951+ String ch = ma.group(9);
1952+ String recmode = ma.group(10);
1953+ String genres = ma.group(11);
1954+ String datetime = ma.group(12);
1955+ String duration = ma.group(13);
1956+ String copycount = ma.group(14);
1957+ String dlnaObjectID = ma.group(15);
1958+ Boolean recording = ma.group(17).equals("true");
1959+ String chapter = ma.group(18);
1960+
1961+ // 基本情報をセットする
1962+ setTitleBasicInfo(t, titlename, network, ch, datetime, duration, device_id, folders, genres);
1963+
1964+ // チャプター情報
1965+ t.setChapter(parseChapters(chapter));
1966+ t.setContentId(unique_id);
1967+
1968+ // 録画モード
1969+// String recmode_name = value2text(vrate, recmode);
1970+ Matcher mb = Pattern.compile("\"id\":(\\d+),\"name\":\"([^\"]+)\"").matcher(recmode);
1971+ if (mb.find())
1972+ t.setRec_mode("[" + mb.group(2) + "]");
1973+
1974+ // それ以外の詳細情報
1975+ HashMap<String,String> hmap = new HashMap<String,String>();
1976+ hmap.put("copycount", copycount);
1977+ hmap.put("dlnaObjectID", dlnaObjectID);
1978+ t.setHidden_params(hmap);
1979+
1980+ t.setRecording(recording);
1981+
1982+ t.setDetailLoaded(true);
1983+
1984+ return(true);
1985+ }
1986+
1987+ /**
1988+ * フォルダーのJSONテキストを解析する
1989+ */
1990+ protected ArrayList<TextValueSet> parseFolders(String device_id, String s) {
1991+
1992+ ArrayList<TextValueSet> list = new ArrayList<TextValueSet>();
1993+
1994+ // "folders":[{"folder_id":9}],
1995+ Matcher ma = Pattern.compile("\\{" +
1996+ "\"folder_id\":(\\d+)\\}") // 1
1997+ .matcher(s);
1998+
1999+ while ( ma.find() ) {
2000+ String folder_id = device_id + ":" + ma.group(1);
2001+ String folder_name = value2text(folder, folder_id);
2002+
2003+ TextValueSet t = new TextValueSet();
2004+ t.setText(folder_name);
2005+ t.setValue(folder_id);
2006+ list.add(t);
2007+ }
2008+
2009+ return(list);
2010+ }
2011+
2012+ /**
2013+ * ジャンルのJSONテキストを解析する
2014+ */
2015+ protected ArrayList<TextValueSet> parseGenres(String s) {
2016+
2017+ ArrayList<TextValueSet> list = new ArrayList<TextValueSet>();
2018+
2019+ // "genres":[{"genrecode":7}],
2020+ Matcher ma = Pattern.compile("\\{" +
2021+ "\"genrecode\":(\\d+)\\}") // 1
2022+ .matcher(s);
2023+
2024+ while ( ma.find() ) {
2025+ String genre_code = Integer.toHexString(Integer.parseInt(ma.group(1))).toUpperCase();
2026+ ProgGenre pg = ProgGenre.getByIEPG(genre_code);
2027+ String genre_name = pg != null ? pg.toString() : "";
2028+
2029+ TextValueSet t = new TextValueSet();
2030+ t.setText(genre_name);
2031+ t.setValue(genre_code);
2032+ list.add(t);
2033+ }
2034+
2035+ return(list);
2036+ }
2037+
2038+ /**
2039+ * チャプターのJSONテキストを解析する
2040+ */
2041+ protected ArrayList<ChapterInfo> parseChapters(String s) {
2042+
2043+ ArrayList<ChapterInfo> list = new ArrayList<ChapterInfo>();
2044+
2045+ // {"chaptername":"","duration":168,"changeFlag":0},
2046+ Matcher ma = Pattern.compile("\\{" +
2047+ "\"chaptername\":\"([^\"]*)\"," +
2048+ "\"duration\":(\\d+)," +
2049+ "\"changeFlag\":(\\d+)\\}")
2050+ .matcher(s);
2051+
2052+ while ( ma.find() ) {
2053+ String chaptername = unescapeJavaString(ma.group(1));
2054+ String duration = ma.group(2);
2055+ String changeFlag = ma.group(3);
2056+
2057+ ChapterInfo c = new ChapterInfo();
2058+ c.setName(chaptername);
2059+ c.setDuration(Integer.parseInt(duration));
2060+ c.setChangeFlag(changeFlag.equals("1"));
2061+
2062+ list.add(c);
2063+ }
2064+
2065+ return(list);
2066+ }
2067+
2068+ /**
2069+ * タイトルの編集をレコーダに通知する。これを先に呼ばないとタイトル情報更新時にエラーになる
2070+ */
2071+ private boolean notifyTitleEdit(String devid, String ttlid) {
2072+ errmsg = "";
2073+
2074+ // おまじない
2075+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
2076+
2077+ // RDへの情報作成
2078+ String pstr = "drive_id=" + devid + "&title_id=" + ttlid;
2079+
2080+ // RDへ情報送信
2081+ reportProgress(MSGID+"レコーダーにタイトル編集を通知します.");
2082+ String [] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/titlelist/NotifyTitleEdit.php?" + pstr, null, thisEncoding);
2083+// String header = d[0];
2084+ String response = d[1];
2085+
2086+ if ( !checkGeneralResponse( "タイトル編集通知", response) ){
2087+ return(false);
2088+ }
2089+
2090+ return(true);
2091+ }
2092+
2093+ /*
2094+ * タイトル更新要求のPOSTデータを生成する
2095+ */
2096+ protected String createTitlePostData(TitleInfo t, TitleInfo o, String devId) {
2097+ String postData = "";
2098+ try {
2099+ String title = o != null && t.getTitle().equals(o.getTitle()) ? TITLE_NOCHANGED :
2100+ // ARIB外字を変換した文字列があれば元の外字に戻す
2101+ URLEncoder.encode(AribCharMap.ConvStringToArib(t.getTitle()), thisEncoding);
2102+
2103+ postData =
2104+ "drive_id=" + devId + "&" +
2105+ "title_id=" + t.getId() + "&" +
2106+ "titleName=" + title + "&" +
2107+ encodeFolders(t.getRec_folder()) + "&" +
2108+ "folder_change=1&" +
2109+ encodeChapters(t.getChapter());
2110+ } catch (UnsupportedEncodingException e) {
2111+ // TODO 自動生成された catch ブロック
2112+ e.printStackTrace();
2113+ }
2114+
2115+ return postData;
2116+ }
2117+
2118+ /**
2119+ * フォルダー情報をJSONから変換したPOSTデータの形式にエンコードする
2120+ */
2121+ protected String encodeFolders(ArrayList<TextValueSet> tvs){
2122+ String s = "";
2123+ int n=0;
2124+ for (TextValueSet t : tvs){
2125+ if ( !s.equals("") )
2126+ s += "&";
2127+ s += "folders[" + String.valueOf(n) + "][folder_id]=" + extractFolderID( t.getValue() );
2128+ n++;
2129+ }
2130+
2131+ return s;
2132+ }
2133+
2134+ /**
2135+ * チャプター情報をJSONから変換したPOSTデータの形式にエンコードする
2136+ */
2137+ protected String encodeChapters(ArrayList<ChapterInfo> ci){
2138+ String s = "";
2139+ int n=0;
2140+ for (ChapterInfo t : ci){
2141+ if ( !s.equals("") )
2142+ s += "&";
2143+ try {
2144+ s += "chapters[" + String.valueOf(n) + "][chnum]=" + String.valueOf(n) + "&" +
2145+ "chapters[" + String.valueOf(n) + "][chname]=" + URLEncoder.encode(t.getName(), thisEncoding);
2146+ } catch (UnsupportedEncodingException e) {
2147+ // TODO 自動生成された catch ブロック
2148+ e.printStackTrace();
2149+ }
2150+ n++;
2151+ }
2152+
2153+ return s;
2154+ }
2155+
2156+ /*
2157+ * 固定の各種設定情報を初期化する
2158+ */
2159+ protected void setSettingFixed() {
2160+ // 録画設定
2161+ setSettingVrate(vrate);
2162+
2163+ // パターン情報
2164+ setSettingPattern(tvsPatternCode, tvsPatternName);
2165+
2166+ // エンコーダー
2167+ setSettingEncoder(encoder);
2168+
2169+ // 持ち出し情報
2170+ setSettingPortable(portable);
2171+ }
2172+
2173+ /*
2174+ * 録画モードを初期化する
2175+ */
2176+ protected void setSettingVrate(ArrayList<TextValueSet> tvs) {
2177+ // {"str":"DR","val":0}, {"str":"AF","val":64}, {"str":"AN","val":65}, {"str":"AS","val":66},
2178+ // {"str":"AL","val":67}, {"str":"AE","val":68},
2179+ // {"str":"XP","val":32}, {"str":"SP","val":33}, {"str":"LP","val":34}, {"str":"EP","val":35},
2180+ // {"str":"自動(HD 4.7GB)","val":192}, {"str":"自動(HD 8.5GB)","val":193}, {"str":"自動(HD 25GB)","val":194},
2181+ // {"str":"自動(HD 50GB)","val":195}, {"str":"自動(標準 4.7GB)","val":197}
2182+
2183+ String texts[] = {
2184+ RECMODE_NAME_DR, "[AF]", "[AN]", "[AS]", "[AL]", "[AE]",
2185+ "[XP]", "[SP]", "[LP]", "[EP]",
2186+ "[自動(HD 4.7GB)]", "[自動(HD 8.5GB)]", "[自動(HD 25GB)]", "[自動(HD 50GB)]",
2187+ "[自動(標準 4.7GB)]",
2188+ null};
2189+ String values[] = {
2190+ RECMODE_DR, "64", "65", "66", "67", "68",
2191+ "32", "33", "34", "35",
2192+ "192", "193", "194", "195", "197",
2193+ null};
2194+
2195+ tvs.clear();
2196+
2197+ for (int n=0; values[n] != null; n++){
2198+ TextValueSet t = new TextValueSet();
2199+ t.setText(texts[n]);
2200+ t.setValue(values[n]);
2201+ tvs.add(t);
2202+ }
2203+ }
2204+
2205+ /*
2206+ * 繰り返しパターンを初期化する
2207+ */
2208+ protected void setSettingPattern(ArrayList<TextValueSet> tvsC, ArrayList<TextValueSet> tvsN) {
2209+ // {"num":0,"str":"しない"},{"num":1,"str":"毎週日"},{"num":2,"str":"毎週月"},{"num":4,"str":"毎週火"},
2210+ // {"num":8,"str":"毎週水"},{"num":16,"str":"毎週木"},{"num":32,"str":"毎週金"},{"num":64,"str":"毎週土"},
2211+ // {"num":62,"str":"月~金"},{"num":126,"str":"月~土"},{"num":124,"str":"火~土"},{"num":127,"str":"毎日"}
2212+ int codesRd[]={
2213+ 0, 1, 2, 3, 4, 5, RPTPTN_ID_SAT,
2214+ RPTPTN_ID_MON2THU, RPTPTN_ID_MON2FRI, RPTPTN_ID_MON2SAT, RPTPTN_ID_TUE2SAT, RPTPTN_ID_EVERYDAY, -1};
2215+ String codes[] = {
2216+ "1", "2", "4", "8", "16", "32", "64",
2217+ "30", "62", "126", "124", "127", null};
2218+ String names[] = {
2219+ "毎日曜日", "毎月曜日", "毎火曜日", "毎水曜日", "毎木曜日", "毎金曜日", "毎土曜日",
2220+ "毎月~木", "毎月~金", "毎月~土", "毎火~土", "毎日", null};
2221+
2222+ tvsC.clear();
2223+ tvsN.clear();
2224+
2225+ for (int n=0; codes[n] != null; n++){
2226+ TextValueSet tc = new TextValueSet();
2227+ tc.setText(String.valueOf(codesRd[n]));
2228+ tc.setValue(codes[n]);
2229+ tvsC.add(tc);
2230+
2231+ TextValueSet tn = new TextValueSet();
2232+ tn.setText(names[n]);
2233+ tn.setValue(codes[n]);
2234+ tvsN.add(tn);
2235+ }
2236+ }
2237+
2238+ /**
2239+ * エンコーダー情報を自動生成する
2240+ */
2241+ protected void setSettingEncoder(ArrayList<TextValueSet> tvs) {
2242+ tvs.clear();
2243+
2244+ // チューナー情報を自動生成する
2245+ if (getTunerNum() >= 2){
2246+ for (int i=1; i<=getTunerNum(); i++){
2247+ TextValueSet t = new TextValueSet();
2248+ t.setText("R" + i);
2249+ t.setValue("R" + i);
2250+ tvs.add(t);
2251+ }
2252+ }
2253+ }
2254+
2255+ /*
2256+ * 持ち出し情報を初期化する
2257+ */
2258+ protected void setSettingPortable(ArrayList<TextValueSet> tvs) {
2259+ // {"portableId":0,"portableStr":"しない"},{"portableId":1,"portableStr":"スマホ持ち出し"},
2260+ // {"portableId":3,"portableStr":"DVD持ち出し(VR)"},{"portableId":2,"portableStr":"SeeQVault対応SDカード転送"}
2261+ String codes[] = {
2262+ MOCHIDASHI_NONE, "1", "3", "2", null};
2263+ String names[] = {
2264+ "しない", "スマホ持ち出し", "DVD持ち出し(VR)", "SeeQVault対応SDカード転送", null};
2265+
2266+ tvs.clear();
2267+
2268+ for (int n=0; codes[n] != null; n++){
2269+ TextValueSet t = new TextValueSet();
2270+ t.setText(names[n]);
2271+ t.setValue(codes[n]);
2272+ tvs.add(t);
2273+ }
2274+ }
2275+
2276+ /*
2277+ * 各種設定情報をレコーダーから取得する
2278+ */
2279+ protected boolean setSettingVariable() {
2280+ // 設定情報
2281+// ArrayList<TextValueSet>discs = new ArrayList<TextValueSet>();
2282+// ArrayList<TextValueSet>repeats = new ArrayList<TextValueSet>();
2283+// setSettingSelect(repeats, discs, folder, vrate);
2284+
2285+ // 記録先デバイス
2286+ setSettingDevice();
2287+
2288+ // フォルダ一覧
2289+ setSettingFolders();
2290+
2291+ // チャンネルコードバリュー - uva、bsaは廃止 -
2292+ ArrayList<TextValueSet> tvsCV = new ArrayList<TextValueSet>();
2293+ ArrayList<TextValueSet> tvsCT = new ArrayList<TextValueSet>();
2294+ ArrayList<TextValueSet> tvsBR = new ArrayList<TextValueSet>();
2295+ setSettingChCodeValue(tvsCV, tvsCT, tvsBR);
2296+ if ( tvsCV.size() == 0 && tvsCT.size() == 0 && tvsBR.size() == 0) {
2297+ System.err.println(errmsg = ERRID+"【致命的エラー】 チャンネルコードバリューが取得できません");
2298+ return (false);
2299+ }
2300+ chvalue = tvsCV;
2301+ chtype = tvsCT;
2302+ tvsBranch = tvsBR;
2303+
2304+ return (true);
2305+ }
2306+
2307+ /*
2308+ * デバイス情報を取得する
2309+ */
2310+ protected boolean setSettingDevice() {
2311+ ArrayList<TextValueSet>tvsD = new ArrayList<TextValueSet>();
2312+ ArrayList<DeviceInfo>tvsDI = new ArrayList<DeviceInfo>();
2313+
2314+ reportProgress(MSGID+"ドライブ一覧を取得します.");
2315+
2316+ // おまじない
2317+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
2318+
2319+ String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/titlelist/LoadSelectInfo.php",null, thisEncoding);
2320+ String res = d[1];
2321+
2322+ if (res == null) {
2323+ errmsg = ERRID+ERRMSG_NORESPONSE;
2324+ return (false);
2325+ }
2326+
2327+ Matcher ma = Pattern.compile("\\{" +
2328+ "\"drive_id\":(\\d+)," + // 1
2329+ "\"drivename\":\"([^\"]+)\"," + // 2
2330+ "\"drivetype\":(\\d+)," + // 3
2331+ "\"playlist_enable\":(true|false)," + // 4
2332+ "\"folder_enable\":(true|false)," + // 5
2333+ "\"allsize\":(\\d+)," + // 6
2334+ "\"freesize\":(\\d+)," + // 7
2335+ "\"connected\":(true|false)," + // 8
2336+ "\"protected\":(true|false)," + // 9
2337+ "\"mounted\":(true|false)," + // 10
2338+ "\"ready\":(true|false)," + // 11
2339+ "\"pin_setting\":(true|false)," + // 12
2340+ "\"formatType\":(\\d+)\\}") // 13
2341+ .matcher(res);
2342+
2343+ int allsizeALL = 0;
2344+ int freesizeALL = 0;
2345+
2346+ while ( ma.find() ) {
2347+ String drive_id = ma.group(1);
2348+ String drive_name = ma.group(2);
2349+ String drive_type = ma.group(3);
2350+ boolean playlist_enable = ma.group(4).equals("true");
2351+ boolean folder_enable = ma.group(5).equals("true");
2352+ int allsize = Integer.parseInt(ma.group(6));
2353+ int freesize = Integer.parseInt(ma.group(7));
2354+ boolean connected = ma.group(8).equals("true");
2355+ boolean isprotected = ma.group(9).equals("true");
2356+ boolean mounted = ma.group(10).equals("true");
2357+ boolean ready = ma.group(11).equals("true");
2358+ boolean pin_setting = ma.group(12).equals("true");
2359+ int formatType = Integer.parseInt(ma.group(13));
2360+
2361+ TextValueSet t = new TextValueSet();
2362+ t.setValue(drive_id);
2363+ // デバイス名のコロン以降は無視する
2364+ t.setText(GetDevicePrefix(drive_name));
2365+ tvsD.add(t);
2366+
2367+ DeviceInfo di = new DeviceInfo();
2368+ di.setId(drive_id);
2369+ di.setName(drive_name);
2370+ di.setType(drive_type);
2371+ di.setPlaylistEnable(playlist_enable);
2372+ di.setFolderEnable(folder_enable);
2373+ di.setAllSize(allsize);
2374+ di.setFreeSize(freesize);
2375+ di.setFreeMin((int)Math.round((double)freesize/MIN_PER_MB));
2376+ di.setConnected(connected);
2377+ di.setCanWrite(true);
2378+ di.setProtected(isprotected);
2379+ di.setMounted(mounted);
2380+ di.setReady(ready);
2381+ di.setFormatType(formatType);
2382+ tvsDI.add(di);
2383+
2384+ allsizeALL += allsize;
2385+ freesizeALL += freesize;
2386+ }
2387+
2388+ TextValueSet t = new TextValueSet();
2389+ t.setValue(DEVICE_ALL);
2390+ t.setText(DEVICE_NAME_ALL);
2391+ tvsD.add(t);
2392+
2393+ DeviceInfo di = new DeviceInfo();
2394+ di.setId(DEVICE_ALL);
2395+ di.setName(DEVICE_NAME_ALL);
2396+ di.setAllSize(allsizeALL);
2397+ di.setFreeSize(freesizeALL);
2398+ di.setFreeMin((int)Math.round((double)freesizeALL/MIN_PER_MB));
2399+ tvsDI.add(di);
2400+
2401+ device = tvsD;
2402+ setDeviceInfos(tvsDI);
2403+
2404+ return (true);
2405+ }
2406+
2407+ /*
2408+ * デバイス情報を保存する
2409+ */
2410+ protected void saveDeviceInfos(){
2411+ String myFileId = getIPAddr()+"_"+getPortNo()+"_"+getRecorderId();
2412+ devinfoTFile = "env/devinfo."+myFileId+".xml";
2413+
2414+ DeviceInfosToFile(getDeviceInfos(), devinfoTFile);
2415+ }
2416+ /*
2417+ * フォルダ一覧を取得する
2418+ */
2419+ protected boolean setSettingFolders() {
2420+ ArrayList<TextValueSet> tvsD = device;
2421+ ArrayList<TextValueSet> tvsF = new ArrayList<TextValueSet>();
2422+
2423+ reportProgress(MSGID+"フォルダ一覧を取得します.");
2424+
2425+ TextValueSet t0 = new TextValueSet();
2426+ t0.setText(FOLDER_NAME_NONE);
2427+ t0.setValue(FOLDER_NONE);
2428+ tvsF.add(t0);
2429+
2430+ for (int n=0; n<tvsD.size(); n++){
2431+ TextValueSet tvs = tvsD.get(n);
2432+
2433+ // RDへの情報作成
2434+ String drive_id = tvs.getValue();
2435+ String pstr = "drive=" + drive_id;
2436+
2437+ // おまじない
2438+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
2439+
2440+ // RDへ情報送信
2441+ System.out.println(MSGID+"レコーダーにフォルダー一覧を要求します:" + pstr);
2442+ String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/folderset/LoadFolderList.php?" + pstr, null, thisEncoding);
2443+ String res = d[1];
2444+
2445+ if (res == null) {
2446+ System.out.println(ERRID+"レコーダーからのレスポンスがありません.");
2447+ errmsg = ERRID+ERRMSG_NORESPONSE;
2448+ folder = tvsF;
2449+ return (false);
2450+ }
2451+
2452+ System.out.println(MSGID+"レコーダーからのレスポンスは以下の通りです:" + res);
2453+ Matcher ma = Pattern.compile("\\{" +
2454+ "\"folder_id\":(\\d+)," + // 1
2455+ "\"foldername\":\"([^\"]+)\"\\}") // 2
2456+ .matcher(res);
2457+
2458+ while ( ma.find() ) {
2459+ TextValueSet t = new TextValueSet();
2460+
2461+ String device_name = tvs.getText();
2462+ String folder_id = ma.group(1);
2463+ String folder_name = "[" + device_name + "] " + unescapeJavaString(ma.group(2));
2464+
2465+ System.out.println(MSGID+"フォルダ(" + folder_id + "," + folder_name + ")を追加します.");
2466+ t.setText(folder_name);
2467+ t.setValue(drive_id + ":" + folder_id);
2468+ tvsF.add(t);
2469+ }
2470+ }
2471+
2472+ folder = tvsF;
2473+
2474+ return (true);
2475+ }
2476+
2477+ /*
2478+ * フォルダー一覧をファイルに保存する
2479+ */
2480+ private void saveFolders(){
2481+ String myFileId = getIPAddr()+"_"+getPortNo()+"_"+getRecorderId();
2482+ folderTFile = "env/folders."+myFileId+".xml";
2483+
2484+ TVSsave(folder, folderTFile);
2485+ }
2486+
2487+ /*
2488+ * タイトル一覧をファイルに保存する
2489+ */
2490+ private void saveTitles(String devId){
2491+ String myFileId = getIPAddr()+"_"+getPortNo()+"_"+getRecorderId();
2492+
2493+ if (!DEVICE_ID.equals(DEVICE_ALL)){
2494+ titleFile = "env/title."+myFileId+"." + DEVICE_ID + ".xml";
2495+
2496+ TitlesToFile(getTitles(), titleFile);
2497+ }
2498+ else{
2499+ for (DeviceInfo di : getDeviceInfos() ) {
2500+ if (di.getId().equals(DEVICE_ALL))
2501+ continue;
2502+
2503+ ArrayList<TitleInfo> list = new ArrayList<TitleInfo>();
2504+
2505+ for (TitleInfo ti : getTitles()){
2506+ if (di.getName().startsWith(ti.getRec_device()))
2507+ list.add(ti);
2508+ }
2509+
2510+ titleFile = "env/title."+myFileId+"." + di.getId() + ".xml";
2511+ TitlesToFile(list, titleFile);
2512+ }
2513+ }
2514+ }
2515+
2516+ /*
2517+ * チャンネル一覧を取得する
2518+ */
2519+ private void setSettingChCodeValue(ArrayList<TextValueSet> tvsvalue, ArrayList<TextValueSet> tvstype,
2520+ ArrayList<TextValueSet> tvsbranch) {
2521+ tvsvalue.clear();
2522+ tvstype.clear();
2523+ tvsbranch.clear();
2524+
2525+ reportProgress(MSGID+"チャンネル一覧を取得します.");
2526+
2527+ // おまじない
2528+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
2529+
2530+ String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/torunavi/LoadChannelList.php",null, thisEncoding);
2531+ String res = d[1];
2532+
2533+ if (res == null) {
2534+ errmsg = ERRID+ERRMSG_NORESPONSE;
2535+ return;
2536+ }
2537+
2538+ Matcher ma = Pattern.compile("\\{\"network\":\"([^\"]+)\",\"service\":\\[([^\\]]+)\\]\\}").matcher(res);
2539+ while ( ma.find() ) {
2540+ String network = ma.group(1);
2541+ String chlist = ma.group(2);
2542+ String prefix = "";
2543+
2544+ // "uvd","bsd","csd","l1","l2","l3"
2545+ String typ = "";
2546+ switch(network){
2547+ case "地上":
2548+ typ = CHTYPE_UVD;
2549+ break;
2550+ case "BS":
2551+ typ = CHTYPE_BSD;
2552+ prefix = CHPREFIX_BS;
2553+ break;
2554+ case "CS":
2555+ typ = CHTYPE_CSD;
2556+ prefix = CHPREFIX_CS;
2557+ break;
2558+ }
2559+
2560+ // {"channelid":"G7FE00400","channelNr":"011","channelName":"NHK総合1・東京","chnum":"011","branch":0,
2561+ // "branchNumExists":0,"networkId":32736,"serviceId":1024,"multiSub":false},
2562+ Matcher mb = Pattern.compile("\\{" +
2563+ "\"channelid\":\"([^\"]+)\"," + // 1
2564+ "\"channelNr\":\"([^\"]+)\"," + // 2
2565+ "\"channelName\":\"([^\"]+)\"," + // 3
2566+ "\"chnum\":\"([^\"]+)\"," + // 4
2567+ "\"branch\":(\\d+)," + // 5
2568+ "\"branchNumExists\":(\\d+)," + // 6
2569+ "\"networkId\":(\\d+)," + // 7
2570+ "\"serviceId\":(\\d+)," + // 8
2571+ "\"multiSub\":([^}]+)}") // 9
2572+ .matcher(chlist);
2573+
2574+ // var uvd_ch_text = new Array(
2575+ // "011-1",
2576+ // "012-1",
2577+ // var uvd_ch_value = new Array(
2578+ // "011:32736:1024",
2579+ // "012:32736:1025",
2580+
2581+ while ( mb.find() ) {
2582+ String chno = prefix + mb.group(2);
2583+ String chid = mb.group(4) + ":" + mb.group(7) + ":" + mb.group(8);
2584+
2585+ TextValueSet t = new TextValueSet();
2586+ t.setText(chno);
2587+ t.setValue(chid);
2588+ tvsvalue.add(t);
2589+
2590+ TextValueSet x = new TextValueSet();
2591+ x.setText(chid);
2592+ x.setValue(typ);
2593+ tvstype.add(x);
2594+
2595+ TextValueSet b = new TextValueSet();
2596+ b.setText(chid);
2597+ b.setValue(mb.group(5));
2598+ tvsbranch.add(b);
2599+ }
2600+ }
2601+ }
2602+
2603+ /*
2604+ * 録画設定情報を取得する(未使用)
2605+ */
2606+ protected void setSettingSelect(ArrayList<TextValueSet> tvsR, ArrayList<TextValueSet> tvsD,
2607+ ArrayList<TextValueSet> tvsF, ArrayList<TextValueSet> tvsV) {
2608+ tvsR.clear();
2609+ tvsD.clear();
2610+ tvsF.clear();
2611+ tvsV.clear();
2612+
2613+ reportProgress(MSGID+"録画設定情報を取得します.");
2614+
2615+ // おまじない
2616+ Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
2617+
2618+ String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/torunavi/LoadDialogInitializationData.php?schId=0", null, thisEncoding);
2619+ String res = d[1];
2620+
2621+ if (res == null) {
2622+ errmsg = ERRID+ERRMSG_NORESPONSE;
2623+ return;
2624+ }
2625+
2626+ Matcher ma = Pattern.compile("\\{\"day_select\":\\[([^\\]]+)\\],").matcher(res);
2627+ if ( ma.find() ) {
2628+ Matcher mb = Pattern.compile("\\{\"str\":\"([^\"]+)\",\"val\":\"([^\"]+)\"\\}").matcher(ma.group(1));
2629+
2630+ while( mb.find() ){
2631+ TextValueSet t = new TextValueSet();
2632+ String repeat_id = ma.group(2);
2633+ String repeat_name = ma.group(1);
2634+ t.setValue(repeat_id);
2635+ t.setText(repeat_name);
2636+ tvsR.add(t);
2637+ }
2638+ }
2639+
2640+ Matcher mc = Pattern.compile("\\{\"disc_select\":\\[([^\\]]+)\\],").matcher(res);
2641+ if ( mc.find() ) {
2642+ Matcher md = Pattern.compile("\\{" +
2643+ "\"driveid\":\"([^\"]+)\"," + // 1
2644+ "\"str\":\"([^\"]+)\"," + // 2
2645+ "\"folder_select\":\\[([^\\]]+)\\]," + // 3
2646+ "\"pqmode_select\":\\[([^\\]]+)\\]") // 4
2647+ .matcher(mc.group(1));
2648+
2649+ while( md.find() ){
2650+ String drive_id = md.group(1);
2651+ String drive_name = md.group(2);
2652+ String folders = md.group(3);
2653+ String vrates = md.group(4);
2654+
2655+ TextValueSet t = new TextValueSet();
2656+ t.setValue(drive_id);
2657+ t.setText(drive_name);
2658+ tvsD.add(t);
2659+
2660+ Matcher me = Pattern.compile("\\{" +
2661+ "\"folderid\":\"([^\"]+)\"," + // 1
2662+ "\"str\":\"([^\"]+)\"\\}") // 2
2663+ .matcher(folders);
2664+
2665+ while( me.find() ){
2666+ String folder_id = mc.group(1);
2667+ String folder_name = "[" + drive_name + "] " + unescapeJavaString(me.group(2));
2668+
2669+ TextValueSet tc = new TextValueSet();
2670+ tc.setValue(folder_id);
2671+ tc.setText(folder_name);
2672+ tvsF.add(tc);
2673+ }
2674+
2675+ if (!drive_id.equals(DEVICE_HDD)){
2676+ continue;
2677+ }
2678+
2679+ Matcher mf = Pattern.compile("\\{" +
2680+ "\"str\":\"([^\"]+)\"," + // 1
2681+ "\"pqmode\":\\[([^\\]]+)\\]\\}") // 2
2682+ .matcher(vrates);
2683+
2684+ while( mf.find() ){
2685+ String vrate_id = mf.group(1);
2686+ String vrate_name = "[" + drive_name + "] " + unescapeJavaString(me.group(2));
2687+
2688+ TextValueSet tc = new TextValueSet();
2689+ tc.setValue(vrate_id);
2690+ tc.setText(vrate_name);
2691+ tvsV.add(tc);
2692+ }
2693+ }
2694+ }
2695+ }
2696+
2697+ /*
2698+ * <device_id>:<folder_id> から<folder_id>を切り出す
2699+ */
2700+ protected String extractFolderID( String fol_id ) {
2701+ if (fol_id == null)
2702+ return null;
2703+
2704+ int idx = fol_id.indexOf(':');
2705+ if (idx == -1)
2706+ return fol_id;
2707+
2708+ return fol_id.substring(idx+1);
2709+ }
2710+
2711+ public String unescapeJavaString(String st) {
2712+ StringBuilder sb = new StringBuilder(st.length());
2713+
2714+ for (int i = 0; i < st.length(); i++) {
2715+ char ch = st.charAt(i);
2716+ if (ch == '\\') {
2717+ char nextChar = (i == st.length() - 1) ? '\\' : st
2718+ .charAt(i + 1);
2719+ // Octal escape?
2720+ if (nextChar >= '0' && nextChar <= '7') {
2721+ String code = "" + nextChar;
2722+ i++;
2723+ if ((i < st.length() - 1) && st.charAt(i + 1) >= '0'
2724+ && st.charAt(i + 1) <= '7') {
2725+ code += st.charAt(i + 1);
2726+ i++;
2727+ if ((i < st.length() - 1) && st.charAt(i + 1) >= '0'
2728+ && st.charAt(i + 1) <= '7') {
2729+ code += st.charAt(i + 1);
2730+ i++;
2731+ }
2732+ }
2733+ sb.append((char) Integer.parseInt(code, 8));
2734+ continue;
2735+ }
2736+ switch (nextChar) {
2737+ case '\\':
2738+ ch = '\\';
2739+ break;
2740+ case 'b':
2741+ ch = '\b';
2742+ break;
2743+ case 'f':
2744+ ch = '\f';
2745+ break;
2746+ case 'n':
2747+ ch = '\n';
2748+ break;
2749+ case 'r':
2750+ ch = '\r';
2751+ break;
2752+ case 't':
2753+ ch = '\t';
2754+ break;
2755+ case '\"':
2756+ ch = '\"';
2757+ break;
2758+ case '\'':
2759+ ch = '\'';
2760+ break;
2761+ case '/':
2762+ ch = '/';
2763+ break;
2764+ // Hex Unicode: u????
2765+ case 'u':
2766+ if (i >= st.length() - 5) {
2767+ ch = 'u';
2768+ break;
2769+ }
2770+ int code = Integer.parseInt(
2771+ "" + st.charAt(i + 2) + st.charAt(i + 3)
2772+ + st.charAt(i + 4) + st.charAt(i + 5), 16);
2773+ sb.append(Character.toChars(code));
2774+ i += 5;
2775+ continue;
2776+ }
2777+ i++;
2778+ }
2779+ sb.append(ch);
2780+ }
2781+ return sb.toString();
2782+ }
2783+
2784+ /*
2785+ * デバイス名からコロンの前の部分だけを取り出す
2786+ */
2787+ static String GetDevicePrefix(String device_name){
2788+ Matcher ma = Pattern.compile("^(.*):").matcher(device_name);
2789+ if (ma.find()){
2790+ return ma.group(1);
2791+ }
2792+
2793+ return device_name;
2794+ }
2795+}
--- a/TinyBannavi/src/tainavi/pluginrec/PlugIn_RecDBR_T2007.java
+++ b/TinyBannavi/src/tainavi/pluginrec/PlugIn_RecDBR_T2007.java
@@ -282,28 +282,6 @@ public class PlugIn_RecDBR_T2007 extends HDDRecorderUtils implements HDDRecorder
282282 return(false);
283283 }
284284
285- // 番組詳細情報を取得する
286-// reportProgress(MSGID+"予約詳細情報を取得します.");
287-
288-// // 録画予約の詳細情報を取得し、内容を調整する
289-// int rno=1;
290-// for (ReserveList entry : ra) {
291-// reportProgress("+予約詳細を取得します("+rno+"/"+ra.size()+").");
292-// rno++;
293-//
294-// // 予約詳細情報を取得する
295-// getReserveDetail(entry);
296-//
297-// // 放送局名変換
298-// entry.setCh_name(getChCode().getCH_REC2WEB(entry.getChannel()));
299-//
300-// // TS->DR
301-// translateAttributeTuner(entry);
302-//
303-// // タイトル自動補完フラグなど本体からは取得できない情報を引き継ぐ
304-// copyAttributesT2007(entry, getReserves());
305-// }
306-
307285 setReserves(ra);
308286
309287 // キャッシュに保存
@@ -1279,7 +1257,12 @@ public class PlugIn_RecDBR_T2007 extends HDDRecorderUtils implements HDDRecorder
12791257
12801258 // 枝番有(branchexists,branchnum)
12811259 branchnum = text2value(tvsBranch, channel);
1282- branchexists = Integer.parseInt(branchnum) > 0 ? BRANCH_YES : BRANCH_NO;
1260+ try{
1261+ branchexists = Integer.parseInt(branchnum) > 0 ? BRANCH_YES : BRANCH_NO;
1262+ }
1263+ catch(NumberFormatException e){
1264+ branchnum = "0";
1265+ }
12831266
12841267 // ネットワーク(network)
12851268 String typ = text2value(chtype, channel);