OSDN Git Service

b5b01919f02ca64cf48c19b30102fdb94b6c0f9d
[tainavi/TinyBannavi.git] / TinyBannavi / src / tainavi / PlugIn_RecRD_EDCB.java
1 package tainavi;\r
2 \r
3 import java.io.File;\r
4 import java.io.UnsupportedEncodingException;\r
5 import java.net.Authenticator;\r
6 import java.net.URLEncoder;\r
7 import java.util.ArrayList;\r
8 import java.util.Calendar;\r
9 import java.util.GregorianCalendar;\r
10 import java.util.HashMap;\r
11 import java.util.regex.Matcher;\r
12 import java.util.regex.Pattern;\r
13 \r
14 \r
15 /**\r
16  * \r
17  */\r
18 public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,Cloneable {\r
19 \r
20         @Override\r
21         public PlugIn_RecRD_EDCB clone() {\r
22                 return (PlugIn_RecRD_EDCB) super.clone();\r
23         }\r
24         \r
25         private static final String thisEncoding = "MS932";\r
26         \r
27         /*******************************************************************************\r
28          * 種族の特性\r
29          ******************************************************************************/\r
30 \r
31         @Override\r
32         public String getRecorderId() { return "EpgDataCap_Bon"; }\r
33         @Override\r
34         public RecType getType() { return RecType.RECORDER; }\r
35         \r
36         // 自動エンコーダ選択は禁止\r
37         @Override\r
38         public boolean isAutoEncSelectEnabled() { return false; }\r
39         // 繰り返し予約はできない\r
40         @Override\r
41         public boolean isRepeatReserveSupported() { return false; }\r
42         // 番組追従が可能\r
43         @Override\r
44         public boolean isPursuesEditable() { return true; }\r
45         // タイトル自動補完はできない\r
46         @Override\r
47         public boolean isAutocompleteSupported() { return false; }\r
48         // chvalueを使っていいよ\r
49         @Override\r
50         public boolean isChValueAvailable() { return true; }\r
51         // CHコードは入力しなくていい\r
52         @Override\r
53         public boolean isChCodeNeeded() { return false; }\r
54 \r
55         /*******************************************************************************\r
56          * 予約ダイアログなどのテキストのオーバーライド\r
57          ******************************************************************************/\r
58         \r
59         @Override\r
60         public String getLabel_Audiorate() { return "予約方法"; }\r
61         @Override\r
62         public String getLabel_Folder() { return "録画モード"; }\r
63         @Override\r
64         public String getLabel_Device() { return "指定サービス対象"; }\r
65         @Override\r
66         public String getLabel_XChapter() { return "録画開始(秒前)"; }\r
67         @Override\r
68         public String getLabel_MsChapter() { return "録画終了(秒後)"; }\r
69         @Override\r
70         public String getLabel_MvChapter() { return "復帰後再起動"; }\r
71         @Override\r
72         public String getLabel_DVDCompat() { return "連続録画動作"; }\r
73         @Override\r
74         public String getLabel_LVoice() { return "ぴったり録画"; }\r
75         @Override\r
76         public String getLabel_Aspect() { return "録画後動作"; }\r
77         @Override\r
78         public String getLabel_Videorate() { return "プリセット"; }\r
79         @Override\r
80         public String getLabel_Autodel() { return "録画優先度"; }\r
81         @Override\r
82         public String getLabel_BVperf() { return "ワンセグを別ファイルに出力"; }\r
83         \r
84         @Override\r
85         public String getChDatHelp() { return\r
86                         "「レコーダの放送局名」は、予約一覧取得が正常に完了していれば設定候補がコンボボックスで選択できるようになります。"+\r
87                         "";\r
88         }\r
89         \r
90         /*******************************************************************************\r
91          * 定数\r
92          ******************************************************************************/\r
93 \r
94         private static final String ITEM_REC_MODE_DISABLE       = "無効";\r
95         \r
96         private static final String ITEM_JUST_ENABLE            = "する";\r
97 \r
98         private static final String ITEM_REC_TYPE_EPG           = "EPG";\r
99         private static final String ITEM_REC_TYPE_PROG          = "プログラム";\r
100 \r
101         private static final String ITEM_PRESETID_REG           = "予約時";\r
102 \r
103         private static final String ITEM_MARGINE_DEFAULT        = "デフォルト";\r
104         \r
105         private static final String ITEM_SERVMOCE_DEFAULT       = "デフォルト";\r
106         private static final String ITEM_SERVMOCE_SUBT          = "+字幕";\r
107         private static final String ITEM_SERVMOCE_CARO          = "+カルーセル";\r
108         private static final String ITEM_SERVMOCE_SUBTCARO      = "+字幕&カルーセル";\r
109         private static final String ITEM_SERVMOCE_NONE          = "なし";\r
110         \r
111         private static final String ITEM_YES = "する";\r
112         private static final String ITEM_NO = "しない";\r
113 \r
114         private static final String VALUE_REC_MODE_DISABLE  = "5";\r
115 \r
116         private static final String VALUE_YES  = "1";\r
117         private static final String VALUE_NO  = "0";\r
118         \r
119         private static final String VALUE_TRACE_DISABLE         = "0";\r
120         private static final String VALUE_TRACE_ENABLE          = "1";\r
121 \r
122         private static final String VALUE_REC_TYPE_EPG          = "EPG";\r
123         private static final String VALUE_REC_TYPE_PROG         = "PROGRAM";\r
124 \r
125         private static final String VALUE_PRESETID_REG          = "65535";\r
126         \r
127         private static final String VALUE_MARGINE_DEFAULT       = "FF";\r
128         \r
129         private static final String VALUE_SERVMOCE_DEFAULT      = "FF";\r
130         private static final String VALUE_SERVMOCE_SUBT         = "0-";\r
131         private static final String VALUE_SERVMOCE_CARO         = "-0";\r
132         private static final String VALUE_SERVMOCE_SUBTCARO     = "00";\r
133         private static final String VALUE_SERVMOCE_NONE         = "--";\r
134         \r
135         private static final String RETVAL_KEY_RECFOLDERCOUNT           = "recFolderCount";\r
136         private static final String RETVAL_KEY_R_RECFOLDER                      = "RrecFolder";\r
137         private static final String RETVAL_KEY_R_WRITEPLUGIN            = "RwritePlugIn";\r
138         private static final String RETVAL_KEY_R_RECNAMEPLUGIN          = "RrecNamePlugIn";\r
139         \r
140         private static final String RETVAL_KEY_PARTIALFOLDERCOUNT       = "partialFolderCount";\r
141         private static final String RETVAL_KEY_P_RECFOLDER                      = "PrecFolder";\r
142         private static final String RETVAL_KEY_P_WRITEPLUGIN            = "PwritePlugIn";\r
143         private static final String RETVAL_KEY_P_RECNAMEPLUGIN          = "PrecNamePlugIn";\r
144 \r
145         private static final String TEXT_NANSHICHO_HEADER = "臨)";\r
146         \r
147         // EPG予約の確認範囲は前後4時間まで\r
148         private static final long likersvrange = 4L*3600L*1000L;\r
149 \r
150         // HTTPリトライ回数\r
151         private static final int retryMax = 3;\r
152 \r
153         // ログ関連\r
154         \r
155         private final String MSGID = "["+getRecorderId()+"] ";\r
156         private final String ERRID = "[ERROR]"+MSGID;\r
157         private final String DBGID = "[DEBUG]"+MSGID;\r
158         \r
159         \r
160         /*******************************************************************************\r
161          * CHコード設定、エラーメッセージ\r
162          ******************************************************************************/\r
163         \r
164         @Override\r
165         public ChannelCode getChCode() {\r
166                 return cc;\r
167         }\r
168         \r
169         private ChannelCode cc = new ChannelCode(getRecorderId());\r
170         \r
171         @Override\r
172         public String getErrmsg() {\r
173                 return(errmsg);\r
174         }\r
175         \r
176         private String errmsg = "";\r
177         \r
178         /*******************************************************************************\r
179          * 部品\r
180          ******************************************************************************/\r
181 \r
182         private String rsvedFile = null;\r
183 \r
184         /*******************************************************************************\r
185          * 素のTVSではコードが読めなくなるのでラッピングしてみる\r
186          ******************************************************************************/\r
187 \r
188         private ArrayList<TextValueSet> getListPresetID()                       { return vrate; }               // プリセット\r
189         private String getTextPresetID(ReserveList r)                           { return r.getRec_mode(); }\r
190         private void setTextPresetID(ReserveList r, String text)        { r.setRec_mode(text); }\r
191         \r
192         private ArrayList<TextValueSet> getListRecMode()                        { return folder; }              // 録画モード\r
193         private String getTextRecMode(ReserveList r)                            { return r.getRec_folder(); }\r
194         private void setTextRecMode(ReserveList r, String text)         { r.setRec_folder(text); }\r
195         \r
196         private ArrayList<TextValueSet> getListPriority()                       { return autodel; }             // 優先度\r
197         private String getTextPriority(ReserveList r)                           { return r.getRec_autodel(); }\r
198         private void setTextPriority(ReserveList r, String text)        { r.setRec_autodel(text); }\r
199         \r
200         private ArrayList<TextValueSet> getListPittariFlag()            { return lvoice; }              // ぴったり(?)録画\r
201         private String getTextPittariFlag(ReserveList r)                        { return r.getRec_lvoice(); }\r
202         private void setTextPittariFlag(ReserveList r, String text)     { r.setRec_lvoice(text); }\r
203         \r
204         private ArrayList<TextValueSet> getListSuspendMode()            { return aspect; }      // 録画後動作\r
205         private String getTextSuspendMode(ReserveList r)                        { return r.getRec_aspect(); }\r
206         private void setTextSuspendMode(ReserveList r, String text)     { r.setRec_aspect(text); }\r
207         \r
208         private ArrayList<TextValueSet> getListRebootFlag()                     { return mvchapter; }   // 復帰後再起動する\r
209         private String getTextRebootFlag(ReserveList r)                         { return r.getRec_mvchapter(); }\r
210         private void setTextRebootFlag(ReserveList r, String text)      { r.setRec_mvchapter(text); }\r
211         \r
212         private ArrayList<TextValueSet> getListStartMargine()           { return xchapter; }    // 録画マージン(開始)\r
213         private String getTextStartMargine(ReserveList r)                       { return r.getRec_xchapter(); }\r
214         private void setTextStartMargine(ReserveList r, String text){ r.setRec_xchapter(text); }\r
215         \r
216         private ArrayList<TextValueSet> getListEndMargine()                     { return mschapter; }   // 録画マージン(終了)\r
217         private String getTextEndMargine(ReserveList r)                         { return r.getRec_mschapter(); }\r
218         private void setTextEndMargine(ReserveList r, String text)      { r.setRec_mschapter(text); }\r
219         \r
220         private ArrayList<TextValueSet> getListContinueRecFlag()        { return dvdcompat; }           // 連続録画動作\r
221         private String getTextContinueRecFlag(ReserveList r)            { return r.getRec_dvdcompat(); }\r
222         private void setTextContinueRecFlag(ReserveList r, String text) { r.setRec_dvdcompat(text); }\r
223         \r
224         private ArrayList<TextValueSet> getListServiceMode()            { return device; }              // 指定サービス対象データ\r
225         private String getTextServiceMode(ReserveList r)                        { return r.getRec_device(); }\r
226         private void setTextServiceMode(ReserveList r, String text)     { r.setRec_device(text); }\r
227         \r
228         private ArrayList<TextValueSet> getListTunerID()                        { return encoder; }             // 使用チューナー強制指定\r
229         private String getTextTunerID(ReserveList r)                            { return r.getTuner(); }\r
230         private void setTextTunerID(ReserveList r, String text)         { r.setTuner(text); }\r
231         \r
232         private ArrayList<TextValueSet> getListPartialRecFlag()         { return bvperf; }              // 別ファイルに同時出力する\r
233         private String getTextPartialRecFlag(ReserveList r)                     { return r.getRec_bvperf(); }\r
234         private void setTextPartialRecFlag(ReserveList r, String text)  { r.setRec_bvperf(text); }\r
235         \r
236         private ArrayList<TextValueSet> getListRecType()                        { return arate; }               // 予約方式 ★鯛ナビ独自\r
237         private String getTextRecType(ReserveList r)                            { return r.getRec_audio(); }\r
238         private void setTextRecType(ReserveList r, String text)         { r.setRec_audio(text); }\r
239         \r
240         private ArrayList<TextValueSet> getListChValue()                        { return chvalue; }             // CH番号 ★鯛ナビ独自\r
241         //private String getTextChValue(ReserveList r)                          { return null; }\r
242         \r
243         private ArrayList<TextValueSet> getListChType()                         { return chtype; }              // CH種別 ★鯛ナビ独自\r
244         //private String getTextChType(ReserveList r)                                   { return null; }\r
245         \r
246         private void setListPresetID(ArrayList<TextValueSet> tvs)               { ArrayList<TextValueSet> o = getListPresetID();                o.clear(); o.addAll(tvs); }\r
247         private void setListRecMode(ArrayList<TextValueSet> tvs)                { ArrayList<TextValueSet> o = getListRecMode();                 o.clear(); o.addAll(tvs); }\r
248         private void setListPriority(ArrayList<TextValueSet> tvs)               { ArrayList<TextValueSet> o = getListPriority();                o.clear(); o.addAll(tvs); }\r
249         private void setListPittariFlag(ArrayList<TextValueSet> tvs)    { ArrayList<TextValueSet> o = getListPittariFlag();             o.clear(); o.addAll(tvs); }\r
250         private void setListSuspendMode(ArrayList<TextValueSet> tvs)    { ArrayList<TextValueSet> o = getListSuspendMode();             o.clear(); o.addAll(tvs); }\r
251         //private void setListRebootFlag(ArrayList<TextValueSet> tvs)           { ArrayList<TextValueSet> o = getListRebootFlag();              o.clear(); o.addAll(tvs); }\r
252         //private void setListStartMargine(ArrayList<TextValueSet> tvs) { ArrayList<TextValueSet> o = getListStartMargine();    o.clear(); o.addAll(tvs); }\r
253         //private void setListEndMargine(ArrayList<TextValueSet> tvs)           { ArrayList<TextValueSet> o = getListEndMargine();              o.clear(); o.addAll(tvs); }\r
254         //private void setListContinueRecFlag(ArrayList<TextValueSet> tvs){ ArrayList<TextValueSet> o = getListContinueRecFlag();       o.clear(); o.addAll(tvs); }\r
255         private void setListTunerID(ArrayList<TextValueSet> tvs)                { ArrayList<TextValueSet> o = getListTunerID();                 o.clear(); o.addAll(tvs); }\r
256         //private void setListPartialRecFlag(ArrayList<TextValueSet> tvs)       { ArrayList<TextValueSet> o = getListPartialRecFlag();  o.clear(); o.addAll(tvs); }\r
257         //private void setListRecType(ArrayList<TextValueSet> tvs)              { ArrayList<TextValueSet> o = getListRecType();                 o.clear(); o.addAll(tvs); }\r
258         private void setListChValue(ArrayList<TextValueSet> tvs)                { ArrayList<TextValueSet> o = getListChValue();                 o.clear(); o.addAll(tvs); }\r
259         private void setListChType(ArrayList<TextValueSet> tvs)                 { ArrayList<TextValueSet> o = getListChType();                  o.clear(); o.addAll(tvs); }\r
260 \r
261         /*******************************************************************************\r
262          * コンストラクタ\r
263          ******************************************************************************/\r
264         \r
265         public PlugIn_RecRD_EDCB() {\r
266                 setIPAddr("127.0.0.1(サンプル)");\r
267                 setPortNo("5510(サンプル)");\r
268                 setUser("IDとPASSはダミーで結構です");\r
269                 setPasswd("********");\r
270         }\r
271 \r
272         /*******************************************************************************\r
273          * チャンネルリモコン機能\r
274          ******************************************************************************/\r
275         \r
276         @Override\r
277         public boolean ChangeChannel(String Channel) {\r
278                 // 何もない\r
279                 return false;\r
280         }\r
281         \r
282         /*\r
283         @Override\r
284         public void wakeup() {\r
285         }\r
286         */\r
287         \r
288         @Override\r
289         public void shutdown() {\r
290         }\r
291 \r
292         \r
293         /*******************************************************************************\r
294          * レコーダーから予約一覧を取得する\r
295          ******************************************************************************/\r
296         \r
297         @Override\r
298         public boolean GetRdSettings(boolean force) {\r
299                 \r
300                 System.out.println("レコーダの各種設定情報を取得します.");\r
301                 \r
302                 /*\r
303                  *  CHコード設定\r
304                  */\r
305                 \r
306                 cc.load(force);\r
307                 replaceChNames(cc);             // これは予約一覧取得からの場合は無駄な処理になるが、GetRdSettings単体呼び出しなら意味がある\r
308                 \r
309                 /*\r
310                  *  選択肢集団\r
311                  */\r
312                 \r
313                 final String presetIdTFile      = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "presetId", getIPAddr(), getPortNo());\r
314                 final String recModeTFile       = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "recMode", getIPAddr(), getPortNo());\r
315                 final String prioTFile          = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "priority", getIPAddr(), getPortNo());\r
316                 final String pittariTFile       = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "pittari", getIPAddr(), getPortNo());\r
317                 final String suspModeTFile      = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "suspendMode", getIPAddr(), getPortNo());\r
318                 final String tunerIdTFile       = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "tunerId", getIPAddr(), getPortNo());\r
319                 final String chTypeTFile        = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "chType", getIPAddr(), getPortNo());\r
320                 final String chValueTFile       = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "chValue", getIPAddr(), getPortNo());\r
321 \r
322                 // ハードコーディングな選択肢の面々\r
323                 setSettingNoYes(getListRebootFlag());\r
324                 setSettingRecMargin(getListStartMargine());\r
325                 setSettingRecMargin(getListEndMargine());\r
326                 setSettingServiceMode(getListServiceMode());\r
327                 setSettingNoYes(getListContinueRecFlag());\r
328                 setSettingNoYes(getListPartialRecFlag());\r
329                 setSettingRecType(getListRecType());\r
330         \r
331                 if ( force == false ) {\r
332                         /*\r
333                          *  キャッシュから読み出し\r
334                          */\r
335                         setListPresetID(TVSload(presetIdTFile));\r
336                         setListRecMode(TVSload(recModeTFile));\r
337                         setListPriority(TVSload(prioTFile));\r
338                         setListPittariFlag(TVSload(pittariTFile));\r
339                         setListSuspendMode(TVSload(suspModeTFile));\r
340                         setListTunerID(TVSload(tunerIdTFile));\r
341                         setListChValue(TVSload(chValueTFile));\r
342                         setListChType(TVSload(chTypeTFile));\r
343                 }\r
344                 else {\r
345                         /*\r
346                          *  レコーダから読み出し\r
347                          */\r
348                         \r
349                         // おまじない\r
350                         Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
351                         \r
352                         // (1)録画設定の取得\r
353                         {\r
354                                 reportProgress("録画設定を取得します.");\r
355                                 String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/addprogres.html",null);\r
356                                 //String hdr = d[0];\r
357                                 String res = d[1];\r
358                                 \r
359                                 if ( res == null ) {\r
360                                         errmsg = "レコーダーが反応しません";\r
361                                         return false;\r
362                                 }\r
363                                 \r
364                                 ArrayList<TextValueSet> tvs = new ArrayList<TextValueSet>();\r
365                                 ArrayList<TextValueSet> tvs2 = new ArrayList<TextValueSet>();\r
366                                 \r
367                                 // (1-1)プリセット\r
368                                 setSettingEtc(tvs,"presetID",0,res);\r
369                                 add2tvs(tvs, ITEM_PRESETID_REG, VALUE_PRESETID_REG);    // なんつーか\r
370                                 TVSsave(tvs, presetIdTFile);\r
371                                 setListPresetID(tvs);\r
372         \r
373                                 // (1-2)録画モード\r
374                                 setSettingEtc(tvs,"recMode",0,res);\r
375                                 for ( TextValueSet o : tvs ) {\r
376                                         if ( o.getText().equals(ITEM_REC_MODE_DISABLE) ) {\r
377                                                 tvs.remove(o);\r
378                                                 break;\r
379                                         }\r
380                                 }\r
381                                 TVSsave(tvs, recModeTFile);\r
382                                 setListRecMode(tvs);\r
383                                 \r
384                                 // (1-12)録画優先度\r
385                                 setSettingEtc(tvs, "priority", 0, res);\r
386                                 TVSsave(tvs, prioTFile);\r
387                                 setListPriority(tvs);\r
388                                 \r
389                                 // (1-11)ぴったり\r
390                                 setSettingEtc(tvs,"pittariFlag",0,res);\r
391                                 TVSsave(tvs, pittariTFile);\r
392                                 setListPittariFlag(tvs);\r
393                                 \r
394                                 // (1-6)録画後動作\r
395                                 setSettingEtc(tvs,"suspendMode",0,res);\r
396                                 TVSsave(tvs, suspModeTFile);\r
397                                 setListSuspendMode(tvs);\r
398                                 \r
399                                 // (1-4)エンコーダ\r
400                                 setSettingEtc(tvs,"tunerID",0,res);\r
401                                 TVSsave(tvs, tunerIdTFile);\r
402                                 setListTunerID(tvs);\r
403                                 \r
404                                 // (1-5)チャンネル\r
405                                 setSettingChCodeValue(tvs,tvs2,"serviceID",res);\r
406                                 TVSsave(tvs, chValueTFile);\r
407                                 TVSsave(tvs2, chTypeTFile);\r
408                                 setListChValue(tvs);\r
409                                 setListChType(tvs);\r
410                         }\r
411                 }\r
412                 \r
413                 // ちゃんと設定を取得できているよね?\r
414                 return (getListTunerID().size()>0 && getListChValue().size()>0 && getListPresetID().size()>0);\r
415         }\r
416         \r
417         /*\r
418          *      レコーダーから予約一覧を取得する \r
419          */\r
420         \r
421         @Override\r
422         public boolean GetRdReserve(boolean force)\r
423         {\r
424                 System.out.println("レコーダから予約一覧を取得します("+force+")");\r
425                 \r
426                 errmsg = "";\r
427                 \r
428                 // 予約情報キャッシュ保存先ファイル名\r
429                 rsvedFile = String.format("%s%s%s.%s_%s_%s.xml", "env", File.separator, "reserved", getIPAddr(), getPortNo(), getRecorderId());\r
430 \r
431                 // おまじない\r
432                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
433                 \r
434                 File f = new File(rsvedFile);\r
435                 if ( force == false && f.exists() ) {\r
436                         // キャッシュから読み出し(予約一覧)\r
437                         setReserves(ReservesFromFile(rsvedFile));\r
438                         replaceChNames(cc);\r
439                         if (getDebug()) ShowReserves();\r
440 \r
441                         return true;\r
442                 }\r
443                 \r
444                 // レコーダから読み出し(予約一覧)\r
445                 ArrayList<ReserveList> newReserveList = new ArrayList<ReserveList>();\r
446                 if ( ! GetRdReservedList(newReserveList) ) {\r
447                         return(false);\r
448                 }\r
449                 \r
450                 // 既存予約一覧からの情報引き継ぎ\r
451                 copyAttributesAllList(getReserves(), newReserveList);\r
452                 \r
453                 // 保存\r
454                 setReserves(newReserveList);\r
455                 ReservesToFile(getReserves(), rsvedFile);       // キャッシュに保存\r
456                 \r
457                 // 録画済みフラグを立てる(録画結果一覧→予約一覧)\r
458                 setRecordedFlag();\r
459                 \r
460                 ShowReserves();\r
461                 \r
462                 return true;\r
463         }\r
464         \r
465         /**\r
466          * CHコードを置き換えよう(EDCBの場合はCODE2WEB)\r
467          */\r
468         private void replaceChNames(ChannelCode cc) {\r
469                 for ( ReserveList r : getReserves() ) {\r
470                         r.setCh_name(cc.getCH_CODE2WEB(r.getChannel()));\r
471                 }\r
472         }\r
473         \r
474         /**\r
475          * @see #GetRdSettings(boolean)\r
476          */\r
477         @Override\r
478         public boolean GetRdRecorded(boolean force) {\r
479                 \r
480                 // おまじない\r
481                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
482                 \r
483                 System.out.println("レコーダから録画結果一覧を取得します("+force+"): "+getRecorderId()+"("+getIPAddr()+":"+getPortNo()+")");\r
484                 \r
485                 String recedFile = String.format("%s%s%s.%s_%s_%s.xml", "env", File.separator, "recorded", getIPAddr(), getPortNo(), getRecorderId());\r
486                 \r
487                 // 既存のログをチェック\r
488                 ArrayList<RecordedInfo> newRecordedList = RecordedFromFile(recedFile);\r
489                 \r
490                 File f = new File(recedFile);\r
491                 if ( ! force && f.exists() ) {\r
492                         \r
493                         // キャッシュから読み出し(録画結果一覧)\r
494                         setRecorded(newRecordedList);\r
495                         if (getDebug()) ShowRecorded();\r
496         \r
497                         // 録画済みフラグを立てる(録画結果一覧→予約一覧)\r
498                         setRecordedFlag();\r
499                 \r
500                         return true;\r
501                 }\r
502                 \r
503                 if ( ! GetRdRecordedList(newRecordedList) ) {\r
504                         return false;\r
505                 }\r
506                 if ( ! GetRdRecordedListDetailAll(newRecordedList) ) {\r
507                         return false;\r
508                 }\r
509                 setRecorded(newRecordedList);                           // 置き換え\r
510                 RecordedToFile(getRecorded(), recedFile);       // キャッシュに保存\r
511                 \r
512                 // 録画済みフラグを立てる(録画結果一覧→予約一覧)\r
513                 setRecordedFlag();\r
514                 \r
515                 ShowRecorded();\r
516 \r
517                 return true;\r
518         }\r
519         \r
520         private void ShowReserves() {\r
521                 System.out.println("---Reserved List Start---");\r
522                 for ( int i = 0; i<getReserves().size(); i++ ) {\r
523                         // 詳細情報の取得\r
524                         ReserveList e = getReserves().get(i);\r
525                         System.out.println(String.format("[%s] %s\t%s\t%s %s:%s-%s:%s\t%sm\t%s\t%s\t%s(%s)\t%s\t%s\t%s",\r
526                                         (i+1), e.getId(), e.getRec_pattern(), e.getRec_nextdate(), e.getAhh(), e.getAmm(), e.getZhh(),  e.getZmm(),     e.getRec_min(), e.getContentId(), getTextRecType(e), e.getTitle(), e.getTitlePop(), e.getChannel(), e.getCh_name(), e.getRecorded()));\r
527                 }\r
528                 System.out.println("---Reserved List End---");\r
529         }\r
530         private void ShowRecorded() {\r
531                 System.out.println("---Recorded List Start---");\r
532                 for ( int i = 0; i<getRecorded().size(); i++ ) {\r
533                         // 詳細情報の取得\r
534                         RecordedInfo e = getRecorded().get(i);\r
535                         System.out.println(String.format("[%s] %s %s\t%s:%s-%s:%s\t%s(%s)\t%s",\r
536                                         (i+1), e.getId(), e.getDate(), e.getAhh(), e.getAmm(), e.getZhh(), e.getZmm(), e.getTitle(), e.getCh_name(), e.getResult()));\r
537                 }\r
538                 System.out.println("---Recorded List End---");\r
539         }\r
540         \r
541         private boolean GetRdReservedList(ArrayList<ReserveList> newReserveList) {\r
542                 \r
543                 // RDから予約一覧を取り出す\r
544                 String response="";\r
545                 {\r
546                         reportProgress("予約一覧を取得します.");\r
547                         String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/api/EnumReserveInfo",null,"utf8");\r
548                         response = d[1];\r
549                         \r
550                         if (response == null) {\r
551                                 errmsg = "レコーダーが反応しません";\r
552                                 return(false);\r
553                         }\r
554                 }\r
555                 \r
556                 Matcher ma = Pattern.compile("<reserveinfo>(.+?)</reserveinfo>", Pattern.DOTALL).matcher(response);\r
557                 while ( ma.find() ) {\r
558                         String id = null;\r
559                         String title = null;\r
560                         GregorianCalendar cal = null;\r
561                         Integer hh = null;\r
562                         Integer mm = null;\r
563                         Integer length = null;\r
564                         Integer onid = null;\r
565                         Integer tsid = null;\r
566                         Integer sid = null;\r
567                         Integer evid = null;            // 65536:プログラム予約\r
568                         String comment = null;\r
569                         Integer overlapMode = null;\r
570                         \r
571                         Integer recMode = null;\r
572                         Integer priority = null;\r
573                         Integer tuijyuuFlag = null;\r
574                         Integer serviceMode = null;\r
575                         Integer pittariFlag = null;\r
576                         Integer suspendMode = null;\r
577                         Integer rebootFlag = null;\r
578                         Integer useMargineFlag = null;\r
579                         Integer startMargine = null;\r
580                         Integer endMargine = null;\r
581                         Integer continueRecFlag = null;\r
582                         Integer partialRecFlag = null;\r
583                         Integer tunerID = null;\r
584                         \r
585                         String batFilePath = null;\r
586                         \r
587                         int recFolderCount = 0;\r
588                         ArrayList<String> rRecFolder = new ArrayList<String>();\r
589                         ArrayList<String> rWritePlugIn = new ArrayList<String>();\r
590                         ArrayList<String> rRecNamePlugIn = new ArrayList<String>();\r
591                         \r
592                         int partialFolderCount = 0;\r
593                         ArrayList<String> pRecFolder = new ArrayList<String>();\r
594                         ArrayList<String> pWritePlugIn = new ArrayList<String>();\r
595                         ArrayList<String> pRecNamePlugIn = new ArrayList<String>();\r
596                         \r
597                         ArrayList<String> recFileNameList = new ArrayList<String>();\r
598 \r
599                         Matcher mb = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(ma.group(1));\r
600                         while ( mb.find() ) {\r
601                                 /*\r
602                                  * 解析\r
603                                  */\r
604                                 \r
605                                 // 基本情報\r
606                                 if ( mb.group(1).equals("ID") ) {\r
607                                         id = mb.group(2);\r
608                                 }\r
609                                 else if ( mb.group(1).equals("title") ) {\r
610                                         title = CommonUtils.unEscape(mb.group(2));\r
611                                 }\r
612                                 else if ( mb.group(1).equals("startDate") ) {\r
613                                         Matcher mc = Pattern.compile("^(\\d+)/(\\d+)/(\\d+)").matcher(mb.group(2));\r
614                                         if ( mc.find() ) {\r
615                                                 cal = CommonUtils.getCalendar(String.format("%04d/%02d/%02d",Integer.valueOf(mc.group(1)),Integer.valueOf(mc.group(2)),Integer.valueOf(mc.group(3))));\r
616                                         }\r
617                                 }\r
618                                 else if ( mb.group(1).equals("startTime") ) {\r
619                                         Matcher mc = Pattern.compile("^(\\d+):(\\d+)").matcher(mb.group(2));\r
620                                         if ( mc.find() ) {\r
621                                                 hh = Integer.valueOf(mc.group(1));\r
622                                                 mm = Integer.valueOf(mc.group(2));\r
623                                         }\r
624                                 }\r
625                                 else if ( mb.group(1).equals("duration") ) {\r
626                                         length = Integer.valueOf(mb.group(2))/60;\r
627                                 }\r
628                                 else if ( mb.group(1).equals("ONID") ) {\r
629                                         onid = Integer.valueOf(mb.group(2));\r
630                                 }\r
631                                 else if ( mb.group(1).equals("TSID") ) {\r
632                                         tsid = Integer.valueOf(mb.group(2));\r
633                                 }\r
634                                 else if ( mb.group(1).equals("SID") ) {\r
635                                         sid = Integer.valueOf(mb.group(2));\r
636                                 }\r
637                                 else if ( mb.group(1).equals("eventID") ) {\r
638                                         evid = Integer.valueOf(mb.group(2));\r
639                                 }\r
640                                 else if ( mb.group(1).equals("comment") ) {\r
641                                         comment = CommonUtils.unEscape(mb.group(2));\r
642                                 }\r
643                                 else if ( mb.group(1).equals("overlapMode") ) {\r
644                                         overlapMode = Integer.valueOf(mb.group(2));\r
645                                 }\r
646                                 else if ( mb.group(1).equals("recsetting") ) {\r
647                                         // 録画設定\r
648                                         Matcher mc = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(mb.group(2));\r
649                                         while ( mc.find() ) {\r
650                                                 if ( mc.group(1).equals("recMode") ) {\r
651                                                         recMode = Integer.valueOf(mc.group(2));\r
652                                                 }\r
653                                                 else if ( mc.group(1).equals("priority") ) {\r
654                                                         priority = Integer.valueOf(mc.group(2));\r
655                                                 }\r
656                                                 else if ( mc.group(1).equals("tuijyuuFlag") ) {\r
657                                                         tuijyuuFlag = Integer.valueOf(mc.group(2));\r
658                                                 }\r
659                                                 else if ( mc.group(1).equals("serviceMode") ) {\r
660                                                         serviceMode = Integer.valueOf(mc.group(2));\r
661                                                 }\r
662                                                 else if ( mc.group(1).equals("pittariFlag") ) {\r
663                                                         pittariFlag = Integer.valueOf(mc.group(2));\r
664                                                 }\r
665                                                 else if ( mc.group(1).equals("batFilePath") ) {\r
666                                                         batFilePath = mc.group(2);\r
667                                                 }\r
668                                                 else if ( mc.group(1).equals("suspendMode") ) {\r
669                                                         suspendMode = Integer.valueOf(mc.group(2));\r
670                                                 }\r
671                                                 else if ( mc.group(1).equals("rebootFlag") ) {\r
672                                                         rebootFlag = Integer.valueOf(mc.group(2));\r
673                                                 }\r
674                                                 else if ( mc.group(1).equals("useMargineFlag") ) {\r
675                                                         useMargineFlag = Integer.valueOf(mc.group(2));\r
676                                                 }\r
677                                                 else if ( mc.group(1).equals("startMargine") ) {\r
678                                                         startMargine = Integer.valueOf(mc.group(2));\r
679                                                 }\r
680                                                 else if ( mc.group(1).equals("endMargine") ) {\r
681                                                         endMargine = Integer.valueOf(mc.group(2));\r
682                                                 }\r
683                                                 else if ( mc.group(1).equals("continueRecFlag") ) {\r
684                                                         continueRecFlag = Integer.valueOf(mc.group(2));\r
685                                                 }\r
686                                                 else if ( mc.group(1).equals("partialRecFlag") ) {\r
687                                                         partialRecFlag = Integer.valueOf(mc.group(2));\r
688                                                 }\r
689                                                 else if ( mc.group(1).equals("tunerID") ) {\r
690                                                         tunerID = Integer.valueOf(mc.group(2));\r
691                                                 }\r
692                                                 else if ( mc.group(1).equals("recFolderList") ) {\r
693                                                         Matcher md = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(mc.group(2));\r
694                                                         while ( md.find() ) {\r
695                                                                 if ( md.group(1).equals("recFolderInfo") ) {\r
696                                                                         recFolderCount++;\r
697                                                                         Matcher me = Pattern.compile("<(.+?)>(.*?)</\\1>", Pattern.DOTALL).matcher(md.group(2));\r
698                                                                         while ( me.find() ) {\r
699                                                                                 if ( me.group(1).equals("recFolder") ) {\r
700                                                                                         rRecFolder.add(me.group(2));\r
701                                                                                 }\r
702                                                                                 else if ( me.group(1).equals("writePlugIn") ) {\r
703                                                                                         rWritePlugIn.add(me.group(2));\r
704                                                                                 }\r
705                                                                                 else if ( me.group(1).equals("recNamePlugIn") ) {\r
706                                                                                         rRecNamePlugIn.add(me.group(2));\r
707                                                                                 }\r
708                                                                         }\r
709                                                                 }\r
710                                                         }\r
711                                                 }\r
712                                                 else if ( mc.group(1).equals("partialRecFolder") ) {\r
713                                                         Matcher md = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(mc.group(2));\r
714                                                         while ( md.find() ) {\r
715                                                                 if ( md.group(1).equals("recFolderInfo") ) {\r
716                                                                         partialFolderCount++;\r
717                                                                         Matcher me = Pattern.compile("<(.+?)>(.*?)</\\1>", Pattern.DOTALL).matcher(md.group(2));\r
718                                                                         while ( me.find() ) {\r
719                                                                                 if ( me.group(1).equals("recFolder") ) {\r
720                                                                                         pRecFolder.add(me.group(2));\r
721                                                                                 }\r
722                                                                                 else if ( me.group(1).equals("writePlugIn") ) {\r
723                                                                                         pWritePlugIn.add(me.group(2));\r
724                                                                                 }\r
725                                                                                 else if ( me.group(1).equals("recNamePlugIn") ) {\r
726                                                                                         pRecNamePlugIn.add(me.group(2));\r
727                                                                                 }\r
728                                                                         }\r
729                                                                 }\r
730                                                         }\r
731                                                 }\r
732                                         }\r
733                                 }\r
734                                 else if ( mb.group(1).equals("recFileNameList") ) {\r
735                                         Matcher mc = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(mb.group(2));\r
736                                         while ( mc.find() ) {\r
737                                                 if ( mc.group(1).equals("name") ) {\r
738                                                         recFileNameList.add(mc.group(2));\r
739                                                 }\r
740                                         }\r
741                                 }\r
742                         }\r
743                         \r
744                         /*\r
745                          * 生成\r
746                          */\r
747                         \r
748                         ReserveList r = new ReserveList();\r
749                         \r
750                         r.setId(getUniqId(id));\r
751                         r.setTitle(title);\r
752                         r.setTitlePop(TraceProgram.replacePop(title));\r
753                         \r
754                         String chid = ContentIdEDCB.getChId(onid, tsid, sid);\r
755                         String edcbid = ContentIdEDCB.getContentId(chid, evid);\r
756                         String contentid = ContentIdEDCB.stripMark(edcbid);\r
757 \r
758                         {\r
759                                 StringBuilder dt = new StringBuilder("■予約状況:");\r
760                                 if ( evid != 0 && evid != 65535 ) {\r
761                                         // EPG予約\r
762                                         r.setContentId(edcbid);\r
763                                         setTextRecType(r,ITEM_REC_TYPE_EPG);\r
764                                         //\r
765                                         if ( comment != null && comment.contains("EPG自動予約") ) {\r
766                                                 dt.append(comment);\r
767                                                 r.setAutoreserved(true);\r
768                                         }\r
769                                         else {\r
770                                                 dt.append("EPG手動予約");\r
771                                                 r.setAutoreserved(false);\r
772                                         }\r
773                                 }\r
774                                 else {\r
775                                         // プログラム予約\r
776                                         r.setContentId(null);\r
777                                         setTextRecType(r,ITEM_REC_TYPE_PROG);\r
778                                         //\r
779                                         dt.append("プログラム予約");\r
780                                         r.setAutoreserved(false);\r
781                                 }\r
782                                 dt.append("\n");\r
783                                 r.setDetail(dt.toString());             // 初期化\r
784                         }\r
785                         \r
786                         r.setChannel(String.valueOf(Long.decode("0x"+chid)));\r
787                         r.setCh_name(cc.getCH_CODE2WEB(r.getChannel()));\r
788                         \r
789                         r.setRec_pattern(CommonUtils.getDate(cal));\r
790                         r.setRec_pattern_id(11);\r
791                         cal.set(Calendar.HOUR_OF_DAY, hh);\r
792                         cal.set(Calendar.MINUTE, mm);\r
793                         r.setAhh(String.format("%02d", cal.get(Calendar.HOUR_OF_DAY)));\r
794                         r.setAmm(String.format("%02d", cal.get(Calendar.MINUTE)));\r
795                         cal.add(Calendar.MINUTE,length);\r
796                         r.setZhh(String.format("%02d", cal.get(Calendar.HOUR_OF_DAY)));\r
797                         r.setZmm(String.format("%02d", cal.get(Calendar.MINUTE)));\r
798                         r.setRec_nextdate(CommonUtils.getNextDate(r));\r
799                         r.setRec_min(CommonUtils.getRecMin(r.getAhh(), r.getAmm(), r.getZhh(), r.getZmm()));\r
800                         getStartEndDateTime(r);\r
801                         \r
802                         // 予約実行とチューナー不足\r
803                         {\r
804                                 String text = value2text(getListRecMode(),String.valueOf(recMode));\r
805                                 setTextRecMode(r, text);\r
806                                 if ( text.equals("") ) {\r
807                                         r.setExec(false);\r
808                                         r.setTunershort(false);\r
809                                 }\r
810                                 else {\r
811                                         r.setExec(true);\r
812                                         r.setTunershort(overlapMode!=0);\r
813                                 }\r
814                         }\r
815                         \r
816                         // プリセット(予約一覧からとれる情報は常に「予約時」)\r
817                         setTextPresetID(r, value2text(getListPresetID(),VALUE_PRESETID_REG));\r
818                         \r
819                         // チューナー\r
820                         setTextTunerID(r, value2text(getListTunerID(),String.valueOf(tunerID)));\r
821                         \r
822                         // 録画後動作\r
823                         setTextSuspendMode(r, value2text(getListSuspendMode(),String.valueOf(suspendMode)));\r
824 \r
825                         // 追従\r
826                         r.setPursues(VALUE_YES.equals(String.valueOf(tuijyuuFlag)));\r
827                         \r
828                         // ぴったり\r
829                         setTextPittariFlag(r, value2text(getListPittariFlag(),String.valueOf(pittariFlag)));\r
830                         \r
831                         // 録画優先度\r
832                         setTextPriority(r, value2text(getListPriority(),String.valueOf(priority)));\r
833                         \r
834                         // 連続録画動作\r
835                         if ( VALUE_YES.equals(String.valueOf(continueRecFlag)) ) {\r
836                                 setTextContinueRecFlag(r, ITEM_YES);\r
837                         }\r
838                         else {\r
839                                 setTextContinueRecFlag(r, ITEM_NO);\r
840                         }\r
841                         \r
842                         // 復帰後動作\r
843                         if ( VALUE_YES.equals(String.valueOf(rebootFlag)) ) {\r
844                                 setTextRebootFlag(r, ITEM_YES);\r
845                         }\r
846                         else {\r
847                                 setTextRebootFlag(r, ITEM_NO);\r
848                         }\r
849                         \r
850                         // 指定サービス対象データ\r
851                         if ( serviceMode == 0x00 ) {\r
852                                 setTextServiceMode(r, ITEM_SERVMOCE_DEFAULT);\r
853                         }\r
854                         else if ( serviceMode == 0x01 ) {\r
855                                 setTextServiceMode(r, ITEM_SERVMOCE_NONE);\r
856                         }\r
857                         else if ( serviceMode == 0x11 ) {\r
858                                 setTextServiceMode(r, ITEM_SERVMOCE_SUBT);\r
859                         }\r
860                         else if ( serviceMode == 0x21 ) {\r
861                                 setTextServiceMode(r, ITEM_SERVMOCE_CARO);\r
862                         }\r
863                         else if ( serviceMode == 0x31 ) {\r
864                                 setTextServiceMode(r, ITEM_SERVMOCE_SUBTCARO);\r
865                         }\r
866                         \r
867                         // 録画マージン\r
868                         if ( useMargineFlag == 0 ) {\r
869                                 setTextStartMargine(r, ITEM_MARGINE_DEFAULT);\r
870                                 setTextEndMargine(r, ITEM_MARGINE_DEFAULT);\r
871                         }\r
872                         else {\r
873                                 setTextStartMargine(r, String.valueOf(startMargine));\r
874                                 setTextEndMargine(r, String.valueOf(endMargine));\r
875                         }\r
876                         \r
877                         // 別ファイルに同時出力する\r
878                         if ( VALUE_YES.equals(String.valueOf(partialRecFlag)) ) {\r
879                                 setTextPartialRecFlag(r, ITEM_YES);\r
880                         }\r
881                         else {\r
882                                 setTextPartialRecFlag(r, ITEM_NO);\r
883                         }\r
884                         \r
885                         // 録画後実行bat\r
886                         if ( batFilePath != null ) {\r
887                                 StringBuilder dt = new StringBuilder(r.getDetail());\r
888                                 dt.append("■録画後実行bat:");\r
889                                 dt.append(batFilePath);\r
890                                 dt.append("\n");\r
891                                 r.setDetail(dt.toString());\r
892                         }\r
893                         \r
894                         // オプショナル\r
895                         r.getHidden_params().put(RETVAL_KEY_RECFOLDERCOUNT, String.valueOf(recFolderCount));\r
896                         if ( recFolderCount > 0 && rRecFolder.size() >= recFolderCount && rWritePlugIn.size() >= recFolderCount && rRecNamePlugIn.size() >= recFolderCount ) {\r
897                                 StringBuilder dt = new StringBuilder(r.getDetail());\r
898                                 StringBuilder rf = new StringBuilder();\r
899                                 StringBuilder wp = new StringBuilder();\r
900                                 StringBuilder rp = new StringBuilder();\r
901                                 for ( int i=0; i<recFolderCount; i++ ) {\r
902                                         dt.append("■録画フォルダ・出力PlugIn・ファイル名PlugIn(");\r
903                                         dt.append(String.valueOf(i+1));\r
904                                         dt.append("):");\r
905                                         dt.append(rRecFolder.get(i));\r
906                                         dt.append(" / ");\r
907                                         dt.append(rWritePlugIn.get(i));\r
908                                         dt.append(" / ");\r
909                                         dt.append(rRecNamePlugIn.get(i));\r
910                                         dt.append("\n");\r
911                                         \r
912                                         rf.append(rRecFolder.get(i));\r
913                                         rf.append("\t");\r
914                                         \r
915                                         wp.append(rWritePlugIn.get(i));\r
916                                         wp.append("\t");\r
917                                         \r
918                                         rp.append(rRecNamePlugIn.get(i));\r
919                                         rp.append("\t");\r
920                                 }\r
921                                 r.setDetail(dt.toString());\r
922                                 r.getHidden_params().put(RETVAL_KEY_R_RECFOLDER, rf.toString());\r
923                                 r.getHidden_params().put(RETVAL_KEY_R_WRITEPLUGIN, wp.toString());\r
924                                 r.getHidden_params().put(RETVAL_KEY_R_RECNAMEPLUGIN, rp.toString());\r
925                         }\r
926                         \r
927                         r.getHidden_params().put(RETVAL_KEY_PARTIALFOLDERCOUNT, String.valueOf(partialFolderCount));\r
928                         if ( partialFolderCount > 0 && pRecFolder.size() >= recFolderCount && pWritePlugIn.size() >= recFolderCount && pRecNamePlugIn.size() >= recFolderCount ) {\r
929                                 StringBuilder dt = new StringBuilder(r.getDetail());\r
930                                 StringBuilder rf = new StringBuilder();\r
931                                 StringBuilder wp = new StringBuilder();\r
932                                 StringBuilder rp = new StringBuilder();\r
933                                 for ( int i=0; i<recFolderCount; i++ ) {\r
934                                         dt.append("■[1SEG] 録画フォルダ・出力PlugIn・ファイル名PlugIn(");\r
935                                         dt.append(String.valueOf(i+1));\r
936                                         dt.append("):");\r
937                                         dt.append(pRecFolder.get(i));\r
938                                         dt.append(" / ");\r
939                                         dt.append(pWritePlugIn.get(i));\r
940                                         dt.append(" / ");\r
941                                         dt.append(pRecNamePlugIn.get(i));\r
942                                         dt.append("\n");\r
943                                         \r
944                                         rf.append(pRecFolder.get(i));\r
945                                         rf.append("\t");\r
946                                         \r
947                                         wp.append(pWritePlugIn.get(i));\r
948                                         wp.append("\t");\r
949                                         \r
950                                         rp.append(pRecNamePlugIn.get(i));\r
951                                         rp.append("\t");\r
952                                 }\r
953                                 r.setDetail(dt.toString());\r
954                                 r.getHidden_params().put(RETVAL_KEY_P_RECFOLDER, rf.toString());\r
955                                 r.getHidden_params().put(RETVAL_KEY_P_WRITEPLUGIN, wp.toString());\r
956                                 r.getHidden_params().put(RETVAL_KEY_P_RECNAMEPLUGIN, rp.toString());\r
957                         }\r
958                         \r
959                         // 予定ファイル名\r
960                         if ( recFileNameList.size() > 0 ) {\r
961                                 StringBuilder dt = new StringBuilder(r.getDetail());\r
962                                 for ( int i=0; i<recFileNameList.size(); i++ ) {\r
963                                         dt.append("■予定ファイル名(");\r
964                                         dt.append(String.valueOf(i+1));\r
965                                         dt.append("):");\r
966                                         dt.append(recFileNameList.get(i));\r
967                                 }\r
968                                 dt.append("\n");\r
969                                 r.setDetail(dt.toString());\r
970                         }\r
971                         \r
972                         // 番組ID\r
973                         if ( evid != 0 && evid != 65535 ) {\r
974                                 StringBuilder dt = new StringBuilder(r.getDetail());\r
975                                 dt.append("■番組ID:");\r
976                                 dt.append(contentid);\r
977                                 dt.append("\n");\r
978                                 r.setDetail(dt.toString());\r
979                         }\r
980                         \r
981                         /*\r
982                          *  既存予約一覧からの情報引き継ぎ\r
983                          */\r
984                         //XcopyAttributes(r, getReserves());\r
985                         \r
986                         /*\r
987                          * 追加\r
988                          */\r
989                         newReserveList.add(r);\r
990                 }\r
991                 \r
992                 return true;\r
993         }\r
994 \r
995         private boolean GetRdReservedDetailByContentId(ReserveList r, int cnt) {\r
996                 String pstr = genPoststrEPGA(r);\r
997                 String url = "http://"+getIPAddr()+":"+getPortNo()+"/epginfo.html?"+pstr;\r
998                 System.out.println("URL: "+url);\r
999                 return _GetRdReservedDetail(r, url, cnt);\r
1000         }\r
1001         private boolean GetRdReservedDetailByReserveId(ReserveList r, int cnt) {\r
1002                 String url = "http://"+getIPAddr()+":"+getPortNo()+"/reserveinfo.html?id="+getRsvId(r.getId());\r
1003                 System.out.println("URL: "+url);\r
1004                 return _GetRdReservedDetail(r, url, cnt);\r
1005         }\r
1006         private boolean _GetRdReservedDetail(ReserveList r, String url, int cnt) {\r
1007                 \r
1008                 reportProgress("+予約詳細を取得します("+cnt+")");\r
1009 \r
1010                 String[] d = reqGET(url,null);\r
1011                 //String hdr = d[0];\r
1012                 String res = d[1];\r
1013                 Matcher mb = null;\r
1014                 \r
1015                 if (res == null) {\r
1016                         return false;\r
1017                 }\r
1018                 \r
1019                 try {\r
1020                         // 予約ID\r
1021                         mb = Pattern.compile("<form method=\"POST\" action=\"reservedel\\.html\\?id=(\\d+?)\">").matcher(res);\r
1022                         if ( mb.find() ) {\r
1023                                 r.setId(getUniqId(mb.group(1)));\r
1024                         }\r
1025                         \r
1026                         // イベントIDと予約方式\r
1027                         int evid = -1;\r
1028                         mb = Pattern.compile("EventID:\\d+\\(0x(.+)\\)").matcher(res);\r
1029                         if ( mb.find() ) {\r
1030                                 evid = Integer.decode("0X"+mb.group(1));\r
1031                                 setTextRecType(r,ITEM_REC_TYPE_EPG);\r
1032                         }\r
1033                         else {\r
1034                                 setTextRecType(r,ITEM_REC_TYPE_PROG);\r
1035                         }\r
1036 \r
1037                         // EPG予約場合のみの処理\r
1038                         if ( getTextRecType(r).equals(ITEM_REC_TYPE_EPG) ) {\r
1039                                 // 放送局\r
1040                                 int onid = -1;\r
1041                                 mb = Pattern.compile("OriginalNetworkID:\\d+\\(0x(.+)\\)").matcher(res);\r
1042                                 if ( mb.find() ) {\r
1043                                         onid = Integer.decode("0X"+mb.group(1));\r
1044                                 }\r
1045                                 int tsid = -1;\r
1046                                 mb = Pattern.compile("TransportStreamID:\\d+\\(0x(.+)\\)").matcher(res);\r
1047                                 if ( mb.find() ) {\r
1048                                         tsid = Integer.decode("0X"+mb.group(1));\r
1049                                 }\r
1050                                 int sid = -1;\r
1051                                 mb = Pattern.compile("ServiceID:\\d+\\(0x(.+)\\)").matcher(res);\r
1052                                 if ( mb.find() ) {\r
1053                                         sid = Integer.decode("0X"+mb.group(1));\r
1054                                 }\r
1055                                 if ( onid == -1 || tsid == -1 || sid == -1 ) {\r
1056                                         System.err.println("放送局IDが取得できませんでした: "+url);\r
1057                                 }\r
1058                                 else {\r
1059                                         String chid = String.valueOf(Long.decode("0x"+ContentIdEDCB.getChId(onid,tsid,sid)));\r
1060                                         r.setCh_name(cc.getCH_CODE2WEB(chid));\r
1061                                         r.setChannel(chid);\r
1062                                         \r
1063                                         r.setContentId(ContentIdEDCB.getContentId(onid,tsid,sid,evid));\r
1064                                 }\r
1065                                 \r
1066                                 // (1-X) 開始・終了日時と、番組詳細、タイトル\r
1067                                 // ★一覧の開始・終了日時は、登録した際の開始・終了日時のままなので詳細を参照して修正が必要\r
1068                                 mb = Pattern.compile("<HR>番組情報<HR>\\s*(\\d\\d\\d\\d/\\d\\d/\\d\\d\\(.\\)) (\\d\\d):(\\d\\d)~(\\d\\d):(\\d\\d)<BR>.+?<BR>\\s*(.*?)<BR>.*?<BR>\\s*(.+?)\\s*<HR>録画設定<HR>",Pattern.DOTALL).matcher(res);\r
1069                                 if ( mb.find() ) {\r
1070                                         GregorianCalendar cal = CommonUtils.getCalendar(mb.group(1));\r
1071                                         r.setRec_pattern(CommonUtils.getDate(cal));\r
1072                                         r.setRec_pattern_id(11);\r
1073                                         \r
1074                                         r.setStartDateTime(CommonUtils.getDateTime(cal));\r
1075                                         r.setRec_nextdate(r.getStartDateTime());\r
1076                                         r.setAhh(mb.group(2));\r
1077                                         r.setAmm(mb.group(3));\r
1078                                         r.setZhh(mb.group(4));\r
1079                                         r.setZmm(mb.group(5));\r
1080                                         \r
1081                                         r.setRec_nextdate(CommonUtils.getNextDate(r));\r
1082                                         r.setRec_min(CommonUtils.getRecMin(r.getAhh(), r.getAmm(), r.getZhh(), r.getZmm()));\r
1083                                         getStartEndDateTime(r);\r
1084                                         \r
1085                                         r.setTitle(CommonUtils.unEscape(mb.group(6)));\r
1086                                         r.setTitlePop(TraceProgram.replacePop(r.getTitle()));\r
1087                                         \r
1088                                         r.setDetail(CommonUtils.unEscape(mb.group(7)).replaceAll("<BR>", ""));\r
1089                                 }\r
1090                         }\r
1091                 }\r
1092                 catch ( Exception e ) {\r
1093                         e.printStackTrace();\r
1094                 }\r
1095                 \r
1096                 // (1-1)プリセット\r
1097                 setTextPresetID(r, getSelectedSetting("presetID",res));\r
1098                 \r
1099                 // (1-3)録画モード\r
1100                 {\r
1101                         String rec_mode = getSelectedSetting("recMode",res);\r
1102                         if ( rec_mode.equals(ITEM_REC_MODE_DISABLE) ) {\r
1103                                 // "無効"は「予約実行」で扱うので\r
1104                                 r.setExec(false);\r
1105                                 setTextRecMode(r,getListRecMode().get(0).getText());\r
1106                                 // チューナー不足警告(リスト取得時に立ててるので落とす)\r
1107                                 r.setTunershort(false);\r
1108                         }\r
1109                         else {\r
1110                                 setTextRecMode(r,rec_mode);\r
1111                         }\r
1112                 }\r
1113                 \r
1114                 // (1-4)エンコーダ\r
1115                 setTextTunerID(r, getSelectedSetting("tunerID",res));\r
1116                 \r
1117                 // (1-6)録画後動作\r
1118                 setTextSuspendMode(r, getSelectedSetting("suspendMode",res));\r
1119                 \r
1120                 // (1-10)追従\r
1121                 r.setPursues(ITEM_YES.equals(getSelectedSetting("tuijyuuFlag",res)));\r
1122                 \r
1123                 // (1-11)ぴったり\r
1124                 setTextPittariFlag(r, getSelectedSetting("pittariFlag",res));\r
1125                 \r
1126                 // (1-12)録画優先度\r
1127                 setTextPriority(r, getSelectedSetting("priority",res));\r
1128                 \r
1129                 // (1-13)連続録画動作\r
1130                 if ( getCheckedSetting("continueRecFlag", res) != null ) {\r
1131                         setTextContinueRecFlag(r, ITEM_YES);\r
1132                 }\r
1133                 else {\r
1134                         setTextContinueRecFlag(r, ITEM_NO);\r
1135                 }\r
1136                 \r
1137                 // (1-14)復帰後再起動\r
1138                 if ( getCheckedSetting("rebootFlag", res) != null ) {\r
1139                         setTextRebootFlag(r, ITEM_YES);\r
1140                 }\r
1141                 else {\r
1142                         setTextRebootFlag(r, ITEM_NO);\r
1143                 }\r
1144                 \r
1145                 // (1-15) 指定サービス対象データ\r
1146                 if ( getCheckedSetting("serviceMode", res) != null ) {\r
1147                         setTextServiceMode(r, ITEM_SERVMOCE_DEFAULT);\r
1148                 }\r
1149                 else {\r
1150                         boolean b1 = "0".equals(getCheckedSetting("serviceMode_1", res));\r
1151                         boolean b2 = "0".equals(getCheckedSetting("serviceMode_2", res));\r
1152                         if ( b1 && b2 ) {\r
1153                                 setTextServiceMode(r, ITEM_SERVMOCE_SUBTCARO);\r
1154                         }\r
1155                         else if ( b1 ) {\r
1156                                 setTextServiceMode(r, ITEM_SERVMOCE_SUBT);\r
1157                         }\r
1158                         else if ( b2 ) {\r
1159                                 setTextServiceMode(r, ITEM_SERVMOCE_CARO);\r
1160                         }\r
1161                         else {\r
1162                                 setTextServiceMode(r, ITEM_SERVMOCE_NONE);\r
1163                         }\r
1164                 }\r
1165                 \r
1166                 // (1-16) 録画マージン\r
1167                 {\r
1168                         if ( getCheckedSetting("useDefMargineFlag", res) != null ) {\r
1169                                 setTextStartMargine(r, ITEM_MARGINE_DEFAULT);\r
1170                                 setTextEndMargine(r, ITEM_MARGINE_DEFAULT);\r
1171                         }\r
1172                         else {\r
1173                                 setTextStartMargine(r, getEditedSetting("startMargine", res));\r
1174                                 setTextEndMargine(r, getEditedSetting("endMargine", res));\r
1175                         }\r
1176                 }\r
1177                 \r
1178                 // (1-17) 別ファイルに同時出力する\r
1179                 if ( getCheckedSetting("partialRecFlag", res) != null ) {\r
1180                         setTextPartialRecFlag(r, ITEM_YES);\r
1181                 }\r
1182                 else {\r
1183                         setTextPartialRecFlag(r, ITEM_NO);\r
1184                 }\r
1185                 \r
1186                 String batFilePath = null;\r
1187                 ArrayList<String> rRecFolder = new ArrayList<String>();\r
1188                 ArrayList<String> rWritePlugIn = new ArrayList<String>();\r
1189                 ArrayList<String> rRecNamePlugIn = new ArrayList<String>();\r
1190                 ArrayList<String> pRecFolder = new ArrayList<String>();\r
1191                 ArrayList<String> pWritePlugIn = new ArrayList<String>();\r
1192                 ArrayList<String> pRecNamePlugIn = new ArrayList<String>();\r
1193                 \r
1194                 // 録画後実行bat\r
1195                 mb = Pattern.compile("録画後実行bat.*?:\\s*(.*?)<BR>",Pattern.DOTALL).matcher(d[1]);\r
1196                 if ( mb.find() ) {\r
1197                         batFilePath = mb.group(1);\r
1198                 }\r
1199                 \r
1200                 // オプショナル\r
1201                 {\r
1202                         // 録画フォルダ等\r
1203                         Matcher mc = Pattern.compile("録画フォルダ.*?(<TABLE.*?</TABLE>)\\s*<input type=hidden name=\"recFolderCount\" value=\"(\\d+?)\">",Pattern.DOTALL).matcher(d[1]);\r
1204                         if ( ! mc.find() ) {\r
1205                                 errmsg = "情報が見つかりません:"+RETVAL_KEY_RECFOLDERCOUNT;\r
1206                         }\r
1207                         else {\r
1208                                 r.getHidden_params().put(RETVAL_KEY_RECFOLDERCOUNT, mc.group(2));\r
1209                                 \r
1210                                 Matcher md = Pattern.compile("<TR>(.*?)</TR>",Pattern.DOTALL).matcher(mc.group(1));\r
1211                                 int idx = 0;\r
1212                                 while ( md.find() ) {\r
1213                                         if ( idx++ == 0 ) {\r
1214                                                 continue;\r
1215                                         }\r
1216                                         Matcher me = Pattern.compile("<TD>(.*?)</TD>",Pattern.DOTALL).matcher(md.group(1));\r
1217                                         for ( int i=0; i<3 && me.find(); i++ ) {\r
1218                                                 switch (i) {\r
1219                                                 case 0:\r
1220                                                         rRecFolder.add(me.group(1));\r
1221                                                         break;\r
1222                                                 case 1:\r
1223                                                         rWritePlugIn.add(me.group(1));\r
1224                                                         break;\r
1225                                                 case 2:\r
1226                                                         rRecNamePlugIn.add(me.group(1));\r
1227                                                         break;\r
1228                                                 }\r
1229                                         }\r
1230                                 }\r
1231                         }\r
1232                         \r
1233                         // 録画フォルダ等(ワンセグ)\r
1234                         mc = Pattern.compile("partialRecFlag.*?(<TABLE.*?</TABLE>)\\s*<input type=hidden name=\"partialFolderCount\" value=\"(\\d+?)\">",Pattern.DOTALL).matcher(d[1]);\r
1235                         if ( ! mc.find() ) {\r
1236                                 errmsg = "情報が見つかりません:"+RETVAL_KEY_PARTIALFOLDERCOUNT;\r
1237                         }\r
1238                         else {\r
1239                                 r.getHidden_params().put(RETVAL_KEY_PARTIALFOLDERCOUNT, mc.group(2));\r
1240                                 \r
1241                                 \r
1242                                 Matcher md = Pattern.compile("<TR>(.*?)</TR>",Pattern.DOTALL).matcher(mc.group(1));\r
1243                                 int idx = 0;\r
1244                                 while ( md.find() ) {\r
1245                                         if ( idx++ == 0 ) {\r
1246                                                 continue;\r
1247                                         }\r
1248                                         Matcher me = Pattern.compile("<TD>(.*?)</TD>",Pattern.DOTALL).matcher(md.group(1));\r
1249                                         for ( int i=0; i<3 && me.find(); i++ ) {\r
1250                                                 switch (i) {\r
1251                                                 case 0:\r
1252                                                         pRecFolder.add(me.group(1));\r
1253                                                         break;\r
1254                                                 case 1:\r
1255                                                         pWritePlugIn.add(me.group(1));\r
1256                                                         break;\r
1257                                                 case 2:\r
1258                                                         pRecNamePlugIn.add(me.group(1));\r
1259                                                         break;\r
1260                                                 }\r
1261                                         }\r
1262                                 }\r
1263                         }\r
1264                 }\r
1265                 \r
1266                 {\r
1267                         StringBuilder dt = new StringBuilder("■予約状況:");\r
1268                         if ( r.getContentId() != null ) {\r
1269                                 dt.append("EPG予約(自動手動不明→予約一覧再取得を行ってください)");\r
1270                         }\r
1271                         else {\r
1272                                 dt.append("プログラム予約");\r
1273                         }\r
1274                         dt.append("\n");\r
1275                         r.setDetail(dt.toString());\r
1276                 }\r
1277                 \r
1278                 if ( batFilePath != null && batFilePath.length() > 0 ) {\r
1279                         StringBuilder dt = new StringBuilder(r.getDetail());\r
1280                         dt.append("■録画後実行bat:");\r
1281                         dt.append(batFilePath);\r
1282                         dt.append("\n");\r
1283                         r.setDetail(dt.toString());\r
1284                 }\r
1285                 \r
1286                 if ( rRecFolder.size() > 0 ) {\r
1287                         StringBuilder dt = new StringBuilder(r.getDetail());\r
1288                         StringBuilder rf = new StringBuilder();\r
1289                         StringBuilder wp = new StringBuilder();\r
1290                         StringBuilder rp = new StringBuilder();\r
1291                         for ( int i=0; i<rRecFolder.size(); i++ ) {\r
1292                                 dt.append("■録画フォルダ・出力PlugIn・ファイル名PlugIn(");\r
1293                                 dt.append(String.valueOf(i+1));\r
1294                                 dt.append("):");\r
1295                                 dt.append(rRecFolder.get(i));\r
1296                                 dt.append(" / ");\r
1297                                 dt.append(rWritePlugIn.get(i));\r
1298                                 dt.append(" / ");\r
1299                                 dt.append(rRecNamePlugIn.get(i));\r
1300                                 dt.append("\n");\r
1301                                 \r
1302                                 rf.append(rRecFolder.get(i));\r
1303                                 rf.append("\t");\r
1304                                 \r
1305                                 wp.append(rWritePlugIn.get(i));\r
1306                                 wp.append("\t");\r
1307                                 \r
1308                                 rp.append(rRecNamePlugIn.get(i));\r
1309                                 rp.append("\t");\r
1310                         }\r
1311                         r.setDetail(dt.toString());\r
1312                         r.getHidden_params().put(RETVAL_KEY_R_RECFOLDER, rf.toString());\r
1313                         r.getHidden_params().put(RETVAL_KEY_R_WRITEPLUGIN, wp.toString());\r
1314                         r.getHidden_params().put(RETVAL_KEY_R_RECNAMEPLUGIN, rp.toString());\r
1315                 }\r
1316                 \r
1317                 if ( pRecFolder.size() > 0 ) {\r
1318                         StringBuilder dt = new StringBuilder(r.getDetail());\r
1319                         StringBuilder rf = new StringBuilder();\r
1320                         StringBuilder wp = new StringBuilder();\r
1321                         StringBuilder rp = new StringBuilder();\r
1322                         for ( int i=0; i<rRecFolder.size(); i++ ) {\r
1323                                 dt.append("■[1SEG] 録画フォルダ・出力PlugIn・ファイル名PlugIn(");\r
1324                                 dt.append(String.valueOf(i+1));\r
1325                                 dt.append("):");\r
1326                                 dt.append(pRecFolder.get(i));\r
1327                                 dt.append(" / ");\r
1328                                 dt.append(pWritePlugIn.get(i));\r
1329                                 dt.append(" / ");\r
1330                                 dt.append(pRecNamePlugIn.get(i));\r
1331                                 dt.append("\n");\r
1332                                 \r
1333                                 rf.append(pRecFolder.get(i));\r
1334                                 rf.append("\t");\r
1335                                 \r
1336                                 wp.append(pWritePlugIn.get(i));\r
1337                                 wp.append("\t");\r
1338                                 \r
1339                                 rp.append(pRecNamePlugIn.get(i));\r
1340                                 rp.append("\t");\r
1341                         }\r
1342                         r.setDetail(dt.toString());\r
1343                         r.getHidden_params().put(RETVAL_KEY_P_RECFOLDER, rf.toString());\r
1344                         r.getHidden_params().put(RETVAL_KEY_P_WRITEPLUGIN, wp.toString());\r
1345                         r.getHidden_params().put(RETVAL_KEY_P_RECNAMEPLUGIN, rp.toString());\r
1346                 }\r
1347                 \r
1348                 // 番組ID\r
1349                 if ( r.getContentId() != null ) {\r
1350                         StringBuilder dt = new StringBuilder(r.getDetail());\r
1351                         dt.append("■番組ID:");\r
1352                         dt.append(ContentIdEDCB.stripMark(r.getContentId()));\r
1353                         dt.append("\n");\r
1354                         r.setDetail(dt.toString());\r
1355                 }\r
1356 \r
1357                 return true;\r
1358         }\r
1359         private String getSelectedSetting(String key, String res) {\r
1360                 Matcher mb = Pattern.compile("<select name=\""+key+"\">[\\s\\S]*?<option value=\"([^\"]+?)\"\\s*selected>(.+?)\n").matcher(res);\r
1361                 if (mb.find()) {\r
1362                         return mb.group(2);\r
1363                 }\r
1364                 return null;\r
1365         }\r
1366         private String getEditedSetting(String key, String res) {\r
1367                 Matcher mb = Pattern.compile("<input type=text name=\""+key+"\" value=\"([^\"]+?)\">").matcher(res);\r
1368                 if (mb.find()) {\r
1369                         return mb.group(1);\r
1370                 }\r
1371                 return null;\r
1372         }\r
1373         private String getCheckedSetting(String key, String res) {\r
1374                 Matcher mb = Pattern.compile("<input type=checkbox name=\""+key+"\" value=\"([^\"]+?)\" checked>").matcher(res);\r
1375                 if (mb.find()) {\r
1376                         return mb.group(1);\r
1377                 }\r
1378                 return null;\r
1379         }\r
1380         \r
1381         /**\r
1382          *      録画結果一覧を取得する\r
1383          */\r
1384         \r
1385         private boolean GetRdRecordedList(ArrayList<RecordedInfo> newRecordedList) {\r
1386                 \r
1387                 String critDate = null;\r
1388                 if ( newRecordedList.size() > 0 ) {\r
1389                         // 最新の情報の前日分までチェックする\r
1390                         GregorianCalendar cal = CommonUtils.getCalendar(newRecordedList.get(0).getDate());\r
1391                         cal.add(Calendar.DATE, -1);\r
1392                         critDate = CommonUtils.getDate(cal);\r
1393                 }\r
1394                 else {\r
1395                         // 既存情報が無ければ上限まで\r
1396                         critDate = CommonUtils.getDate(CommonUtils.getCalendar(-86400*getRecordedSaveScope()));\r
1397                 }\r
1398                 \r
1399                 if (getDebug()) System.out.println(DBGID+"録画結果の取り込みはここまで: "+critDate);\r
1400                 \r
1401                 // RDから予約一覧を取り出す\r
1402                 String response="";\r
1403                 {\r
1404                         reportProgress("録画結果一覧を取得します.(1)");\r
1405                         String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/recinfo.html",null);\r
1406                         response = d[1];\r
1407                         \r
1408                         if (response == null) {\r
1409                                 errmsg = "レコーダーが反応しません";\r
1410                                 return false;\r
1411                         }\r
1412                 }\r
1413 \r
1414                 // 30件を超えるとページが増える\r
1415                 int maxpage = 0;\r
1416                 Matcher ma = Pattern.compile("\"recinfo.html\\?page=(\\d+)\"").matcher(response);\r
1417                 while ( ma.find() ) {\r
1418                         int page = Integer.valueOf(ma.group(1));\r
1419                         if ( maxpage < page ) {\r
1420                                 maxpage = page;\r
1421                         }\r
1422                 }\r
1423                 \r
1424                 for ( int page = 0; page<=maxpage; page++ ) {\r
1425                         if ( page > 0 ) {\r
1426                                 reportProgress(String.format("録画結果一覧を取得します.(%d)",page+1));\r
1427                                 String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/recinfo.html?page="+page,null,thisEncoding);\r
1428                                 response = d[1];\r
1429                         }\r
1430                         if ( GetRdRecordedListSub(newRecordedList, response, critDate) <= 0) {\r
1431                                 // おわったぽ\r
1432                                 break;\r
1433                         }\r
1434                 }\r
1435 \r
1436                 return true;\r
1437         }\r
1438         \r
1439         private int GetRdRecordedListSub(ArrayList<RecordedInfo> newRecordedList, String response, String critDate) {\r
1440                 \r
1441                 int cnt = 0;\r
1442                 \r
1443                 //\r
1444                 Matcher mc = Pattern.compile("<TABLE BORDER=\"1\">(.+?)</TABLE>",Pattern.DOTALL).matcher(response);\r
1445                 if (mc.find()) {\r
1446                         Matcher ma = Pattern.compile("<TR( BGCOLOR=#......)?><TD>(\\d\\d\\d\\d/\\d\\d/\\d\\d)\\(.\\) (\\d\\d):(\\d\\d)~(\\d\\d):(\\d\\d)</TD><TD>(.+?)</TD>.*?<A HREF=\"recinfodesc\\.html\\?id=(\\d+?)\">詳細</A></TD></TR>\\s*?<TR( BGCOLOR=#......)?><TD COLSPAN=\"2\">(.*?)</TD></TR>\\s*?<TR( BGCOLOR=#......)?><TD COLSPAN=\"2\">(.*?)</TD></TR>",Pattern.DOTALL).matcher(mc.group(1));\r
1447                         while ( ma.find() ) {\r
1448                                 \r
1449                                 // 日付を調べる\r
1450                                 GregorianCalendar cal = CommonUtils.getCalendar(ma.group(2));\r
1451                                 String date = CommonUtils.getDate(cal);\r
1452                                 \r
1453                                 // 既存の情報に追いついたので取得終了\r
1454                                 if ( date.compareTo(critDate) < 0 ) {\r
1455                                         return -1;\r
1456                                 }\r
1457                                 \r
1458                                 // 個々のデータを取り出す\r
1459                                 RecordedInfo entry = new RecordedInfo();\r
1460 \r
1461                                 entry.setDate(date);\r
1462                                 \r
1463                                 entry.setAhh(ma.group(3));\r
1464                                 entry.setAmm(ma.group(4));\r
1465                                 entry.setZhh(ma.group(5));\r
1466                                 entry.setZmm(ma.group(6));\r
1467                                 \r
1468                                 long lenL = CommonUtils.getCompareDateTime(entry.getDate()+" "+entry.getZhh()+":"+entry.getZmm(), entry.getDate()+" "+entry.getAhh()+":"+entry.getAmm());\r
1469                                 if ( lenL < 0 ) {\r
1470                                         lenL += 86400000;\r
1471                                 }\r
1472                                 int len =  (int) (lenL / 60000L);\r
1473                                 entry.setLength(len);\r
1474                                 \r
1475                                 // 放送局(仮)\r
1476                                 String recChName = ma.group(7);\r
1477                                 String chid = cc.getCH_REC2CODE(recChName);\r
1478                                 if ( chid == null ) {\r
1479                                         // 難視聴対策局対策\r
1480                                         String nan = TEXT_NANSHICHO_HEADER+recChName;\r
1481                                         chid = cc.getCH_REC2CODE(nan);\r
1482                                         if ( chid != null ) {\r
1483                                                 recChName = nan;\r
1484                                         }\r
1485                                 }\r
1486                                 \r
1487                                 if ( chid == null ) {\r
1488                                         // CHコードにできなければ、HTMLから取得した放送局名をそのまま使う\r
1489                                         entry.setChannel(null);\r
1490                                         entry.setCh_name(recChName);\r
1491                                 }\r
1492                                 else {\r
1493                                         entry.setChannel(chid);\r
1494                                         String ch_name = cc.getCH_CODE2WEB(chid);\r
1495                                         if ( ch_name == null ) {\r
1496                                                 // CHコード設定がうまくないようですよ?\r
1497                                                 entry.setCh_name(ma.group(7));\r
1498                                         }\r
1499                                         else {\r
1500                                                 entry.setCh_name(ch_name);\r
1501                                         }\r
1502                                 }\r
1503                                 \r
1504                                 entry.setCh_orig(recChName);\r
1505                                 \r
1506                                 // ID\r
1507                                 entry.setId(ma.group(8));\r
1508                                 \r
1509                                 // 予約名\r
1510                                 entry.setTitle(CommonUtils.unEscape(ma.group(10)).replaceAll("<BR>", ""));\r
1511                                 \r
1512                                 // 録画結果\r
1513                                 entry.setResult(ma.group(12));\r
1514                                 entry.setSucceeded(entry.getResult().matches("^(録画終了|開始時間が変更されました)$"));\r
1515                                 \r
1516                                 // その他\r
1517                                 \r
1518                                 addRecorded(newRecordedList, entry);\r
1519                                 \r
1520                                 ++cnt;\r
1521                         }\r
1522                 }\r
1523                 \r
1524                 return cnt;\r
1525         }\r
1526 \r
1527         private boolean GetRdRecordedListDetailAll(ArrayList<RecordedInfo> newRecordedList) {\r
1528                 // 詳細情報を取得する\r
1529                 int i=0;\r
1530                 for ( RecordedInfo entry : newRecordedList ) {\r
1531                         \r
1532                         if ( entry.getId() == null ) {\r
1533                                 // 過去ログかな…?\r
1534                                 continue;\r
1535                         }\r
1536                         \r
1537                         ++i;\r
1538                         \r
1539                         reportProgress("+録画結果詳細を取得します("+i+")");\r
1540                         \r
1541                         String response="";\r
1542                         {\r
1543                                 String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/recinfodesc.html?id="+entry.getId(),null);\r
1544                                 response = d[1];\r
1545                                 \r
1546                                 if (response == null) {\r
1547                                         errmsg = "レコーダーが反応しません";\r
1548                                         return false;\r
1549                                 }\r
1550                         }\r
1551                         \r
1552                         Matcher ma = Pattern.compile("ドロップ:(\\d+)", Pattern.DOTALL).matcher(response);\r
1553                         if ( ma.find() ) {\r
1554                                 entry.setDrop(Integer.valueOf(ma.group(1)));\r
1555                         }\r
1556                         \r
1557                         ma = Pattern.compile("Drop:\\s*(\\d+)\\s*Scramble:\\s*(\\d+)\\s*MPEG2", Pattern.DOTALL).matcher(response);\r
1558                         while ( ma.find() ) {\r
1559                                 entry.setDrop_mpeg(entry.getDrop_mpeg()+Integer.valueOf(ma.group(1)));\r
1560                         }\r
1561                         \r
1562                         ma = Pattern.compile("(<HR>番組情報<HR>.*</PRE>)", Pattern.DOTALL).matcher(response);\r
1563                         if ( ma.find() ) {\r
1564                                 entry.setDetail(CommonUtils.unEscape(ma.group(1).replaceAll("<BR>", "").replaceAll("</?PRE>", "").replaceAll("<HR>", "====").replaceAll("\n\n+", "\n\n")/*.replaceFirst("^([\\s\\S]*?)(====エラーログ====[\\s\\S]*?)$","$2\n\n$1")*/));\r
1565                         }\r
1566                         \r
1567                         // 放送局(訂正)\r
1568                         Matcher md = Pattern.compile("OriginalNetworkID:(\\d+).*?TransportStreamID:(\\d+).*?ServiceID:(\\d+)",Pattern.DOTALL).matcher(response);\r
1569                         if ( md.find() ) {\r
1570                                 // 詳細情報からCHコードが取得できるなら\r
1571                                 String chid = String.valueOf(Long.decode("0x"+ContentIdEDCB.getChId(Integer.valueOf(md.group(1)),Integer.valueOf(md.group(2)),Integer.valueOf(md.group(3)))));\r
1572                                 entry.setChannel(chid);\r
1573                                 String ch_name = cc.getCH_CODE2WEB(chid);\r
1574                                 if ( ch_name != null ) {\r
1575                                         entry.setCh_name(ch_name);\r
1576                                 }\r
1577                         }\r
1578                         \r
1579 \r
1580                 }\r
1581                 return true;\r
1582         }\r
1583 \r
1584         \r
1585         /*******************************************************************************\r
1586          * 新規予約\r
1587          ******************************************************************************/\r
1588         \r
1589         @Override\r
1590         public boolean PostRdEntry(ReserveList reqr)\r
1591         {\r
1592                 \r
1593                 ArrayList<ReserveList> tmprl = getReserves();\r
1594                 \r
1595                 boolean b = _PostRdEntry(reqr);\r
1596                 \r
1597                 // 予約一覧が更新されていたら、本体から取得できない情報は引き継ぐ\r
1598                 if ( getReserves() != tmprl ) {\r
1599                         copyAttributesAllList(tmprl, getReserves());\r
1600                 }\r
1601                 \r
1602                 // 成功しても失敗してもキャッシュが更新されている可能性があるので保存し直す\r
1603                 ReservesToFile(getReserves(), rsvedFile);\r
1604                 setRecordedFlag();\r
1605                 \r
1606                 return b;\r
1607         }\r
1608         private boolean _PostRdEntry(ReserveList reqr) \r
1609         {\r
1610                 //\r
1611                 System.out.println("Run: PostRdEntry("+reqr.getTitle()+")");\r
1612                 \r
1613                 errmsg = "";\r
1614 \r
1615                 // 放送局と日付のチェック\r
1616                 if ( ! PrePostCheck(reqr) ) {\r
1617                         return(false);\r
1618                 }\r
1619                 \r
1620                 // プリセット\r
1621                 if ( reqr.getRec_audio().equals(ITEM_PRESETID_REG) ) {\r
1622                         errmsg = "新規予約では次の指定はできません:プリセット="+ITEM_PRESETID_REG;\r
1623                         return false;\r
1624                 }\r
1625                 \r
1626                 // おまじない\r
1627                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
1628                 \r
1629                 String header;\r
1630                 String response;\r
1631                 \r
1632                 int onid = -1;\r
1633                 int tsid = -1;\r
1634                 int sid = -1;\r
1635                 int evid = -1;\r
1636                 \r
1637                 boolean rec_type_epg = true;\r
1638                 if ( getTextRecType(reqr) != null && getTextRecType(reqr).equals(ITEM_REC_TYPE_EPG) ) {\r
1639                         if ( ContentIdEDCB.isValid(reqr.getContentId()) ) {\r
1640                                 ContentIdEDCB.decodeContentId(reqr.getContentId());\r
1641                                 onid = ContentIdEDCB.getOnId();\r
1642                                 tsid = ContentIdEDCB.getTSId();\r
1643                                 sid = ContentIdEDCB.getSId();\r
1644                                 evid = ContentIdEDCB.getEvId();\r
1645                         }\r
1646                         else if ( ContentIdDIMORA.isValid(reqr.getContentId()) ) {\r
1647                                 ContentIdDIMORA.decodeContentId(reqr.getContentId());\r
1648                                 evid = ContentIdDIMORA.getEvId();\r
1649                                 // 後続処理あり\r
1650                         }\r
1651                         else if ( ContentIdREGZA.isValid(reqr.getContentId()) ) {\r
1652                                 ContentIdREGZA.decodeContentId(reqr.getContentId());\r
1653                                 evid = ContentIdREGZA.getEvId();\r
1654                                 // 後続処理あり\r
1655                         }\r
1656                         else {\r
1657                                 errmsg = "番組表に予約IDがないためEPG予約は利用できません。EDCB番組表を利用するかプログラム予約を行ってください。";\r
1658                                 return false;\r
1659                         }\r
1660                         \r
1661                         if ( evid != -1 && onid == -1 ) {\r
1662                                 // Dimora、REGZA形式の場合 onid と tsid が取得できないので自前の情報で補完\r
1663                                 ContentIdEDCB.decodeChId(ContentIdEDCB.getChId(cc.getCH_WEB2CODE(reqr.getCh_name())));\r
1664                                 onid = ContentIdEDCB.getOnId();\r
1665                                 tsid = ContentIdEDCB.getTSId();\r
1666                                 sid = ContentIdEDCB.getSId();\r
1667                                 // EDCB形式で置き換え\r
1668                                 reqr.setContentId(ContentIdEDCB.getContentId(onid, tsid, sid, evid));\r
1669                         }\r
1670                 }\r
1671                 else {\r
1672                         rec_type_epg = false;\r
1673                 }\r
1674                 \r
1675                 ReserveList newr = null;\r
1676                 \r
1677                 // 予約IDが含まれていたら削る\r
1678                 reqr.setId("");\r
1679                 \r
1680                 /*\r
1681                  *  EPG予約\r
1682                  */\r
1683                 if ( rec_type_epg ) {\r
1684                         \r
1685                         int cntMax = 3;\r
1686                         int cnt = 1;\r
1687                         \r
1688                         \r
1689                         // 番組情報ページを開く\r
1690                         {\r
1691                                 reportProgress(String.format("EPG予約を実行します(%d/%d).",cnt++,cntMax));\r
1692                                 \r
1693                                 ReserveList tmpr = new ReserveList();\r
1694                                 tmpr.setContentId(reqr.getContentId());\r
1695                                 setTextPresetID(tmpr, getTextPresetID(reqr));\r
1696                                 if ( ! GetRdReservedDetailByContentId(tmpr,0) ) {\r
1697                                         errmsg = "予約ページが開けません。";\r
1698                                         return(false);\r
1699                                 }\r
1700                                 \r
1701                                 if ( tmpr.getId() != null && tmpr.getId().length() > 0 ) {\r
1702                                         System.out.println("重複予約が実行されます.");\r
1703                                 }\r
1704                         }\r
1705                         \r
1706                         // 予約登録を実行する\r
1707                         {               \r
1708                                 reportProgress(String.format("追加を実行します(%d/%d).",cnt++,cntMax));\r
1709                                 \r
1710                                 String pstr = genPoststrEPGB(reqr);\r
1711                                 String uri = "http://"+getIPAddr()+":"+getPortNo()+"/"+String.format("reserveadd.html?onid=%d&tsid=%d&sid=%d&evid=%d",onid,tsid,sid,evid);;\r
1712                                 \r
1713                                 System.err.println("URL: "+uri);\r
1714                                 \r
1715                                 header = response = null;\r
1716                                 for (int i=0; i<retryMax; i++) {\r
1717                                         String[] d = reqPOST(uri, pstr, null);\r
1718                                         header = d[0];\r
1719                                         response = d[1];\r
1720                                         if ( header != null && response == null ) {\r
1721                                                 reportProgress("コネクションがリセットされました。リトライします。");\r
1722                                                 CommonUtils.milSleep(1000);\r
1723                                         }\r
1724                                         else {\r
1725                                                 break;\r
1726                                         }\r
1727                                 }\r
1728                                 if ( header == null || response == null ) {\r
1729                                         errmsg = "レコーダーが反応しません。";\r
1730                                         return(false);\r
1731                                 }\r
1732                         }\r
1733                         \r
1734                         // EPG予約の場合はすぐわかる(はずだった→重複予約だとわからない)\r
1735                         {\r
1736                                 reportProgress(String.format("新しい予約IDを取得します(%d/%d).",cnt++,cntMax));\r
1737                                 \r
1738                                 newr = getRsvOnEdcbTR(reqr);\r
1739                                 if ( newr == null ) {\r
1740                                         return(false);\r
1741                                 }\r
1742                                 \r
1743                                 // 本体から取得できない情報は引き継ぐ\r
1744                                 copyAttributesMethod(reqr, newr);\r
1745                                 \r
1746                                 // 一発ヒットしたものはキャッシュ上にないので載せる\r
1747                                 if ( ! getReserves().contains(newr) ) {\r
1748                                         getReserves().add(newr);\r
1749                                 }\r
1750                                 \r
1751                                 reportProgress("+新しい予約ID: "+newr.getId());\r
1752                                 \r
1753                                 if ( isModified(reqr, newr) ) {\r
1754                                         errmsg = "EDCB番組表からの情報で内容が変更されました: "+newr.getStartDateTime()+"~"+newr.getZhh()+":"+newr.getZmm()+" "+newr.getTitle();\r
1755                                 }\r
1756                         }\r
1757                 }\r
1758                 \r
1759                 /*\r
1760                  * プログラム予約 \r
1761                  */\r
1762                 else {\r
1763                         \r
1764                         int cntMax = 3;\r
1765                         int cnt = 1;\r
1766                         \r
1767                         // プログラム予約の制限のチェック\r
1768                         if ( ! PreProgResCheck(reqr) ) {\r
1769                                 return(false);\r
1770                         }\r
1771                         \r
1772                         // 番組IDが含まれていたら削る\r
1773                         reqr.setContentId(null);\r
1774                         \r
1775                         // 予約情報の一部を確定する\r
1776                         {               \r
1777                                 reportProgress(String.format("プログラム予約を実行します(%d/%d).",cnt++,cntMax));\r
1778                                 \r
1779                                 String pstr = genPoststrDTA(reqr);\r
1780                                 String uri = "http://"+getIPAddr()+":"+getPortNo()+"/addprogres.html";\r
1781                                 \r
1782                                 System.err.println("URL: "+uri+"?"+pstr);\r
1783                                 \r
1784                                 header = response = null;\r
1785                                 for (int i=0; i<retryMax; i++) {\r
1786                                         String[] d = reqPOST(uri, pstr, null);\r
1787                                         header = d[0];\r
1788                                         response = d[1];\r
1789                                         if ( header != null && response == null ) {\r
1790                                                 reportProgress("コネクションがリセットされました。リトライします。");\r
1791                                                 CommonUtils.milSleep(1000);\r
1792                                         }\r
1793                                         else {\r
1794                                                 break;\r
1795                                         }\r
1796                                 }\r
1797                                 if ( header == null || response == null ) {\r
1798                                         errmsg = "レコーダーが反応しません。";\r
1799                                         return(false);\r
1800                                 }\r
1801 \r
1802                                 Matcher ma = Pattern.compile("<form method=\"POST\" action=\"reservepgadd.html\">").matcher(response);\r
1803                                 if ( ! ma.find() ) {\r
1804                                         errmsg = "予約に失敗しました。";\r
1805                                         return(false);\r
1806                                 }\r
1807                                 \r
1808                                 ma = Pattern.compile("<input type=hidden name=\"recFolderCount\" value=\"(\\d+?)\">").matcher(response);\r
1809                                 if ( ! ma.find() ) {\r
1810                                         errmsg = "予約に失敗しました。";\r
1811                                         return(false);\r
1812                                 }\r
1813                                 reqr.getHidden_params().put(RETVAL_KEY_RECFOLDERCOUNT, ma.group(1));\r
1814                                 \r
1815                                 ma = Pattern.compile("<input type=hidden name=\"partialFolderCount\" value=\"(\\d+?)\">").matcher(response);\r
1816                                 if ( ! ma.find() ) {\r
1817                                         errmsg = "予約に失敗しました。";\r
1818                                         return(false);\r
1819                                 }\r
1820                                 reqr.getHidden_params().put(RETVAL_KEY_PARTIALFOLDERCOUNT, ma.group(1));\r
1821                         }\r
1822                         \r
1823                         // 予約登録を実行する\r
1824                         {               \r
1825                                 reportProgress(String.format("追加を実行します(%d/%d).",cnt++,cntMax));\r
1826                                 \r
1827                                 String pstr = genPoststrDTB(reqr);\r
1828                                 String uri = "http://"+getIPAddr()+":"+getPortNo()+"/reservepgadd.html";\r
1829                                 \r
1830                                 System.err.println("URL: "+uri+"?"+pstr);\r
1831                                 \r
1832                                 header = response = null;\r
1833                                 for (int i=0; i<retryMax; i++) {\r
1834                                         String[] d = reqPOST(uri, pstr, null);\r
1835                                         header = d[0];\r
1836                                         response = d[1];\r
1837                                         if ( header != null && response == null ) {\r
1838                                                 reportProgress("コネクションがリセットされました。リトライします。");\r
1839                                                 CommonUtils.milSleep(1000);\r
1840                                         }\r
1841                                         else {\r
1842                                                 break;\r
1843                                         }\r
1844                                 }\r
1845                                 if ( header == null || response == null ) {\r
1846                                         errmsg = "レコーダーが反応しません。";\r
1847                                         return(false);\r
1848                                 }\r
1849                         }\r
1850                         \r
1851                         // EDCBに追加された予約IDを検索する ★EDCBは再起動すると予約IDが振り直しになるので必要!!\r
1852                         {\r
1853                                 reportProgress(String.format("新しい予約IDを番号を取得します(%d/%d).",cnt++,cntMax));\r
1854                                 \r
1855                                 reqr.setId(""); // 予約番号未定のためダミー\r
1856                                 newr = getRsvOnEdcbDT(reqr);\r
1857                                 if ( newr == null ) {\r
1858                                         errmsg = "予約IDがみつかりません。";\r
1859                                         return(false);\r
1860                                 }\r
1861                                 \r
1862                                 // 本体から取得できない情報は引き継ぐ\r
1863                                 copyAttributesMethod(reqr, newr);\r
1864 \r
1865                                 // 一発ヒットしたものはキャッシュ上にないので載せる\r
1866                                 if ( ! getReserves().contains(newr) ) {\r
1867                                         getReserves().add(newr);\r
1868                                 }\r
1869                                 \r
1870                                 reportProgress("+新しい予約ID: "+newr.getId());\r
1871                         }\r
1872                 }\r
1873                 \r
1874                 System.out.printf("\n<<< Message from RD >>> \"%s\"\n\n", "正常に登録できました。");\r
1875                 \r
1876                 return(true);\r
1877                 \r
1878                 // 長いよ!分割しる!!\r
1879         }\r
1880 \r
1881         \r
1882         /*******************************************************************************\r
1883          * 予約更新\r
1884          ******************************************************************************/\r
1885         \r
1886         /**\r
1887          * 予約を更新する(入口)\r
1888          */\r
1889         @Override\r
1890         public boolean UpdateRdEntry(ReserveList cacher, ReserveList reqr)\r
1891         {\r
1892                 ArrayList<ReserveList> tmprl = getReserves();\r
1893                 \r
1894                 boolean b = _UpdateRdEntry(cacher, reqr);\r
1895                 \r
1896                 // 予約一覧が更新されていたら、本体から取得できない情報は引き継ぐ\r
1897                 if ( getReserves() != tmprl ) {\r
1898                         copyAttributesAllList(tmprl, getReserves());\r
1899                 }\r
1900                 \r
1901                 // 成功しても失敗してもキャッシュが更新されている可能性があるので保存し直す\r
1902                 ReservesToFile(getReserves(), rsvedFile);\r
1903                 setRecordedFlag();\r
1904                 \r
1905                 return b;\r
1906         }\r
1907         \r
1908         /**\r
1909          * 予約を更新する(本体)\r
1910          */\r
1911         private boolean _UpdateRdEntry(ReserveList cacher, ReserveList reqr)\r
1912         {\r
1913                 //\r
1914                 System.out.println("Run: UpdateRdEntry()");\r
1915                 \r
1916                 errmsg = "";\r
1917                 \r
1918                 // おまじない\r
1919                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
1920                 \r
1921                 // 放送局と日付のチェック\r
1922                 if ( ! PrePostCheck(reqr) ) {\r
1923                         return(false);\r
1924                 }\r
1925                 \r
1926                 if ( ! getTextRecType(cacher).equals(getTextRecType(reqr)) ) {\r
1927                         errmsg = String.format("異なる予約方式への更新は行えません(%s->%s)",getTextRecType(cacher),getTextRecType(reqr));\r
1928                         return false;\r
1929                 }\r
1930                 \r
1931                 boolean rec_type_epg = true;\r
1932                 if ( getTextRecType(reqr) != null && getTextRecType(reqr).equals(ITEM_REC_TYPE_EPG) ) {\r
1933                         if ( ContentIdEDCB.isValid(reqr.getContentId()) ) {\r
1934                                 // 正しい番組IDのようですね\r
1935                         }\r
1936                         else {\r
1937                                 errmsg = "番組表に予約IDがないためEPG予約は利用できません。EDCB番組表を利用するかプログラム予約を行ってください。";\r
1938                                 return false;\r
1939                         }\r
1940                 }\r
1941                 else {\r
1942                         rec_type_epg = false;\r
1943                         // 番組IDが含まれていたら削る\r
1944                         reqr.setContentId(null);\r
1945                 }\r
1946                 \r
1947                 if ( rec_type_epg ) {\r
1948                         // EPG予約は普通に更新\r
1949                         if (getDebug()) System.err.println("[DEBUG] Update EPG RSV");\r
1950                         return UpdateRdEntryTR(cacher,reqr);\r
1951                 }\r
1952                 else {\r
1953                         \r
1954                         // プログラム予約の制限のチェック\r
1955                         if ( ! PreProgResCheck(reqr)) {\r
1956                                 return(false);\r
1957                         }\r
1958                         \r
1959                         // プログラム予約\r
1960                         if ( isEqualsDate(cacher, reqr) && cacher.getTitle().equals(reqr.getTitle()) ) {\r
1961                                 // 開始・終了日時とタイトルに変更がない場合は更新\r
1962                                 if (getDebug()) System.err.println("[DEBUG] Update PROG RSV");\r
1963                                 return UpdateRdEntryDT2(cacher,reqr);\r
1964                         }\r
1965                         else {\r
1966                                 // 開始・終了日時とタイトルに変更がある場合は削除して追加\r
1967                                 if (getDebug()) System.err.println("[DEBUG] Refresh PROG RSV");\r
1968                                 return UpdateRdEntryDT1(cacher,reqr);\r
1969                         }\r
1970                 }\r
1971         }\r
1972         \r
1973         /**\r
1974          * EPG予約を更新する\r
1975          */\r
1976         private boolean UpdateRdEntryTR(ReserveList cacher, ReserveList reqr) {\r
1977                 \r
1978                 // EDCBで更新する\r
1979                 int cnt = 1;\r
1980                 int cntMax = 2;\r
1981                 \r
1982                 ReserveList oldr = null;        // 本体にあった既存の予約情報\r
1983                 ReserveList newr = null;        // 更新後に取得しなおした新しい予約情報\r
1984                 \r
1985                 // 予約IDの検索\r
1986                 {\r
1987                         reportProgress(String.format("更新するEPG予約の予約IDを取得します(%d/%d).",cnt++,cntMax));\r
1988                         \r
1989                         // 予約IDを取得する\r
1990                         oldr = getRsvOnEdcbTR(cacher);\r
1991                         if ( oldr == null ) {\r
1992                                 return false;\r
1993                         }\r
1994                         \r
1995                         reportProgress("+更新される予約ID: "+oldr.getId());\r
1996                 }\r
1997                 \r
1998                 // 予約更新\r
1999                 {               \r
2000                         reportProgress(String.format("更新を実行します(%d/%d).",cnt++,cntMax));\r
2001                         \r
2002                         newr = _UpdateRdEntrySub(oldr, reqr);\r
2003                         if ( newr == null  ) {\r
2004                                 return false;\r
2005                         }\r
2006                         \r
2007                         // 本体から取得できない情報は引き継ぐ\r
2008                         copyAttributesMethod(reqr, newr);\r
2009                         \r
2010                         // 一発ヒットした場合は予約リストの更新が必要。再取得している場合は不要\r
2011                         int idx = getReserves().indexOf(cacher);\r
2012                         if ( idx >= 0 ) {\r
2013                                 getReserves().set(idx,newr);\r
2014                         }\r
2015                 }\r
2016                 \r
2017                 if ( isModified(cacher, newr) ) {\r
2018                         // ピンピンうるさいので実行OFFの予約の場合はだんまりで\r
2019                         errmsg = "EDCB番組表からの情報で内容が変更されました: "+newr.getStartDateTime()+"~"+newr.getZhh()+":"+newr.getZmm()+" "+newr.getTitle();\r
2020                 }\r
2021                 \r
2022                 return true;\r
2023         }\r
2024         \r
2025         /**\r
2026          * プログラム予約を更新する(開始・終了日時とタイトルに変更がない場合は更新)\r
2027          */\r
2028         private boolean UpdateRdEntryDT2(ReserveList cacher, ReserveList reqr) {\r
2029                 \r
2030                 // EDCBで更新する\r
2031                 int cnt = 1;\r
2032                 int cntMax = 2;\r
2033                 \r
2034                 ReserveList oldr = null;        // 本体にあった既存の予約情報\r
2035                 ReserveList newr = null;        // 更新後に取得しなおした新しい予約情報\r
2036                 \r
2037                 // EDCBの更新すべき予約IDを検索する ★EDCBは再起動すると予約IDが振り直しになるので必要!!\r
2038                 {\r
2039                         reportProgress(String.format("更新対象の予約を探します(%d/%d).",cnt++,cntMax));\r
2040                         \r
2041                         oldr = getRsvOnEdcbDT(cacher);\r
2042                         if ( oldr == null ) {\r
2043                                 errmsg = "予約一覧に更新対象が見つかりません。";\r
2044                                 return false;\r
2045                         }\r
2046                         \r
2047                         // 予約IDのみ更新\r
2048                         reportProgress("+更新される予約ID: "+oldr.getId());\r
2049                 }\r
2050                 \r
2051                 // 予約更新\r
2052                 {\r
2053                         reportProgress(String.format("プログラム予約を更新します(%d/%d).",cnt++,cntMax));\r
2054 \r
2055                         newr = _UpdateRdEntrySub(oldr, reqr);\r
2056                         if ( newr == null  ) {\r
2057                                 return false;\r
2058                         }\r
2059                         \r
2060                         // 本体から取得できない情報は引き継ぐ\r
2061                         copyAttributesMethod(reqr, newr);\r
2062                         \r
2063                         // 一発ヒットした場合は予約リストの更新が必要。再取得している場合は不要\r
2064                         int idx = getReserves().indexOf(cacher);\r
2065                         if ( idx >= 0 ) {\r
2066                                 getReserves().set(idx,newr);\r
2067                         }\r
2068                 }\r
2069                 \r
2070                 return true;\r
2071         }\r
2072         \r
2073         /**\r
2074          * プログラム予約を更新する(開始・終了日時とタイトルに変更がある場合は削除して追加)\r
2075          */\r
2076         private boolean UpdateRdEntryDT1(ReserveList cacher, ReserveList reqr) {\r
2077                 \r
2078                 reportProgress("プログラム予約を登録し直します.");\r
2079                 \r
2080                 // 削除して\r
2081                 if ( RemoveRdEntry(cacher.getId()) == null ) {\r
2082                         return(false);\r
2083                 }\r
2084                 \r
2085                 // 追加する\r
2086                 if ( ! PostRdEntry(reqr) ) {\r
2087                         errmsg += "予約が削除されたので登録しなおしてください。";\r
2088                 }\r
2089                 \r
2090                 return(true);\r
2091         }\r
2092 \r
2093         /**\r
2094          * 予約更新の共通部分\r
2095          */\r
2096         private ReserveList _UpdateRdEntrySub(ReserveList oldr, ReserveList reqr) {\r
2097                 \r
2098                 String pstr = genPoststrDTB(reqr);\r
2099                 String uri = "http://"+getIPAddr()+":"+getPortNo()+"/reservechg.html?id="+getRsvId(oldr.getId());\r
2100                 \r
2101                 System.err.println("URL: "+uri);\r
2102                 \r
2103                 String header = null;\r
2104                 String response = null;\r
2105                 for (int i=0; i<retryMax; i++) {\r
2106                         String[] d = reqPOST(uri, pstr, null);\r
2107                         header = d[0];\r
2108                         response = d[1];\r
2109                         if ( header != null && response == null ) {\r
2110                                 reportProgress("コネクションがリセットされました。リトライします。");\r
2111                                 CommonUtils.milSleep(1000);\r
2112                         }\r
2113                         else {\r
2114                                 break;\r
2115                         }\r
2116                 }\r
2117                 if ( header == null || response == null ) {\r
2118                         errmsg = "レコーダーが反応しません。";\r
2119                         return null;\r
2120                 }\r
2121                 if ( ! response.contains("予約を変更しました") ) {\r
2122                         errmsg = "更新に失敗しました。";\r
2123                         return null;\r
2124                 }\r
2125                 \r
2126                 // 更新後の情報を再取得\r
2127                 ReserveList newr = reqr.clone();\r
2128                 newr.setId(oldr.getId());\r
2129                 if ( ! GetRdReservedDetailByReserveId(newr,0) ) {\r
2130                         errmsg = "更新後の情報を取得できませんでした。";\r
2131                         return null;\r
2132                 }\r
2133 \r
2134                 System.out.printf("\n<<< Message from RD >>> \"%s\"\n\n", "正常に更新できました。");\r
2135                 return newr;\r
2136         }\r
2137         \r
2138         \r
2139         /*******************************************************************************\r
2140          * 予約削除\r
2141          ******************************************************************************/\r
2142         \r
2143         @Override\r
2144         public ReserveList RemoveRdEntry(String delid) {\r
2145                 \r
2146                 System.out.println("Run: RemoveRdEntry()");\r
2147                 \r
2148                 errmsg = "";\r
2149                 \r
2150                 // おまじない\r
2151                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
2152 \r
2153                 ReserveList delr = null;        // キャッシュ上の削除対象\r
2154                 ReserveList oldr = null;        // レコーダ上の削除対象\r
2155                 \r
2156                 // キャッシュから削除対象を探す\r
2157                 for ( ReserveList reserve : getReserves() )  {\r
2158                         if (reserve.getId().equals(delid)) {\r
2159                                 delr = reserve;\r
2160                                 break;\r
2161                         }\r
2162                 }\r
2163                 if (delr == null) {\r
2164                         return(null);\r
2165                 }\r
2166                 \r
2167                 // EDCBから削除対象を探す ★EDCBは再起動すると予約IDが振り直しになるので必要!!\r
2168                 reportProgress(String.format("削除する予約IDを取得します."));\r
2169                 \r
2170                 if ( ContentIdEDCB.isValid(delr.getContentId()) ) {\r
2171                         oldr = getRsvOnEdcbTR(delr);\r
2172                 }\r
2173                 else {\r
2174                         oldr = getRsvOnEdcbDT(delr);\r
2175                 }\r
2176                 if ( oldr == null ) {\r
2177                         errmsg = "レコーダ上に削除対象が見つかりません。";\r
2178                         return(null);\r
2179                 }\r
2180                 \r
2181                 reportProgress("+削除される予約ID: "+oldr.getId());\r
2182                 \r
2183                 // EDCBから削除する\r
2184                 String header;\r
2185                 String response;\r
2186 \r
2187                 {               \r
2188                         reportProgress("削除を実行します.");\r
2189                         String uri = "http://"+getIPAddr()+":"+getPortNo()+"/reservedel.html?id="+getRsvId(oldr.getId());\r
2190                         \r
2191                         System.err.println("URL: "+uri);\r
2192                         \r
2193                         header = response = null;\r
2194                         for (int i=0; i<retryMax; i++) {\r
2195                                 String[] d = reqPOST(uri, "", null);\r
2196                                 header = d[0];\r
2197                                 response = d[1];\r
2198                                 if ( header != null && response == null ) {\r
2199                                         reportProgress("コネクションがリセットされました。リトライします。");\r
2200                                         CommonUtils.milSleep(1000);\r
2201                                 }\r
2202                                 else {\r
2203                                         break;\r
2204                                 }\r
2205                         }\r
2206                         if ( header == null || response == null ) {\r
2207                                 errmsg = "レコーダーが反応しません。";\r
2208                                 return(null);\r
2209                         }\r
2210                         if ( ! response.contains("予約を削除しました") ) {\r
2211                                 errmsg = "削除に失敗しました。";\r
2212                                 return(null);\r
2213                         }\r
2214                 }\r
2215                 \r
2216                 // 予約リストを更新\r
2217                 getReserves().remove(delr);\r
2218                 \r
2219                 // キャッシュに保存(削除なので録画済みフラグは操作しなくてよい)\r
2220                 ReservesToFile(getReserves(), rsvedFile);\r
2221                 //setRecordedFlag();\r
2222                 \r
2223                 System.out.printf("\n<<< Message from RD >>> \"%s\"\n\n", "正常に削除できました。");\r
2224                 \r
2225                 return delr;\r
2226         }\r
2227         \r
2228         \r
2229         /*******************************************************************************\r
2230          * 予約用の部品\r
2231          ******************************************************************************/\r
2232         \r
2233         /**\r
2234          * 放送局と日付のチェック\r
2235          */\r
2236         private boolean PrePostCheck(ReserveList r) {\r
2237                 // 放送局\r
2238                 r.setChannel(cc.getCH_WEB2CODE(r.getCh_name()));\r
2239                 if ( r.getChannel() == null) {\r
2240                         errmsg = "【警告】Web番組表の放送局名「"+r.getCh_name()+"」をCHコードに変換できません。CHコード設定を修正してください。" ;\r
2241                         System.out.println(errmsg);\r
2242                         return(false);\r
2243                 }\r
2244                 \r
2245                 // 予約パターンID\r
2246                 // 次回予定日\r
2247                 // 録画長\r
2248                 // 開始日時・終了日時\r
2249                 r.setRec_pattern_id(getRec_pattern_Id(r.getRec_pattern()));\r
2250                 r.setRec_nextdate(CommonUtils.getNextDate(r));\r
2251                 r.setRec_min(CommonUtils.getRecMin(r.getAhh(),r.getAmm(),r.getZhh(),r.getZmm()));\r
2252                 getStartEndDateTime(r);\r
2253                 if ( r.getRec_pattern_id() != 11 ) {\r
2254                         errmsg = "日付指定しか利用出来ません。";\r
2255                         System.out.println(errmsg);\r
2256                         return(false) ;\r
2257                 }\r
2258                 \r
2259                 return true;\r
2260         }\r
2261         \r
2262         /**\r
2263          * プログラム予約の制限のチェック\r
2264          */\r
2265         private boolean PreProgResCheck(ReserveList r) {\r
2266                 if (\r
2267                                 getTextPittariFlag(r).equals(ITEM_JUST_ENABLE)\r
2268                         ) {\r
2269                         errmsg = "プログラム予約では次の指定はできません:ぴったり録画="+ITEM_JUST_ENABLE;\r
2270                         return(false) ;\r
2271                 }\r
2272                 \r
2273                 if (\r
2274                                 r.getPursues()\r
2275                         ) {\r
2276                         errmsg = "プログラム予約では次の指定はできないので規定値に変更しました:番組追従="+ITEM_YES;\r
2277                         r.setPursues(false);\r
2278                         //return(false) ;\r
2279                 }\r
2280                 \r
2281                 return true;\r
2282         }\r
2283         \r
2284         /**\r
2285          * EDCB予約一覧から操作対象を探すのです(EPG予約版)\r
2286          * @see #isEqualsTR(ReserveList, ReserveList, int)\r
2287          * @see #getRsvOnEdcbDT(ReserveList)\r
2288          */\r
2289         private ReserveList getRsvOnEdcbTR(ReserveList origr) {\r
2290                 \r
2291                 // 予約IDを試してみる(EDCBがリブートしていなければこれでOKなはず)\r
2292                 if ( origr.getId() != null && origr.getId().length() > 0 ) {\r
2293                         ReserveList newr = origr.clone();\r
2294                         if ( GetRdReservedDetailByReserveId(newr,0) && isEqualsTR(origr, newr, -1) ) {\r
2295                                 //System.out.println("+-一致する予約です(予約ID直接): "+newr.getId());\r
2296                                 return newr;\r
2297                         }\r
2298                 }\r
2299                 \r
2300                 // 番組IDを試してみる(重複予約されていなければこれで大丈夫なはず)\r
2301                 if ( origr.getContentId() != null && ContentIdEDCB.isValid(origr.getContentId()) ) {\r
2302                         ReserveList newr = origr.clone();\r
2303                         if ( GetRdReservedDetailByContentId(newr,0) && isEqualsTR(origr, newr, 0) ) {\r
2304                                 //System.out.println("+-一致する予約です(番組ID直接): "+newr.getId());\r
2305                                 return newr;\r
2306                         }\r
2307                 }\r
2308 \r
2309                 // 一覧取得しなおし(3.17.5b)\r
2310                 ArrayList<ReserveList> rl = new ArrayList<ReserveList>();\r
2311                 if ( ! GetRdReservedList(rl) ) {\r
2312                         errmsg = "予約一覧の取得に失敗しました。";\r
2313                         return null;\r
2314                 }\r
2315 \r
2316                 // 置き換えていいよ\r
2317                 setReserves(rl);\r
2318 \r
2319                 // 一覧から該当する予約を探す\r
2320                 int idx=1;\r
2321                 for ( ReserveList newr : rl ) {\r
2322                         if ( isEqualsTR(origr, newr, idx++) ) {\r
2323                                 return newr;\r
2324                         }\r
2325                 }\r
2326                 \r
2327                 errmsg = "予約IDがみつかりません。";\r
2328                 return null;\r
2329         }\r
2330         \r
2331         /**\r
2332          * 同じEPG予約かどうかしらべる\r
2333          */\r
2334         private boolean isEqualsTR(ReserveList origr, ReserveList newr, Integer idx) {\r
2335                 \r
2336                 // 放送局が一緒で、開始日時が近いかどうか(旧情報vs一覧)\r
2337                 if ( ! isLikesRsvOnList(origr, newr) ) {\r
2338                         return false;\r
2339                 }\r
2340                 \r
2341                 // EPG予約かどうか(詳細)\r
2342                 if ( ! ContentIdEDCB.isValid(newr.getContentId()) ) {\r
2343                         if ( idx != null ) System.out.println("+-そっくりですがEPG予約ではありません: "+newr.getId());\r
2344                         return false;\r
2345                 }\r
2346                 \r
2347                 // おなじ番組かどうか(旧情報vs一覧)\r
2348                 if ( ! origr.getContentId().equals(newr.getContentId()) ) {\r
2349                         if ( idx != null ) System.out.println("+-そっくりですが別の番組です: "+newr.getId());\r
2350                         return false;\r
2351                 }\r
2352                 \r
2353                 // チューナー指定が等しいかどうか(旧情報vs一覧)\r
2354                 if ( ! origr.getTuner().equals(newr.getTuner()) ) {\r
2355                         if ( idx != null ) System.out.println("+-そっくりですが異なる予約です(使用するチューナーが異なります): "+newr.getId());\r
2356                         return false;\r
2357                 }\r
2358                 \r
2359                 // 時間移動も確認しておくか\r
2360                 if ( isEqualsDate(origr, newr) ) {\r
2361                         if ( idx != null ) {\r
2362                                 if ( idx == -1 ) {\r
2363                                         System.out.println("+-一致する予約です(予約ID直接): "+newr.getId());\r
2364                                 }\r
2365                                 else if ( idx == 0 ) {\r
2366                                         System.out.println("+-一致する予約です(番組ID直接): "+newr.getId());\r
2367                                 }\r
2368                                 else {\r
2369                                         System.out.println("+-一致する予約です(間接)["+idx+"]: "+newr.getId());\r
2370                                 }\r
2371                         }\r
2372                 }\r
2373                 else {\r
2374                         System.out.println("+-一致する予約のようです(時間が移動しています)["+idx+"]: "+newr.getId());\r
2375                 }\r
2376                 \r
2377                 return true;\r
2378         }\r
2379         \r
2380         /**\r
2381          * EDCB予約一覧から操作対象を探すのです(プログラム予約版)<BR>\r
2382          * ※一発ヒットしたものはキャッシュに乗らないので注意\r
2383          * @see #isEqualsDT(ReserveList, ReserveList, int)\r
2384          * @see #getRsvOnEdcbTR(ReserveList)\r
2385          */\r
2386         private ReserveList getRsvOnEdcbDT(ReserveList origr) {\r
2387                 \r
2388                 // 予約IDを試してみる(EDCBがリブートしていなければこれでOKなはず)\r
2389                 if ( origr.getId() != null && origr.getId().length() > 0 ) {\r
2390                         ReserveList newr = origr.clone();\r
2391                         if ( GetRdReservedDetailByReserveId(newr,0) && isEqualsDT(origr, newr, 0) ) {\r
2392                                 //System.out.println("+-一致する予約です(番組ID直接): "+newr.getId());\r
2393                                 return newr;\r
2394                         }\r
2395                 }\r
2396 \r
2397                 // 予約IDは固定ではないので再度取得しなおさないと(3.17.5b変更)\r
2398                 ArrayList<ReserveList> rl = new ArrayList<ReserveList>();\r
2399                 if ( ! GetRdReservedList(rl) ) {\r
2400                         errmsg = "予約一覧の取得に失敗しました。";\r
2401                         return null;\r
2402                 }\r
2403 \r
2404                 // 置き換えていいよ\r
2405                 setReserves(rl);\r
2406                 \r
2407                 // 一覧から該当する予約を探す\r
2408                 int idx=0;\r
2409                 for ( ReserveList newr : rl ) {\r
2410                         if ( isEqualsDT(origr, newr, idx++) ) {\r
2411                                 return newr;\r
2412                         }\r
2413                 }\r
2414                 \r
2415                 errmsg = "予約IDが見つかりません。";\r
2416                 return null;\r
2417         }\r
2418         \r
2419         /**\r
2420          * 同じプログラム予約かどうかしらべる\r
2421          */\r
2422         private boolean isEqualsDT(ReserveList origr, ReserveList newr, Integer idx) {\r
2423                 \r
2424                 // 放送局がいっしょで、開始日時・終了時刻が等しいかどうか(旧情報vs一覧)\r
2425                 if ( ! isEqualsRsvOnList(origr, newr) ) {\r
2426                         return false;\r
2427                 }\r
2428                 \r
2429                 // プログラム予約かどうか\r
2430                 if ( ContentIdEDCB.isValid(newr.getContentId()) ) {\r
2431                         if ( idx != null ) System.out.println("+-そっくりですがプログラム予約ではありません: "+newr.getId());\r
2432                         return false;\r
2433                 }\r
2434                 \r
2435                 // チューナー指定が等しいかどうか(旧情報vs一覧)\r
2436                 if ( ! origr.getTuner().equals(newr.getTuner()) ) {\r
2437                         if ( idx != null ) System.out.println("+-そっくりですが異なる予約です(使用するチューナーが異なります): "+newr.getId());\r
2438                         return false;\r
2439                 }\r
2440                 \r
2441                 if ( idx != null ) {\r
2442                         if ( idx == 0 ) {\r
2443                                 System.out.println("+-一致する予約です(予約ID直接): "+newr.getId());\r
2444                         }\r
2445                         else {\r
2446                                 System.out.println("+-一致する予約です(間接)["+idx+"]: "+newr.getId());\r
2447                         }\r
2448                 }\r
2449                 \r
2450                 return true;\r
2451         }\r
2452 \r
2453         /**\r
2454          * 古い予約一覧から情報を引き継ぐ\r
2455          */\r
2456         private void copyAttributesAllList( ArrayList<ReserveList> oldrl, ArrayList<ReserveList> newrl ) {\r
2457                 \r
2458                 // 予約一覧の再取得があった\r
2459                 for ( ReserveList newr : newrl ) {\r
2460                         if ( newr.getContentId() != null ) {\r
2461                                 for ( ReserveList oldr : oldrl ) {\r
2462                                         if ( oldr.getContentId() != null && isEqualsTR(oldr, newr, null) ) {\r
2463                                                 copyAttributesMethod(oldr, newr);\r
2464                                         }\r
2465                                 }\r
2466                         }\r
2467                         else {\r
2468                                 for ( ReserveList oldr : oldrl ) {\r
2469                                         if ( oldr.getContentId() == null && isEqualsDT(oldr, newr, null) ) {\r
2470                                                 copyAttributesMethod(oldr, newr);\r
2471                                         }\r
2472                                 }\r
2473                         }\r
2474                 }\r
2475                 \r
2476         }\r
2477         private void copyAttributesMethod( ReserveList oldr, ReserveList newr ) {\r
2478                 newr.setRec_genre(oldr.getRec_genre());\r
2479                 newr.setRec_subgenre(oldr.getRec_subgenre());\r
2480                 setTextPresetID(newr, getTextPresetID(oldr));\r
2481         }\r
2482         \r
2483         \r
2484         /* ここまで */\r
2485         \r
2486         \r
2487         \r
2488 \r
2489         \r
2490         \r
2491         /*******************************************************************************\r
2492          * 非公開メソッド\r
2493          ******************************************************************************/\r
2494 \r
2495         //\r
2496         private String genPoststrEPGA(ReserveList r) {\r
2497                 StringBuilder sb = new StringBuilder();\r
2498                 try {\r
2499                         sb.append("presetID="+text2value(getListPresetID(),getTextPresetID(r))+"&");\r
2500                         sb.append("onid="+Integer.decode("0x"+r.getContentId().substring(5,9))+"&");\r
2501                         sb.append("tsid="+Integer.decode("0x"+r.getContentId().substring(9,13))+"&");\r
2502                         sb.append("sid="+Integer.decode("0x"+r.getContentId().substring(13,17))+"&");\r
2503                         sb.append("evid="+Integer.decode("0x"+r.getContentId().substring(17,21)));\r
2504                 }\r
2505                 catch ( Exception e ) {\r
2506                         e.printStackTrace();\r
2507                 }\r
2508                 return sb.toString();\r
2509         }\r
2510         private String genPoststrEPGB(ReserveList r) {\r
2511                 StringBuilder sb = new StringBuilder();\r
2512                 sb.append(genPoststrEPGA(r)+"&");\r
2513                 sb.append(genPoststrCom(r));\r
2514                 return sb.toString();\r
2515         }\r
2516         \r
2517         //\r
2518         private String genPoststrDTCom(ReserveList r) {\r
2519                 StringBuilder sb = new StringBuilder();\r
2520                 \r
2521                 // 日付指定しか対応してないが…\r
2522                 GregorianCalendar cal = CommonUtils.getCalendar(r.getRec_nextdate().substring(0,10));\r
2523                 sb.append("sdy="+cal.get(Calendar.YEAR)+"&");\r
2524                 sb.append("sdm="+(cal.get(Calendar.MONTH)+1)+"&");\r
2525                 sb.append("sdd="+cal.get(Calendar.DATE)+"&");\r
2526                 sb.append("sth="+Integer.valueOf(r.getAhh())+"&");\r
2527                 sb.append("stm="+Integer.valueOf(r.getAmm())+"&");\r
2528                 //\r
2529                 if ( r.getAhh().compareTo(r.getZhh()) > 0 ) {\r
2530                         cal.add(Calendar.DATE, 1);\r
2531                 }\r
2532                 sb.append("edy="+cal.get(Calendar.YEAR)+"&");\r
2533                 sb.append("edm="+(cal.get(Calendar.MONTH)+1)+"&");\r
2534                 sb.append("edd="+cal.get(Calendar.DATE)+"&");\r
2535                 sb.append("eth="+Integer.valueOf(r.getZhh())+"&");\r
2536                 sb.append("etm="+Integer.valueOf(r.getZmm()));\r
2537                 \r
2538                 return sb.toString();\r
2539         }\r
2540         private String genPoststrDTA(ReserveList r) {\r
2541                 StringBuilder sb = new StringBuilder();\r
2542                 try {\r
2543                         //sb.append("presetID="+text2value(getListPresetID(),getTextPresetID(r))+"&");\r
2544                         sb.append("serviceID="+cc.getCH_WEB2CODE(r.getCh_name())+"&");\r
2545                         sb.append("pgname="+URLEncoder.encode(r.getTitle(),thisEncoding)+"&");\r
2546                         sb.append(genPoststrDTCom(r));\r
2547                 } catch (UnsupportedEncodingException e) {\r
2548                         e.printStackTrace();\r
2549                 }\r
2550                 \r
2551                 return sb.toString();\r
2552         }\r
2553         private String genPoststrDTB(ReserveList r) {\r
2554                 StringBuilder sb = new StringBuilder();\r
2555                 try {\r
2556                         sb.append("serviceID="+cc.getCH_WEB2CODE(r.getCh_name())+"&");\r
2557                         sb.append("pgname="+URLEncoder.encode(r.getTitle(),thisEncoding)+"&");\r
2558                         sb.append(genPoststrDTCom(r)+"&");\r
2559                         sb.append(genPoststrCom(r));\r
2560                 } catch (UnsupportedEncodingException e) {\r
2561                         e.printStackTrace();\r
2562                 }\r
2563                 \r
2564                 return sb.toString();\r
2565         }\r
2566         \r
2567         //                      \r
2568         private String genPoststrCom(ReserveList r) {\r
2569                 // EPG・プログラム予約共通\r
2570                 StringBuilder sb = new StringBuilder();\r
2571                 try {\r
2572                         sb.append("presetID="+text2value(getListPresetID(),getTextPresetID(r))+"&");\r
2573                         if ( r.getExec() ) {\r
2574                                 sb.append("recMode="+text2value(getListRecMode(),getTextRecMode(r))+"&");\r
2575                         }\r
2576                         else {\r
2577                                 sb.append("recMode="+VALUE_REC_MODE_DISABLE+"&");\r
2578                         }\r
2579                         if ( r.getPursues() ) {\r
2580                                 sb.append("tuijyuuFlag="+VALUE_TRACE_ENABLE+"&");\r
2581                         }\r
2582                         else {\r
2583                                 sb.append("tuijyuuFlag="+VALUE_TRACE_DISABLE+"&");\r
2584                         }\r
2585                         sb.append("priority="+text2value(getListPriority(),getTextPriority(r))+"&");\r
2586                         sb.append("pittariFlag="+text2value(getListPittariFlag(),getTextPittariFlag(r))+"&");\r
2587                         sb.append("suspendMode="+text2value(getListSuspendMode(),getTextSuspendMode(r))+"&");\r
2588                         if ( getTextStartMargine(r).equals(ITEM_MARGINE_DEFAULT) || getTextEndMargine(r).equals(ITEM_MARGINE_DEFAULT) ) {\r
2589                                 sb.append("useDefMargineFlag=1&");\r
2590                                 sb.append("startMargine=0&");\r
2591                                 sb.append("endMargine=0&");\r
2592                         }\r
2593                         else {\r
2594                                 sb.append("startMargine="+text2value(getListStartMargine(),getTextStartMargine(r))+"&");\r
2595                                 sb.append("endMargine="+text2value(getListEndMargine(),getTextEndMargine(r))+"&");\r
2596                         }\r
2597                         {\r
2598                                 String s = getTextServiceMode(r);\r
2599                                 if ( s.equals(ITEM_SERVMOCE_DEFAULT) ) {\r
2600                                         sb.append("serviceMode=0&");\r
2601                                 }\r
2602                                 else {\r
2603                                         if ( s.equals(ITEM_SERVMOCE_SUBT) || s.equals(ITEM_SERVMOCE_SUBTCARO) ) {\r
2604                                                 sb.append("serviceMode_1=0&");\r
2605                                         }\r
2606                                         if ( s.equals(ITEM_SERVMOCE_CARO) || s.equals(ITEM_SERVMOCE_SUBTCARO) ) {\r
2607                                                 sb.append("serviceMode_2=0&");\r
2608                                         }\r
2609                                 }\r
2610                         }\r
2611                         sb.append("tunerID="+text2value(getListTunerID(),getTextTunerID(r))+"&");\r
2612                         if ( getTextContinueRecFlag(r).equals(ITEM_YES) ) {\r
2613                                 sb.append("continueRecFlag=1&");\r
2614                         }\r
2615                         if ( getTextRebootFlag(r).equals(ITEM_YES) ) {\r
2616                                 sb.append("rebootFlag=1&");\r
2617                         }\r
2618                         if ( getTextPartialRecFlag(r).equals(ITEM_YES) ) {\r
2619                                 sb.append("partialRecFlag=1&");\r
2620                         }\r
2621                         \r
2622                         // オプショナル\r
2623                         {\r
2624                                 String val = r.getHidden_params().get(RETVAL_KEY_RECFOLDERCOUNT);\r
2625                                 sb.append("recFolderCount=");\r
2626                                 sb.append((val!=null)?(val):("0"));\r
2627                                 sb.append("&");\r
2628                                 \r
2629                                 val = r.getHidden_params().get(RETVAL_KEY_PARTIALFOLDERCOUNT);\r
2630                                 sb.append("partialFolderCount=");\r
2631                                 sb.append((val!=null)?(val):("0"));\r
2632                         }\r
2633                 }\r
2634                 catch ( Exception e ) {\r
2635                         e.printStackTrace();\r
2636                 }\r
2637                 \r
2638                 return sb.toString();\r
2639         }\r
2640         \r
2641         //\r
2642         private void setSettingRecMargin(ArrayList<TextValueSet> tvs) {\r
2643                 tvs.clear();\r
2644                 add2tvs(tvs,ITEM_MARGINE_DEFAULT,VALUE_MARGINE_DEFAULT);\r
2645                 for (int i=0; i<=90; i++) {\r
2646                         add2tvs(tvs,String.valueOf(i),String.valueOf(i));\r
2647                 }\r
2648         }\r
2649         private void setSettingServiceMode(ArrayList<TextValueSet> tvs) {\r
2650                 tvs.clear();\r
2651                 add2tvs(tvs,ITEM_SERVMOCE_DEFAULT,VALUE_SERVMOCE_DEFAULT);\r
2652                 add2tvs(tvs,ITEM_SERVMOCE_SUBT,VALUE_SERVMOCE_SUBT);\r
2653                 add2tvs(tvs,ITEM_SERVMOCE_CARO,VALUE_SERVMOCE_CARO);\r
2654                 add2tvs(tvs,ITEM_SERVMOCE_SUBTCARO,VALUE_SERVMOCE_SUBTCARO);\r
2655                 add2tvs(tvs,ITEM_SERVMOCE_NONE,VALUE_SERVMOCE_NONE);\r
2656         }\r
2657         private void setSettingNoYes(ArrayList<TextValueSet> tvs) {\r
2658                 tvs.clear();\r
2659                 add2tvs(tvs,ITEM_NO,VALUE_NO);\r
2660                 add2tvs(tvs,ITEM_YES,VALUE_YES);\r
2661         }\r
2662         private void setSettingRecType(ArrayList<TextValueSet> tvs) {\r
2663                 tvs.clear();\r
2664                 add2tvs(tvs,ITEM_REC_TYPE_EPG,VALUE_REC_TYPE_EPG);\r
2665                 add2tvs(tvs,ITEM_REC_TYPE_PROG,VALUE_REC_TYPE_PROG);\r
2666         }\r
2667         //\r
2668         private void setSettingChCodeValue(ArrayList<TextValueSet> tvsValue, ArrayList<TextValueSet> tvsType, String key, String res) {\r
2669                 \r
2670                 HashMap<String, String> typ = new HashMap<String, String>();\r
2671                 typ.put("地デジ", "uvd");\r
2672                 typ.put("BS", "bsd");\r
2673                 typ.put("","csd");\r
2674                 \r
2675                 tvsValue.clear();\r
2676                 tvsType.clear();\r
2677                 Matcher mb = Pattern.compile("<select name=\""+key+"\">([\\s\\S]+?)</select>").matcher(res);\r
2678                 if (mb.find()) {\r
2679                         Matcher mc = Pattern.compile("<option value=\"([^\"]*?)\"(\\s*selected\\s*)?>(.+?)\\((.+?)\\)\\n").matcher(mb.group(1));\r
2680                         while (mc.find()) {\r
2681                                 // ワンセグは対象外\r
2682                                 if (mc.group(4).equals("ワンセグ")) {\r
2683                                         continue;\r
2684                                 }\r
2685                                 \r
2686                                 String chname = mc.group(3);\r
2687                                 Long chid = 0L;\r
2688                                 \r
2689                                 // 難視聴対策放送\r
2690                                 try {\r
2691                                         chid = Long.valueOf(mc.group(1));\r
2692                                         Long tsid = (chid & 0x0000FFFF0000L);\r
2693                                         if ( tsid == 0x000043100000L || tsid == 0x000043110000L ) {\r
2694                                                 chname = TEXT_NANSHICHO_HEADER+chname;\r
2695                                                 System.out.println("[DEBUG] "+chname);\r
2696                                         }\r
2697                                 }\r
2698                                 catch (NumberFormatException e) {\r
2699                                         continue;\r
2700                                 }\r
2701                                 \r
2702                                 // 重複する放送局名は対象外\r
2703                                 boolean dup = false;\r
2704                                 for ( TextValueSet t : tvsValue ) {\r
2705                                         if ( t.getText().equals(chname) ) {\r
2706                                                 dup = true;\r
2707                                         }\r
2708                                 }\r
2709                                 if (dup) {\r
2710                                         continue;\r
2711                                 }\r
2712                                 \r
2713                                 // 放送局ID順でソートして追加\r
2714                                 {\r
2715                                         int n = 0;\r
2716                                         for ( ; n<tvsValue.size(); n++ ) {\r
2717                                                 if ( Long.valueOf(tvsValue.get(n).getValue()) > Long.valueOf(chid) ) {\r
2718                                                         break;\r
2719                                                 }\r
2720                                         }\r
2721                                         add2tvs(n,tvsValue,chname,mc.group(1));\r
2722                                 }\r
2723 \r
2724                                 // 地デジでもBSでもないものは全部CSあつかい\r
2725                                 {\r
2726                                         String val = typ.get(mc.group(4));\r
2727                                         if (val == null) {\r
2728                                                 val = typ.get("");\r
2729                                         }\r
2730                                         add2tvs(tvsType,chname,val);\r
2731                                 }\r
2732                         }\r
2733                 }\r
2734                 \r
2735                 System.err.println("=== CHコード一覧 for EDCB ===");\r
2736                 System.err.println("放送局 : \"レコーダの放送局名\",\"放送局コード\"");\r
2737                 System.err.println("=============================");\r
2738                 \r
2739                 for ( TextValueSet tv : tvsValue ) {\r
2740                         System.err.println(String.format("%-20s : \"%s\",\"%s\"",tv.getText(),tv.getValue(),tv.getValue()));\r
2741                 }\r
2742                 System.err.println("=============================");\r
2743         }\r
2744         //\r
2745         protected void setSettingEtc(ArrayList<TextValueSet> tvs, String key, int typ, String res) {\r
2746                 tvs.clear();\r
2747                 Matcher mb = Pattern.compile("<select name=\""+key+"\">([\\s\\S]+?)</select>").matcher(res);\r
2748                 if (mb.find()) {\r
2749                         Matcher mc = Pattern.compile("<option value=\"([^\"]*?)\"(\\s*selected\\s*)?>(.*?)\\n").matcher(mb.group(1));\r
2750                         while (mc.find()) {\r
2751                                 TextValueSet t = add2tvs(tvs,mc.group(3),mc.group(1));\r
2752                                 if (mc.group(2) != null) {\r
2753                                         t.setDefval(true);\r
2754                                 }\r
2755                         }\r
2756                 }\r
2757         }\r
2758         \r
2759         // 予約情報同志を比較する\r
2760         private boolean isModified(ReserveList o, ReserveList r) {\r
2761                 return ! (isEqualsDate(o, r) && o.getTitle().equals(r.getTitle()));\r
2762         }\r
2763         private boolean isEqualsRsvOnDetail(ReserveList o, ReserveList r) {\r
2764                 // ここまで一緒なら同じ予約情報だろ\r
2765                 return (isEqualsRsvOnList(o, r) && o.getTuner().equals(r.getTuner()));\r
2766         }\r
2767         private boolean isEqualsRsvOnList(ReserveList o, ReserveList r) {\r
2768                 // ここまで一緒なら同じ予約情報だろ\r
2769                 return (isEqualsDate(o, r) && o.getChannel().equals(r.getChannel()));\r
2770         }\r
2771         private boolean isEqualsDate(ReserveList o, ReserveList r) {\r
2772                 return (o.getStartDateTime().equals(r.getStartDateTime()) && o.getEndDateTime().equals(r.getEndDateTime()));\r
2773         }\r
2774         private boolean isLikesRsvOnList(ReserveList o, ReserveList r) {\r
2775                 // ここまで一緒なら親戚の予約情報だろ\r
2776                 return (isLikesDate(o, r) && o.getChannel().equals(r.getChannel()));\r
2777         }\r
2778         private boolean isLikesDate(ReserveList o, ReserveList r) {\r
2779                 return (CommonUtils.getDiffDateTime(o.getStartDateTime(), r.getStartDateTime()) < likersvrange);\r
2780         }\r
2781 }\r