3 import java.io.BufferedReader;
\r
5 import java.io.IOException;
\r
6 import java.io.InputStreamReader;
\r
7 import java.io.OutputStreamWriter;
\r
8 import java.io.UnsupportedEncodingException;
\r
9 import java.net.Authenticator;
\r
10 import java.net.DatagramPacket;
\r
11 import java.net.DatagramSocket;
\r
12 import java.net.HttpURLConnection;
\r
13 import java.net.InetSocketAddress;
\r
14 import java.net.PasswordAuthentication;
\r
15 import java.net.SocketException;
\r
16 import java.net.URL;
\r
17 import java.util.ArrayList;
\r
18 import java.util.Calendar;
\r
19 import java.util.Date;
\r
20 import java.util.GregorianCalendar;
\r
21 import java.util.Hashtable;
\r
22 import java.util.List;
\r
23 import java.util.Map;
\r
24 import java.util.regex.Matcher;
\r
25 import java.util.regex.Pattern;
\r
29 * {@link HDDRecorder}インタフェース をインプルメントしたレコーダプラグインのクラスで利用できる、共有部品の集合です。
\r
30 * @version 3.15.4β クラス名を RecorderUtils から HDDRecorderUtils に変更しました。
\r
32 public class HDDRecorderUtils implements HDDRecorder,Cloneable {
\r
34 /*******************************************************************************
\r
36 ******************************************************************************/
\r
38 public HDDRecorderUtils clone() {
\r
40 HDDRecorderUtils ru = (HDDRecorderUtils) super.clone();
\r
41 FieldUtils.deepCopy(ru, this); // ディープコピーするよ
\r
43 } catch (CloneNotSupportedException e) {
\r
44 throw new InternalError(e.toString());
\r
48 /*******************************************************************************
\r
50 ******************************************************************************/
\r
53 public boolean isThereAdditionalDetails() { return false; }
\r
55 public boolean isEditAutoReserveSupported() { return false; }
\r
57 public boolean isRepeatReserveSupported() { return true; }
\r
59 public boolean isPursuesEditable() { return false; }
\r
61 public boolean isAutocompleteSupported() { return true; }
\r
63 public boolean isChangeChannelSupported() { return ChangeChannel(null); }
\r
65 public boolean isBackgroundOnly() { return false; }
\r
67 public boolean isChValueAvailable() { return false; }
\r
69 public boolean isChCodeNeeded() { return true; }
\r
71 public boolean isRecChNameNeeded() { return true; }
\r
73 public boolean isBroadcastTypeNeeded() { return false; }
\r
75 public boolean isAutoEncSelectEnabled() { return true; }
\r
77 public String getChDatHelp() { return ""; }
\r
79 // フリーテキストによるオプション指定
\r
81 public boolean setOptString(String s) { return true; } // ダミー
\r
83 public String getOptString() { return null; } // ダミー
\r
86 /*******************************************************************************
\r
88 ******************************************************************************/
\r
91 private static final String MSGID = "[レコーダ共通] ";
\r
92 private static final String DBGID = "[DEBUG]"+MSGID;
\r
93 private static final String ERRID = "[ERROR]"+MSGID;
\r
96 /*******************************************************************************
\r
98 ******************************************************************************/
\r
101 public void setDebug(boolean b) { debug = b; }
\r
102 protected boolean getDebug() { return debug; }
\r
103 private boolean debug = false;
\r
105 // 終了時刻と開始時刻が重なる番組を重複扱いするか
\r
106 public void setAdjNotRep(boolean b) { adjnotrep = b; }
\r
107 private boolean getAdjNotRep() { return adjnotrep; }
\r
108 private boolean adjnotrep = false;
\r
111 public void setUseCalendar(boolean b) { usecalendar = b; }
\r
112 public boolean getUseCalendar() { return usecalendar; }
\r
113 private boolean usecalendar = true;
\r
116 public void setUseChChange(boolean b) { usechchange = b; }
\r
117 public boolean getUseChChange() { return usechchange; }
\r
118 private boolean usechchange = true;
\r
121 public void setRecordedCheckScope(int n) { recordedCheckScope = n; }
\r
122 protected int getRecordedCheckScope() { return recordedCheckScope; }
\r
123 private int recordedCheckScope = 14;
\r
126 public void setRecordedSaveScope(int n) { recordedSaveScope = n; }
\r
127 protected int getRecordedSaveScope() { return recordedSaveScope; }
\r
128 private int recordedSaveScope = 90;
\r
130 // HTTPアクセス時のUser-Agent
\r
131 public void setUserAgent(String s) { userAgent = s; }
\r
132 //public String getUserAgent() { return userAgent; }
\r
133 private String userAgent = "";
\r
136 /*******************************************************************************
\r
138 ******************************************************************************/
\r
140 public String Myself() { return(getIPAddr()+":"+getPortNo()+":"+getRecorderId()); }
\r
141 public boolean isMyself(String myself) { return Myself().equals(myself); }
\r
143 protected ArrayList<TextValueSet> vrate = new ArrayList<TextValueSet>();
\r
144 protected ArrayList<TextValueSet> arate = new ArrayList<TextValueSet>();
\r
145 protected ArrayList<TextValueSet> folder = new ArrayList<TextValueSet>();
\r
146 protected ArrayList<TextValueSet> encoder = new ArrayList<TextValueSet>();
\r
147 protected ArrayList<TextValueSet> dvdcompat = new ArrayList<TextValueSet>();
\r
148 protected ArrayList<TextValueSet> device = new ArrayList<TextValueSet>();
\r
149 protected ArrayList<TextValueSet> channel = new ArrayList<TextValueSet>();
\r
150 protected ArrayList<TextValueSet> xchapter = new ArrayList<TextValueSet>();
\r
151 protected ArrayList<TextValueSet> mschapter = new ArrayList<TextValueSet>();
\r
152 protected ArrayList<TextValueSet> mvchapter = new ArrayList<TextValueSet>();
\r
153 protected ArrayList<TextValueSet> chvalue = new ArrayList<TextValueSet>();
\r
154 protected ArrayList<TextValueSet> chtype = new ArrayList<TextValueSet>();
\r
155 protected ArrayList<TextValueSet> genre = new ArrayList<TextValueSet>();
\r
157 protected ArrayList<TextValueSet> aspect = new ArrayList<TextValueSet>();
\r
158 protected ArrayList<TextValueSet> bvperf = new ArrayList<TextValueSet>();
\r
159 protected ArrayList<TextValueSet> lvoice = new ArrayList<TextValueSet>();
\r
160 protected ArrayList<TextValueSet> autodel = new ArrayList<TextValueSet>();
\r
162 public ArrayList<TextValueSet> getVideoRateList() { return(vrate); }
\r
163 public ArrayList<TextValueSet> getAudioRateList() { return(arate); }
\r
164 public ArrayList<TextValueSet> getFolderList() { return(folder); }
\r
165 public ArrayList<TextValueSet> getEncoderList() { return(encoder); }
\r
166 public ArrayList<TextValueSet> getDVDCompatList() { return(dvdcompat); }
\r
167 public ArrayList<TextValueSet> getDeviceList() { return(device); }
\r
168 public ArrayList<TextValueSet> getXChapter() { return(xchapter); }
\r
169 public ArrayList<TextValueSet> getMsChapter() { return(mschapter); }
\r
170 public ArrayList<TextValueSet> getMvChapter() { return(mvchapter); }
\r
171 public ArrayList<TextValueSet> getChValue() { return(chvalue); }
\r
172 public ArrayList<TextValueSet> getChType() { return(chtype); }
\r
174 public ArrayList<TextValueSet> getAspect() { return(aspect); }
\r
175 public ArrayList<TextValueSet> getBVperf() { return(bvperf); }
\r
176 public ArrayList<TextValueSet> getLVoice() { return(lvoice); }
\r
177 public ArrayList<TextValueSet> getAutodel() { return(autodel); }
\r
179 public String getLabel_Videorate() { return null; }
\r
180 public String getLabel_Audiorate() { return null; }
\r
181 public String getLabel_Folder() { return null; }
\r
182 public String getLabel_Device() { return null; }
\r
183 public String getLabel_DVDCompat() { return null; }
\r
184 public String getLabel_XChapter() { return null; }
\r
185 public String getLabel_MsChapter() { return null; }
\r
186 public String getLabel_MvChapter() { return null; }
\r
187 public String getLabel_Aspect() { return null; }
\r
188 public String getLabel_BVperf() { return null; }
\r
189 public String getLabel_LVoice() { return null; }
\r
190 public String getLabel_Autodel() { return null; }
\r
192 /*******************************************************************************
\r
194 ******************************************************************************/
\r
196 public String getRecorderId() { return "THIS IS DUMMY METHOD"; }
\r
198 private String recorderIPAddr = "";
\r
199 private String recorderPortNo = "";
\r
200 private String recorderUser = "";
\r
201 private String recorderPasswd = "";
\r
202 private String recorderMacAddr = "";
\r
203 private String recorderBroadcast = "";
\r
204 private int recorderTunerNum = 0;
\r
206 public String getIPAddr() { return recorderIPAddr; }
\r
207 public void setIPAddr(String s) { recorderIPAddr = s; }
\r
208 public String getPortNo() { return recorderPortNo; }
\r
209 public void setPortNo(String s) { recorderPortNo = s; }
\r
210 public String getUser() { return recorderUser; }
\r
211 public void setUser(String s) { recorderUser = s; }
\r
212 public String getPasswd() { return recorderPasswd; }
\r
213 public void setPasswd(String s) { recorderPasswd = s; }
\r
214 public String getMacAddr() { return recorderMacAddr; }
\r
215 public void setMacAddr(String s) { recorderMacAddr = s; }
\r
216 public String getBroadcast() { return recorderBroadcast; }
\r
217 public void setBroadcast(String s) { recorderBroadcast = s; }
\r
218 public int getTunerNum() { return recorderTunerNum; }
\r
219 public void setTunerNum(int n) { recorderTunerNum = n; }
\r
222 public String getColor(String tuner) {
\r
224 if (tuner != null && tuner.length() != 0) {
\r
226 for (TextValueSet e : getEncoderList()) {
\r
227 if (tuner.equals(e.getText())) {
\r
228 if (recorderColorList.size() > idx) {
\r
229 return recorderColorList.get(idx);
\r
236 // 適当なエンコーダが見つからない場合は既定値
\r
237 return recorderColorList.get(0);
\r
240 // Envからもらってきたものを分解して保持する
\r
241 public void setColor(String s) {
\r
243 recorderColorList.clear();
\r
246 ma = Pattern.compile("^#......$").matcher(s);
\r
248 recorderColorList.add(s);
\r
251 ma = Pattern.compile("(#......);").matcher(s);
\r
252 while (ma.find()) {
\r
253 recorderColorList.add(ma.group(1));
\r
259 public ArrayList<String> getColors() { return recorderColorList; }
\r
261 private ArrayList<String> recorderColorList = new ArrayList<String>();
\r
266 public ReserveList getReserveList(String rsvId) {
\r
267 for ( ReserveList rsv : RESERVES ) {
\r
268 if ( rsv.getId() != null && rsv.getId().equals(rsvId) ) {
\r
276 * 持っている予約をすべて…吐き出させるっ…!
\r
278 public ArrayList<ReserveList> getReserves() { return RESERVES; }
\r
280 private ArrayList<ReserveList> RESERVES = new ArrayList<ReserveList>();
\r
285 public AutoReserveInfoList getAutoReserves() { return AUTORESERVES; }
\r
286 private AutoReserveInfoList AUTORESERVES = new AutoReserveInfoList(Env.envDir,null,"dummy","0.0.0.0","0");
\r
291 public ArrayList<RecordedInfo> getRecorded() { return RECORDED; }
\r
292 protected void setRecorded(ArrayList<RecordedInfo> r ) { RECORDED = r; }
\r
294 private ArrayList<RecordedInfo> RECORDED = new ArrayList<RecordedInfo>();
\r
296 /*******************************************************************************
\r
298 ******************************************************************************/
\r
300 // 素直にHashMapつかっておけばよかった
\r
301 public String text2value(ArrayList<TextValueSet> tvs, String text) {
\r
302 for ( TextValueSet t : tvs ) {
\r
303 if (t.getText().equals(text)) {
\r
304 return(t.getValue());
\r
309 public String value2text(ArrayList<TextValueSet> tvs, String value) {
\r
310 for ( TextValueSet t : tvs ) {
\r
311 if (t.getValue().equals(value)) {
\r
312 return(t.getText());
\r
318 protected TextValueSet add2tvs(ArrayList<TextValueSet> tvs, String text, String value) {
\r
319 TextValueSet t = new TextValueSet();
\r
325 protected TextValueSet add2tvs(int n, ArrayList<TextValueSet> tvs, String text, String value) {
\r
326 TextValueSet t = new TextValueSet();
\r
333 // 予約日付をId化する(単日以外)
\r
334 protected int getRec_pattern_Id(String s) {
\r
336 for (; i<HDDRecorder.RPTPTN.length;i++) {
\r
337 //System.out.println(s + "->" + HDDRecorder.RPTPTN[i]);
\r
338 if (s.equals(HDDRecorder.RPTPTN[i])) {
\r
345 /* 予約IDが動的に変化するレコーダ向けの処理 */
\r
346 private int rsvcnt = 0;
\r
347 protected String getUniqId(String rsvId) { return (!rsvId.startsWith("U$"))?(String.format("U$%14s,%05d,%s",CommonUtils.getDateTimeYMD(0),(rsvcnt++)%100000,rsvId)):(rsvId); }
\r
348 protected String getRsvId(String uniqId) { return (uniqId.startsWith("U$"))?(uniqId.substring(23)):(uniqId); }
\r
352 public void getStartEndDateTime(ReserveList r) {
\r
354 GregorianCalendar c = CommonUtils.getCalendar(r.getRec_nextdate());
\r
356 // ★★★ MM/DDをYYYY/MM/DDに戻す? ★★★
\r
357 c.set(Calendar.MINUTE, Integer.valueOf(r.getAmm()));
\r
358 c.set(Calendar.HOUR_OF_DAY, Integer.valueOf(r.getAhh()));
\r
359 r.setStartDateTime(CommonUtils.getDateTime(c));
\r
361 c.add(Calendar.MINUTE, Integer.valueOf(r.getRec_min()));
\r
362 r.setEndDateTime(CommonUtils.getDateTime(c));
\r
367 public String[] _mmdd2yyyymmdd(String mm, String dd)
\r
369 GregorianCalendar c = new GregorianCalendar();
\r
370 c.setTime(new Date());
\r
371 if ( Integer.valueOf(mm) < c.get(Calendar.MONTH)+1 ) {
\r
372 c.add(Calendar.YEAR, 1);
\r
375 return (new String[] { String.format("%04d",c.get(Calendar.YEAR)), mm, dd });
\r
379 public String[] _hhmm2hhmm_min(String ahhmm, String zhhmm)
\r
386 Matcher ma = Pattern.compile("^(\\d+):(\\d+)").matcher(ahhmm);
\r
388 ahh = String.format("%02d",Integer.valueOf(ma.group(1)));
\r
389 amm = String.format("%02d",Integer.valueOf(ma.group(2)));
\r
392 ma = Pattern.compile("^(\\d+):(\\d+)").matcher(zhhmm);
\r
394 zhh = String.format("%02d",Integer.valueOf(ma.group(1)));
\r
395 zmm = String.format("%02d",Integer.valueOf(ma.group(2)));
\r
398 int min = Integer.valueOf(zhh)*60+Integer.valueOf(zmm) - (Integer.valueOf(ahh)*60+Integer.valueOf(amm));
\r
399 if ( min < 0 ) min += 24*60;
\r
401 return (new String[] {ahh, amm, zhh, zmm, Integer.toString(min)});
\r
404 // レコーダの設定情報をキャッシュする
\r
405 public ArrayList<TextValueSet> TVSload(String filename) {
\r
406 File f = new File(filename);
\r
407 if ( ! f.exists() ) {
\r
408 return new ArrayList<TextValueSet>();
\r
411 @SuppressWarnings("unchecked")
\r
412 ArrayList<TextValueSet> ar = (ArrayList<TextValueSet>) CommonUtils.readXML(filename);
\r
413 if ( ar == null ) {
\r
414 System.err.println("設定ファイルの読み込みに失敗しました: "+filename);
\r
415 return new ArrayList<TextValueSet>();
\r
420 public void TVSsave(ArrayList<TextValueSet> ar, String filename) {
\r
421 if ( ! CommonUtils.writeXML(filename, ar) ) {
\r
422 System.err.println("設定ファイルの保存に失敗しました: "+filename);
\r
427 * レコーダの予約リストをキャッシュする
\r
429 * @return nullは返さない!
\r
430 * @see #ReservesToFile(ArrayList, String)
\r
432 protected ArrayList<ReserveList> ReservesFromFile(String rsvedFile) {
\r
433 File f = new File(rsvedFile);
\r
434 if ( ! f.exists() ) {
\r
435 System.out.println("+予約キャッシュはありません: "+rsvedFile);
\r
436 return new ArrayList<ReserveList>();
\r
439 @SuppressWarnings("unchecked")
\r
440 ArrayList<ReserveList> tmp = (ArrayList<ReserveList>) CommonUtils.readXML(rsvedFile);
\r
441 if ( tmp == null ) {
\r
442 System.err.println("予約キャッシュの読み込みに失敗しました: "+rsvedFile);
\r
443 return new ArrayList<ReserveList>();
\r
448 for (ReserveList r : tmp) {
\r
449 if (r.getId() == null && r.getNo() > 0) {
\r
450 r.setId(String.valueOf(r.getNo()));
\r
455 System.out.println("+予約キャッシュを読み込みました("+tmp.size()+"): "+rsvedFile);
\r
462 * @see #ReservesFromFile(String)
\r
464 protected void ReservesToFile(ArrayList<ReserveList> reserves, String rsvedFile) {
\r
465 if ( ! CommonUtils.writeXML(rsvedFile, reserves) ) {
\r
466 System.err.println("予約キャッシュの保存に失敗しました: "+rsvedFile);
\r
471 * レコーダの録画結果リストをキャッシュする<BR>
\r
472 * ※キャッシュから取得したものはIDがnullでクリアされる
\r
474 * @return nullは返さない!
\r
475 * @see #RecordedToFile(ArrayList, String)
\r
477 protected ArrayList<RecordedInfo> RecordedFromFile(String recedFile) {
\r
479 File f = new File(recedFile);
\r
480 if ( ! f.exists() ) {
\r
481 System.out.println("+録画結果キャッシュはありません: "+recedFile);
\r
482 return new ArrayList<RecordedInfo>();
\r
485 @SuppressWarnings("unchecked")
\r
486 ArrayList<RecordedInfo> tmp = (ArrayList<RecordedInfo>) CommonUtils.readXML(recedFile);
\r
487 if ( tmp == null ) {
\r
488 System.err.println("録画結果キャッシュの読み込みに失敗しました: "+recedFile);
\r
489 return new ArrayList<RecordedInfo>();
\r
493 String critDate = CommonUtils.getDate(CommonUtils.getCalendar(-86400*getRecordedSaveScope()));
\r
494 String specialDate = CommonUtils.getDate(CommonUtils.getCalendar("1970/01/01"));
\r
495 for ( int i=tmp.size()-1; i>=0; i-- ) {
\r
496 if ( tmp.get(i).getDate().compareTo(critDate) < 0 && tmp.get(i).getDate().compareTo(specialDate) > 0) {
\r
498 if (debug) System.out.println("録画結果のキャッシュを削除しました: "+tmp.get(i).getDate()+" "+tmp.get(i).getTitle());
\r
507 for ( RecordedInfo ri : tmp ) {
\r
508 // キャッシュから読みだしたものはIDをクリアする
\r
511 if ( ri.getCh_orig() == null ) {
\r
512 ri.setCh_orig(ri.getCh_name());
\r
516 System.out.println("+録画結果キャッシュを読み込みました("+tmp.size()+"件): "+recedFile);
\r
523 * @see #RecordedToFile(ArrayList, String)
\r
525 protected void RecordedToFile(ArrayList<RecordedInfo> recorded, String recedFile) {
\r
526 if ( ! CommonUtils.writeXML(recedFile, recorded) ) {
\r
527 System.err.println("録画結果キャッシュの保存に失敗しました: "+recedFile);
\r
534 protected boolean matchReserveV1(ReserveList n, ReserveList o) {
\r
536 n.getTitle().equals(o.getTitle()) &&
\r
537 n.getChannel().equals(o.getChannel()) &&
\r
538 n.getRec_pattern().equals(o.getRec_pattern()) &&
\r
539 n.getAhh().equals(o.getAhh()) && n.getAmm().equals(o.getAmm())
\r
542 public void setReservesV1(ArrayList<ReserveList> r) {
\r
543 // ライン入力のチャンネル名を保持する
\r
544 //System.out.println(RESERVES.size()+","+r.size());
\r
545 for (ReserveList o : RESERVES) {
\r
546 for (ReserveList n : r) {
\r
547 if (matchReserveV1(n, o)) {
\r
549 if (o.getCh_name() != null && n.getCh_name() != null && n.getCh_name().startsWith("外部入力")) {
\r
550 System.out.println("外部入力を次の放送局で置き換えます: "+n.getCh_name()+"->"+o.getCh_name());
\r
551 n.setCh_name(o.getCh_name());
\r
555 n.setAutocomplete(o.getAutocomplete());
\r
557 n.setDetail(o.getDetail());
\r
558 n.setRec_genre(o.getRec_genre());
\r
559 n.setRec_device(o.getRec_device());
\r
560 n.setRec_folder(o.getRec_folder());
\r
561 n.setRec_dvdcompat(o.getRec_dvdcompat());
\r
562 n.setRec_xchapter(o.getRec_xchapter());
\r
563 n.setRec_mschapter(o.getRec_mschapter());
\r
564 n.setRec_mvchapter(o.getRec_mvchapter());
\r
566 n.setRec_aspect(o.getRec_aspect());
\r
567 n.setRec_bvperf(o.getRec_bvperf());
\r
568 n.setRec_lvoice(o.getRec_lvoice());
\r
569 n.setRec_autodel(o.getRec_autodel());
\r
578 public void setReserves(ArrayList<ReserveList> r) {
\r
579 // ライン入力のチャンネル名を保持する
\r
580 for (ReserveList o : RESERVES) {
\r
581 for (ReserveList n : r) {
\r
583 if (o.getCh_name() != null && n.getCh_name() != null && n.getCh_name().startsWith("外部入力")) {
\r
584 if (o.getId() == n.getId() && o.getChannel().equals(n.getChannel())) {
\r
585 System.out.println("外部入力を次の放送局で置き換えます: "+n.getCh_name()+"->"+o.getCh_name());
\r
586 n.setCh_name(o.getCh_name());
\r
593 if ( getTunerNum() >= 2 ) {
\r
597 ArrayList<ReserveList> s = new ArrayList<ReserveList>();
\r
598 for ( ReserveList o : r ) {
\r
600 for ( int i=0; i<s.size(); i++ ) {
\r
601 if ( o.getStartDateTime().compareTo(s.get(i).getStartDateTime()) < 0 ) {
\r
617 for ( int x=0; x<s.size(); x++ ) {
\r
619 ArrayList<String> tuns = new ArrayList<String>();
\r
620 for ( TextValueSet enc : encoder ) {
\r
621 tuns.add(enc.getText());
\r
623 // 残っているチューナーをリストアップする
\r
624 for ( int y=0; y<s.size() && tuns.size()>0; y++ ) {
\r
625 if ( x == y || s.get(y).getTuner().equals("") ) {
\r
626 // 自分自身と、チューナー番号が振られていない相手はスルー
\r
629 // 時間が重なっている予約が既に使用しているチューナーは除外する
\r
630 ArrayList<String> starts = new ArrayList<String>();
\r
631 ArrayList<String> ends = new ArrayList<String>();
\r
632 CommonUtils.getStartEndList(starts, ends, s.get(y));
\r
633 for ( int z=0; z<starts.size(); z++ ) {
\r
634 // 帯予約を正しく処理するために全予約日時をなめるようにする
\r
635 if ( CommonUtils.isOverlap(s.get(x).getStartDateTime(), s.get(x).getEndDateTime(), starts.get(z), ends.get(z), getAdjNotRep()) ) {
\r
636 tuns.remove(s.get(y).getTuner());
\r
642 if ( tuns.size() == 0 ) {
\r
644 s.get(x).setTuner(encoder.get(0).getText());
\r
647 // 余っているならそのうちの最初のものを使用
\r
648 s.get(x).setTuner(tuns.get(0));
\r
652 else if ( getTunerNum() == 1 ) {
\r
654 for ( int x=0; x<r.size(); x++ ) {
\r
655 r.get(x).setTuner("■");
\r
666 public void refreshReserves() {
\r
668 String curDateTime = CommonUtils.getCritDateTime();
\r
670 for (int i=RESERVES.size()-1; i>=0; i--) {
\r
671 ReserveList r = RESERVES.get(i);
\r
672 if (r.getRec_pattern_id() == HDDRecorder.RPTPTN_ID_BYDATE) {
\r
674 if (r.getEndDateTime().compareTo(curDateTime) < 0) {
\r
676 RESERVES.remove(r);
\r
681 String nextDate = CommonUtils.getNextDate(r);
\r
682 r.setRec_nextdate(nextDate);
\r
693 protected ArrayList<ReserveList> decodeReservedList(String response) {
\r
695 ArrayList<ReserveList> newReserveList = new ArrayList<ReserveList>();
\r
697 Matcher ma = Pattern.compile("(c1\\[\\d+?\\]=[\\s\\S]+?\";)\\n").matcher(response);
\r
698 while ( ma.find() ) {
\r
700 ReserveList entry = new ReserveList();
\r
704 String[] d = new String[17];
\r
705 mb = Pattern.compile("c\\d+?\\[\\d+?\\]=\"(.*?)\";").matcher(ma.group(1));
\r
706 for (int i=0; i<d.length; i++) {
\r
708 d[i] = mb.group(1);
\r
710 //System.out.println(i+") "+d[i]);
\r
714 if (d[1].equals("2")) {
\r
715 entry.setExec(false);
\r
719 //if (d[12].equals("0") || d[12].equals("4") || d[12].equals("3")) {
\r
720 if (d[12].equals("4")) {
\r
721 entry.setPursues(true);
\r
725 entry.setRec_device(d[8]);
\r
728 String title = CommonUtils.unEscape(d[2]).replaceAll("<BR>","");
\r
734 entry.setRec_pattern(d[5]);
\r
735 entry.setRec_pattern_id(getRec_pattern_Id(entry.getRec_pattern()));
\r
736 mb = Pattern.compile("(\\d\\d):(\\d\\d).*?(\\d\\d):(\\d\\d)").matcher(d[6]+"-"+d[7]);
\r
738 entry.setAhh(mb.group(1));
\r
739 entry.setAmm(mb.group(2));
\r
740 entry.setZhh(mb.group(3));
\r
741 entry.setZmm(mb.group(4));
\r
743 entry.setRec_nextdate(CommonUtils.getNextDate(entry));
\r
744 //entry.setRec_nextdate(getNextDate(entry.getRec_pattern(), entry.getZhh()+":"+entry.getZmm()));
\r
745 entry.setRec_min(CommonUtils.getRecMin(entry.getAhh(), entry.getAmm(), entry.getZhh(), entry.getZmm()));
\r
746 getStartEndDateTime(entry);
\r
749 if (d[3].equals("18") || d[3].equals("10") || d[3].equals("9")) {
\r
750 entry.setTuner("TS2");
\r
752 else if (d[3].equals("17") || d[3].equals("12") || d[3].equals("11")) {
\r
753 entry.setTuner("TS1");
\r
755 else if (d[3].equals("16") || d[3].equals("7")) {
\r
756 entry.setTuner("RE");
\r
759 entry.setTuner("--");
\r
763 if (d[10].equals(" ")) {
\r
764 if (d[9].equals("A1")) {
\r
765 d[9] = "[TSE] AT 4.7GB";
\r
767 else if (d[9].equals("A2")) {
\r
768 d[9] = "[TSE] AT 9.4GB";
\r
770 else if (d[9].equals("DL")) {
\r
771 d[9] = "[TSE] AT 8.5GB";
\r
774 Matcher mc = Pattern.compile("^MN").matcher(d[9]);
\r
776 d[9] = mc.replaceFirst("[TSE] ");
\r
781 if (d[9].equals("A1")) {
\r
782 d[9] = "[VR] AT 4.7GB";
\r
784 else if (d[9].equals("A2")) {
\r
785 d[9] = "[VR] AT 9.4GB";
\r
787 else if (d[9].equals("DL")) {
\r
788 d[9] = "[VR] AT 8.5GB";
\r
791 Matcher mc = Pattern.compile("^MN").matcher(d[9]);
\r
793 d[9] = mc.replaceFirst("[VR] ");
\r
795 else if ( d[9].startsWith("SP") || d[9].startsWith("LP")) {
\r
796 d[9] = "[VR] "+d[9];
\r
801 if (d[9].equals("TS")) {
\r
802 entry.setRec_mode("[TS]");
\r
805 entry.setRec_mode(d[9]);
\r
808 entry.setTitle(title);
\r
809 entry.setTitlePop(TraceProgram.replacePop(title));
\r
810 //entry.setCh_name(getChCode().getCH_NO2NAME(d[4])); // 機種固有領域に移動
\r
811 entry.setChannel(d[4]);
\r
813 entry.setRec_audio(d[10]);
\r
814 //entry.rec_folder = data.get(); // 予約一覧からはとれない
\r
815 //entry.rec_genre = data.get(); // 予約一覧からはとれない
\r
818 newReserveList.add(entry.clone());
\r
820 return(newReserveList);
\r
824 * レコーダーから取得できない情報は直接コピー(既存のリストから探して)
\r
826 protected void copyAttributes(ReserveList to, ArrayList<ReserveList> fromlist) {
\r
827 ReserveList olde = null;
\r
828 for ( ReserveList from : fromlist ) {
\r
829 if ( from.getId() != null && from.getId().equals(to.getId()) ) {
\r
830 copyAttribute(to, olde = from);
\r
835 // DIGAの終了時間"未定"対応だけど、別にDIGAかどうか確認したりはしない。
\r
836 setAttributesDiga(to,olde);
\r
840 * レコーダーから取得できない情報は直接コピー(既存エントリから直に)
\r
842 protected void copyAttribute(ReserveList to, ReserveList from) {
\r
844 to.setAutocomplete(from.getAutocomplete());
\r
846 to.setDetail(from.getDetail());
\r
847 to.setRec_genre(from.getRec_genre());
\r
848 //n.setRec_device(o.getRec_device());
\r
849 to.setRec_folder(from.getRec_folder());
\r
850 to.setRec_dvdcompat(from.getRec_dvdcompat());
\r
851 to.setRec_xchapter(from.getRec_xchapter());
\r
852 to.setRec_mschapter(from.getRec_mschapter());
\r
853 to.setRec_mvchapter(from.getRec_mvchapter());
\r
855 to.setRec_aspect(from.getRec_aspect());
\r
856 to.setRec_bvperf(from.getRec_bvperf());
\r
857 to.setRec_lvoice(from.getRec_lvoice());
\r
858 to.setRec_autodel(from.getRec_autodel());
\r
859 // BZ700以降の取得一覧から取得できない画質の対応
\r
860 if (to.getRec_mode().equals("")) {
\r
861 to.setRec_mode(from.getRec_mode());
\r
865 protected void setAttributesDiga(ReserveList to, ReserveList from) {
\r
866 if ( to.getZhh() != null && to.getZmm() != null && to.getRec_min() != null ) {
\r
871 if ( from != null && from.getZhh() != null ) {
\r
873 to.setZhh(from.getZhh());
\r
874 to.setZmm(from.getZmm());
\r
875 to.setRec_min(from.getRec_min());
\r
876 to.setRec_nextdate(CommonUtils.getNextDate(to));
\r
877 getStartEndDateTime(to);
\r
882 // 現在時刻から30分後か、開始時刻から1時間後の、どちらか短い方に強制設定する
\r
883 String curTM = CommonUtils.getTime(30);
\r
884 String endTM = String.format("%02d:%s", (Integer.valueOf(to.getAhh())+1)%24,to.getAmm());
\r
885 if ( curTM.compareTo(endTM) > 0 ) {
\r
888 to.setZhh(endTM.substring(0,2));
\r
889 to.setZmm(endTM.substring(3,5));
\r
890 to.setRec_min(CommonUtils.getRecMin(to.getAhh()+":"+to.getAmm(), endTM));
\r
893 // 開始時刻から1時間後に強制設定する
\r
894 to.setZhh(String.format("%02d", (Integer.valueOf(to.getAhh())+1)%24));
\r
895 to.setZmm(to.getAmm());
\r
896 to.setRec_min("60");
\r
898 to.setRec_nextdate(CommonUtils.getNextDate(to));
\r
899 getStartEndDateTime(to);
\r
905 protected void setRecordedFlag() {
\r
907 // 過去X日分までチェック(初期値は14日)
\r
908 final String critDateTime = CommonUtils.getDateTimeW(-86400*getRecordedCheckScope());
\r
910 for ( ReserveList reserved : RESERVES ) {
\r
911 reserved.setRecorded(false);
\r
914 for ( RecordedInfo recorded : RECORDED ) {
\r
915 if ( critDateTime.compareTo(recorded.getDate()+" "+recorded.getAhh()+":"+recorded.getAmm()) > 0 ) {
\r
918 String chktitle = recorded.getTitle().replaceFirst(TVProgram.titlePrefixRemoveExpr, "");
\r
919 for ( ReserveList reserved : RESERVES ) {
\r
920 if ( reserved.getRecorded() ) {
\r
921 // 既にフラグが立ってるものはスルー
\r
924 if ( reserved.getRec_pattern_id() != HDDRecorder.RPTPTN_ID_BYDATE ) {
\r
928 String restitle = reserved.getTitle().replaceFirst(TVProgram.titlePrefixRemoveExpr, "");
\r
929 boolean chchk = (recorded.getChannel() != null && recorded.getChannel().length() > 0) ? (recorded.getChannel().equals(reserved.getChannel())) : (true);
\r
930 if ( recorded.getSucceeded() && recorded.getDrop_mpeg() == 0 && chchk && chktitle.equals(restitle) ) {
\r
931 // 成功していて、放送局とタイトルが一致
\r
932 reserved.setRecorded(true);
\r
940 * @param newRecordedList
\r
943 protected RecordedInfo addRecorded(ArrayList<RecordedInfo> newRecordedList, RecordedInfo entry) {
\r
945 String endt = entry.getDate()+entry.getAhh()+entry.getAmm();
\r
949 for ( ; n<newRecordedList.size(); n++ ) {
\r
950 RecordedInfo ri = newRecordedList.get(n);
\r
951 String ridt = ri.getDate()+ri.getAhh()+ri.getAmm();
\r
952 int result = ridt.compareTo(endt);
\r
953 if ( result == 0 ) {
\r
955 // 開始時刻が同じ情報を発見したら、最終的にはそれの前に差し込みたいので、nを保存する
\r
960 if ( ri.getId() == null ) {
\r
961 // キャッシュから取得したものだった場合に重複チェックする
\r
962 if ( ri.getTitle().equals(entry.getTitle()) && ri.getCh_orig().equals(entry.getCh_orig()) && ri.getLength() == entry.getLength()/* && ri.getDrop() == entry.getDrop()*/ ) {
\r
964 System.out.println(MSGID+"録画結果はすでにキャッシュ上に存在していたようです: "+endt+" "+entry.getTitle());
\r
968 if (getDebug()) System.out.println(DBGID+"よく似た録画結果です: "+endt+" "+entry.getTitle()+" <-> "+ridt+ri.getTitle());
\r
972 else if ( result < 0 ) {
\r
977 entry.setDrop_mpeg(entry.getDrop()-entry.getDrop_mpeg());
\r
979 newRecordedList.add((dn!=-1)?(dn):(n),entry);
\r
981 if (getDebug()) System.out.println(DBGID+"録画結果を追加しました: "+endt+" "+entry.getTitle());
\r
988 * <P>chCode→chName変換もこの中でやる
\r
990 protected void setAutoReserves(AutoReserveInfoList l) {
\r
991 for ( AutoReserveInfo r : l ) {
\r
993 for ( String chCode : r.getChCodes() ) {
\r
994 String chName = getChCode().getCH_CODE2WEB(chCode);
\r
995 r.addChName((chName!=null) ? chName : chCode);
\r
1001 /*******************************************************************************
\r
1003 ******************************************************************************/
\r
1005 private StatusWindow stw = null;
\r
1006 public void setProgressArea(StatusWindow o) { stw = o; }
\r
1007 protected void reportProgress(String msg) {
\r
1008 if (stw != null) {
\r
1011 System.out.println(msg);
\r
1015 protected String getNewId(String response) {
\r
1016 Matcher ma = null;
\r
1017 String newid = null;
\r
1018 ma = Pattern.compile("c1\\[\\d+?\\]=\"(\\d+?)\";").matcher(response);
\r
1019 while (ma.find()) {
\r
1021 String idtmp = ma.group(1);
\r
1023 boolean flag = true;
\r
1024 for (ReserveList rx : getReserves()) {
\r
1025 if (rx.getId().equals(idtmp)) {
\r
1030 if (flag == true) {
\r
1038 /*******************************************************************************
\r
1040 ******************************************************************************/
\r
1042 protected void ShowReserves(ArrayList<ReserveList> ress) {
\r
1044 System.out.println("---Reserved List Start---");
\r
1046 for ( ReserveList e : ress ) {
\r
1048 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
1049 ++i, e.getId(), e.getRec_pattern(), e.getRec_nextdate(), e.getAhh(), e.getAmm(), e.getZhh(), e.getZmm(), e.getRec_min(), e.getContentId(), e.getRec_audio(), e.getTitle(), e.getTitlePop(), e.getChannel(), e.getCh_name(), e.getRecorded()));
\r
1051 System.out.println("---Reserved List End---");
\r
1055 protected void ShowRecorded(ArrayList<RecordedInfo> recs) {
\r
1057 System.out.println("---Recorded List Start---");
\r
1059 for ( RecordedInfo e : recs ) {
\r
1061 System.out.println(String.format("[%s] %s %s\t%s:%s-%s:%s\t%s(%s)\t%s",
\r
1062 ++i, e.getId(), e.getDate(), e.getAhh(), e.getAmm(), e.getZhh(), e.getZmm(), e.getTitle(), e.getCh_name(), e.getResult()));
\r
1064 System.out.println("---Recorded List End---");
\r
1068 /*******************************************************************************
\r
1070 ******************************************************************************/
\r
1072 private final DumpHttp dump = new DumpHttp();
\r
1075 public void wakeup() {
\r
1076 if ( ! getMacAddr().equals("") && ! getBroadcast().equals("")) {
\r
1078 byte[] magic = new byte[102];
\r
1080 for (; i<6; i++) {
\r
1081 magic[i] = (byte) 0xff;
\r
1083 for (int j=0; j<16; j++) {
\r
1084 for (int k=0; k<6; k++) {
\r
1085 short sv = Short.decode("0x"+getMacAddr().substring(k*2,k*2+2));
\r
1086 magic[i++] = (byte)sv;
\r
1092 InetSocketAddress remote = new InetSocketAddress(getBroadcast(), 1234);
\r
1093 DatagramPacket packet = new DatagramPacket(magic, magic.length, remote);
\r
1094 new DatagramSocket().send(packet);
\r
1095 } catch (SocketException e) {
\r
1096 e.printStackTrace();
\r
1097 } catch (IOException e) {
\r
1098 e.printStackTrace();
\r
1102 System.out.println("send magic packet to "+getBroadcast()+","+getMacAddr());
\r
1107 public void shutdown() {
\r
1109 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
\r
1111 reqGET("http://"+getIPAddr()+":"+getPortNo()+"/remote/remote.htm?key=12", null);
\r
1113 System.out.println("send shutdown request to "+getBroadcast()+","+getMacAddr());
\r
1117 public class MyAuthenticator extends Authenticator {
\r
1118 private String username;
\r
1119 private String password;
\r
1121 public MyAuthenticator(String username, String password) {
\r
1122 this.username = username;
\r
1123 this.password = password;
\r
1125 protected PasswordAuthentication getPasswordAuthentication() {
\r
1126 return new PasswordAuthentication(username, password.toCharArray());
\r
1131 public String[] reqGET(String uri, Hashtable<String, String>property) {
\r
1132 return reqGET(uri, property, "MS932");
\r
1134 public String[] reqGET(String uri, Hashtable<String, String>property, String encoding)
\r
1136 //CookieManager manager = new CookieManager();
\r
1137 //CookieHandler.setDefault(manager);
\r
1139 String header = "";
\r
1140 String response = "";
\r
1141 boolean getSuccess = false;
\r
1143 HttpURLConnection conn = null;
\r
1144 BufferedReader reader = null;
\r
1145 InputStreamReader sr = null;
\r
1148 System.out.println("# GET: "+uri);
\r
1149 dump.request("# GET: "+uri);
\r
1153 URL url = new URL(uri);
\r
1154 conn = (HttpURLConnection)url.openConnection();
\r
1155 conn.setRequestMethod("GET");
\r
1156 conn.setConnectTimeout(5*1000);
\r
1157 conn.setReadTimeout(15*1000);
\r
1158 conn.addRequestProperty("User-Agent", userAgent);
\r
1159 if (property != null) {
\r
1160 for (String key : property.keySet()) {
\r
1161 conn.setRequestProperty(key, property.get(key));
\r
1167 Map<String, List<String>> h = conn.getHeaderFields();
\r
1168 for ( String key : h.keySet() ) {
\r
1170 if (key == null) {
\r
1171 header += h.get(key).get(0)+"\n";
\r
1172 Matcher ma = Pattern.compile(" 200 ").matcher(h.get(key).get(0).toString());
\r
1174 getSuccess = true;
\r
1178 header += key+": "+h.get(key).get(0)+"\n";
\r
1182 System.out.println("# Header");
\r
1183 System.out.println(header);
\r
1184 dump.res_header("# Header\n"+header);
\r
1186 if (getSuccess == false) {
\r
1187 // コネクション切断はfinallyで
\r
1188 return(new String[] {header,null});
\r
1192 sr = new InputStreamReader(conn.getInputStream(),encoding);
\r
1193 reader = new BufferedReader(sr);
\r
1196 StringBuilder sb = new StringBuilder();
\r
1197 while ((s = reader.readLine()) != null) {
\r
1202 response = sb.toString();
\r
1204 // コネクション切断はfinallyで
\r
1207 //System.out.printf("# RESPONSE\n%s\n", response);
\r
1208 System.out.println("# DUMP TO FILE: "+dump.res_body("<!-- # RESPONSE -->\n"+response));
\r
1211 return(new String[] {header,response});
\r
1213 catch (UnsupportedEncodingException e) {
\r
1214 System.err.println("[ERROR] レコーダへのアクセスで問題が発生しました(GET): "+e.toString());
\r
1215 if (getSuccess == true) {
\r
1216 return(new String[] {header,null});
\r
1219 catch (IOException e) {
\r
1220 System.err.println("[ERROR] レコーダへのアクセスで問題が発生しました(GET): "+e.toString());
\r
1221 if (getSuccess == true) {
\r
1222 return(new String[] {header,null});
\r
1226 CommonUtils.closing(reader);
\r
1227 CommonUtils.closing(sr);
\r
1228 CommonUtils.closing(conn);
\r
1231 return(new String[] {null,null});
\r
1235 public String[] reqPOST(String uri, String pstr, Hashtable<String, String>property) {
\r
1236 return reqPOST(uri, pstr, property, "MS932");
\r
1238 public String[] reqPOST(String uri, String pstr, Hashtable<String, String>property, String encoding)
\r
1240 //CookieManager manager = new CookieManager();
\r
1241 //CookieHandler.setDefault(manager);
\r
1243 boolean postSuccess = false;
\r
1244 String header = "";
\r
1245 String response = "";
\r
1247 HttpURLConnection conn = null;
\r
1248 OutputStreamWriter writer = null;
\r
1249 BufferedReader reader = null;
\r
1250 InputStreamReader sr = null;
\r
1253 System.out.println("# POST: "+uri+"?"+pstr);
\r
1254 dump.request("# POST: "+uri+"?"+pstr);
\r
1257 URL url = new URL(uri);
\r
1258 conn = (HttpURLConnection)url.openConnection();
\r
1259 conn.setRequestMethod("POST");
\r
1260 conn.setConnectTimeout(5*1000);
\r
1261 conn.setReadTimeout(15*1000);
\r
1262 conn.setDoOutput(true);
\r
1263 conn.addRequestProperty("User-Agent", userAgent);
\r
1264 if (property != null) {
\r
1265 for (String key : property.keySet()) {
\r
1266 conn.setRequestProperty(key, property.get(key));
\r
1272 writer = new OutputStreamWriter(conn.getOutputStream(),encoding);
\r
1273 writer.write(pstr);
\r
1277 Map<String, List<String>> h = conn.getHeaderFields();
\r
1278 for ( String key : h.keySet() ) {
\r
1280 if (key == null) {
\r
1281 header += h.get(key).get(0)+"\n";
\r
1282 Matcher ma = Pattern.compile(" 200 ").matcher(h.get(key).get(0).toString());
\r
1284 postSuccess = true;
\r
1288 header += key+": "+h.get(key).get(0)+"\n";
\r
1292 System.out.println("# Header");
\r
1293 System.out.println(header);
\r
1294 dump.res_header("# Header\n"+header);
\r
1296 if (postSuccess == false) {
\r
1297 // コネクション切断はfinallyで
\r
1298 return(new String[] {header,null});
\r
1301 sr = new InputStreamReader(conn.getInputStream(),encoding);
\r
1302 reader = new BufferedReader(sr);
\r
1305 StringBuilder sb = new StringBuilder();
\r
1306 while ((s = reader.readLine()) != null) {
\r
1311 response = sb.toString();
\r
1313 // コネクション切断はfinallyで
\r
1316 //System.out.printf("# RESPONSE\n%s\n", response);
\r
1317 System.out.println("# DUMP TO FILE: "+dump.res_body("<!-- # RESPONSE -->\n"+response));
\r
1320 return(new String[] {header,response});
\r
1322 catch (UnsupportedEncodingException e) {
\r
1323 System.err.println("[ERROR] レコーダへのアクセスで問題が発生しました(POST): "+e.toString());
\r
1324 if (postSuccess == true) {
\r
1325 return(new String[] {header,null});
\r
1328 catch (IOException e) {
\r
1329 System.err.println("[ERROR] レコーダへのアクセスで問題が発生しました(POST): "+e.toString());
\r
1330 if (postSuccess == true) {
\r
1331 return(new String[] {header,null});
\r
1335 CommonUtils.closing(writer);
\r
1336 CommonUtils.closing(reader);
\r
1337 CommonUtils.closing(sr);
\r
1338 CommonUtils.closing(conn);
\r
1341 return(new String[] {null,null});
\r
1344 /*******************************************************************************
\r
1345 * ここから下は該当機能が無効なプラグイン用のダミー
\r
1346 ******************************************************************************/
\r
1349 public RecType getType() {
\r
1353 public ChannelCode getChCode() {
\r
1357 public boolean ChangeChannel(String Channel) {
\r
1361 public boolean GetRdSettings(boolean force) {
\r
1365 public boolean GetRdReserve(boolean force) {
\r
1369 public boolean GetRdAutoReserve(boolean force) {
\r
1374 public boolean GetRdReserveDetails() {
\r
1378 public boolean GetRdRecorded(boolean force) {
\r
1382 public boolean PostRdEntry(ReserveList r) {
\r
1386 public boolean UpdateRdEntry(ReserveList o, ReserveList r) {
\r
1390 public ReserveList RemoveRdEntry(String delno) {
\r
1394 public String getErrmsg() {
\r