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 CommonUtils.FieldCopy(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 isRepeatReserveSupported() { return true; }
\r
57 public boolean isPursuesEditable() { return false; }
\r
59 public boolean isAutocompleteSupported() { return true; }
\r
61 public boolean isChangeChannelSupported() { return ChangeChannel(null); }
\r
63 public boolean isBackgroundOnly() { return false; }
\r
65 public boolean isChValueAvailable() { return false; }
\r
67 public boolean isChCodeNeeded() { return true; }
\r
69 public boolean isRecChNameNeeded() { return true; }
\r
71 public boolean isBroadcastTypeNeeded() { return false; }
\r
73 public boolean isAutoEncSelectEnabled() { return true; }
\r
75 public String getChDatHelp() { return ""; }
\r
77 // フリーテキストによるオプション指定
\r
79 public boolean setOptString(String s) { return true; } // ダミー
\r
81 public String getOptString() { return null; } // ダミー
\r
84 /*******************************************************************************
\r
86 ******************************************************************************/
\r
89 private static final String MSGID = "[レコーダ共通] ";
\r
90 private static final String DBGID = "[DEBUG]"+MSGID;
\r
91 private static final String ERRID = "[ERROR]"+MSGID;
\r
94 /*******************************************************************************
\r
96 ******************************************************************************/
\r
99 public void setDebug(boolean b) { debug = b; }
\r
100 protected boolean getDebug() { return debug; }
\r
101 private boolean debug = false;
\r
103 // 終了時刻と開始時刻が重なる番組を重複扱いするか
\r
104 public void setAdjNotRep(boolean b) { adjnotrep = b; }
\r
105 private boolean getAdjNotRep() { return adjnotrep; }
\r
106 private boolean adjnotrep = false;
\r
109 public void setUseCalendar(boolean b) { usecalendar = b; }
\r
110 public boolean getUseCalendar() { return usecalendar; }
\r
111 private boolean usecalendar = true;
\r
114 public void setUseChChange(boolean b) { usechchange = b; }
\r
115 public boolean getUseChChange() { return usechchange; }
\r
116 private boolean usechchange = true;
\r
119 public void setRecordedCheckScope(int n) { recordedCheckScope = n; }
\r
120 protected int getRecordedCheckScope() { return recordedCheckScope; }
\r
121 private int recordedCheckScope = 14;
\r
124 public void setRecordedSaveScope(int n) { recordedSaveScope = n; }
\r
125 protected int getRecordedSaveScope() { return recordedSaveScope; }
\r
126 private int recordedSaveScope = 90;
\r
128 // HTTPアクセス時のUser-Agent
\r
129 public void setUserAgent(String s) { userAgent = s; }
\r
130 //public String getUserAgent() { return userAgent; }
\r
131 private String userAgent = "";
\r
134 /*******************************************************************************
\r
136 ******************************************************************************/
\r
138 public String Myself() { return(getIPAddr()+":"+getPortNo()+":"+getRecorderId()); }
\r
139 public boolean isMyself(String myself) { return Myself().equals(myself); }
\r
141 protected ArrayList<TextValueSet> vrate = new ArrayList<TextValueSet>();
\r
142 protected ArrayList<TextValueSet> arate = new ArrayList<TextValueSet>();
\r
143 protected ArrayList<TextValueSet> folder = new ArrayList<TextValueSet>();
\r
144 protected ArrayList<TextValueSet> encoder = new ArrayList<TextValueSet>();
\r
145 protected ArrayList<TextValueSet> dvdcompat = new ArrayList<TextValueSet>();
\r
146 protected ArrayList<TextValueSet> device = new ArrayList<TextValueSet>();
\r
147 protected ArrayList<TextValueSet> channel = new ArrayList<TextValueSet>();
\r
148 protected ArrayList<TextValueSet> xchapter = new ArrayList<TextValueSet>();
\r
149 protected ArrayList<TextValueSet> mschapter = new ArrayList<TextValueSet>();
\r
150 protected ArrayList<TextValueSet> mvchapter = new ArrayList<TextValueSet>();
\r
151 protected ArrayList<TextValueSet> chvalue = new ArrayList<TextValueSet>();
\r
152 protected ArrayList<TextValueSet> chtype = new ArrayList<TextValueSet>();
\r
153 protected ArrayList<TextValueSet> genre = new ArrayList<TextValueSet>();
\r
155 protected ArrayList<TextValueSet> aspect = new ArrayList<TextValueSet>();
\r
156 protected ArrayList<TextValueSet> bvperf = new ArrayList<TextValueSet>();
\r
157 protected ArrayList<TextValueSet> lvoice = new ArrayList<TextValueSet>();
\r
158 protected ArrayList<TextValueSet> autodel = new ArrayList<TextValueSet>();
\r
160 public ArrayList<TextValueSet> getVideoRateList() { return(vrate); }
\r
161 public ArrayList<TextValueSet> getAudioRateList() { return(arate); }
\r
162 public ArrayList<TextValueSet> getFolderList() { return(folder); }
\r
163 public ArrayList<TextValueSet> getEncoderList() { return(encoder); }
\r
164 public ArrayList<TextValueSet> getDVDCompatList() { return(dvdcompat); }
\r
165 public ArrayList<TextValueSet> getDeviceList() { return(device); }
\r
166 public ArrayList<TextValueSet> getXChapter() { return(xchapter); }
\r
167 public ArrayList<TextValueSet> getMsChapter() { return(mschapter); }
\r
168 public ArrayList<TextValueSet> getMvChapter() { return(mvchapter); }
\r
169 public ArrayList<TextValueSet> getChValue() { return(chvalue); }
\r
170 public ArrayList<TextValueSet> getChType() { return(chtype); }
\r
172 public ArrayList<TextValueSet> getAspect() { return(aspect); }
\r
173 public ArrayList<TextValueSet> getBVperf() { return(bvperf); }
\r
174 public ArrayList<TextValueSet> getLVoice() { return(lvoice); }
\r
175 public ArrayList<TextValueSet> getAutodel() { return(autodel); }
\r
177 public String getLabel_Videorate() { return null; }
\r
178 public String getLabel_Audiorate() { return null; }
\r
179 public String getLabel_Folder() { return null; }
\r
180 public String getLabel_Device() { return null; }
\r
181 public String getLabel_DVDCompat() { return null; }
\r
182 public String getLabel_XChapter() { return null; }
\r
183 public String getLabel_MsChapter() { return null; }
\r
184 public String getLabel_MvChapter() { return null; }
\r
185 public String getLabel_Aspect() { return null; }
\r
186 public String getLabel_BVperf() { return null; }
\r
187 public String getLabel_LVoice() { return null; }
\r
188 public String getLabel_Autodel() { return null; }
\r
190 /*******************************************************************************
\r
192 ******************************************************************************/
\r
194 public String getRecorderId() { return "THIS IS DUMMY METHOD"; }
\r
196 private String recorderIPAddr = "";
\r
197 private String recorderPortNo = "";
\r
198 private String recorderUser = "";
\r
199 private String recorderPasswd = "";
\r
200 private String recorderMacAddr = "";
\r
201 private String recorderBroadcast = "";
\r
202 private int recorderTunerNum = 0;
\r
204 public String getIPAddr() { return recorderIPAddr; }
\r
205 public void setIPAddr(String s) { recorderIPAddr = s; }
\r
206 public String getPortNo() { return recorderPortNo; }
\r
207 public void setPortNo(String s) { recorderPortNo = s; }
\r
208 public String getUser() { return recorderUser; }
\r
209 public void setUser(String s) { recorderUser = s; }
\r
210 public String getPasswd() { return recorderPasswd; }
\r
211 public void setPasswd(String s) { recorderPasswd = s; }
\r
212 public String getMacAddr() { return recorderMacAddr; }
\r
213 public void setMacAddr(String s) { recorderMacAddr = s; }
\r
214 public String getBroadcast() { return recorderBroadcast; }
\r
215 public void setBroadcast(String s) { recorderBroadcast = s; }
\r
216 public int getTunerNum() { return recorderTunerNum; }
\r
217 public void setTunerNum(int n) { recorderTunerNum = n; }
\r
220 public String getColor(String tuner) {
\r
222 if (tuner != null && tuner.length() != 0) {
\r
224 for (TextValueSet e : getEncoderList()) {
\r
225 if (tuner.equals(e.getText())) {
\r
226 if (recorderColorList.size() > idx) {
\r
227 return recorderColorList.get(idx);
\r
234 // 適当なエンコーダが見つからない場合は既定値
\r
235 return recorderColorList.get(0);
\r
238 // Envからもらってきたものを分解して保持する
\r
239 public void setColor(String s) {
\r
241 recorderColorList.clear();
\r
244 ma = Pattern.compile("^#......$").matcher(s);
\r
246 recorderColorList.add(s);
\r
249 ma = Pattern.compile("(#......);").matcher(s);
\r
250 while (ma.find()) {
\r
251 recorderColorList.add(ma.group(1));
\r
257 public ArrayList<String> getColors() { return recorderColorList; }
\r
259 private ArrayList<String> recorderColorList = new ArrayList<String>();
\r
264 public ReserveList getReserveList(String rsvId) {
\r
265 for ( ReserveList rsv : RESERVES ) {
\r
266 if ( rsv.getId() != null && rsv.getId().equals(rsvId) ) {
\r
274 * 持っている予約をすべて…吐き出させるっ…!
\r
276 public ArrayList<ReserveList> getReserves() { return RESERVES; }
\r
278 private ArrayList<ReserveList> RESERVES = new ArrayList<ReserveList>();
\r
283 public ArrayList<RecordedInfo> getRecorded() { return RECORDED; }
\r
284 protected void setRecorded(ArrayList<RecordedInfo> r ) { RECORDED = r; }
\r
286 private ArrayList<RecordedInfo> RECORDED = new ArrayList<RecordedInfo>();
\r
288 /*******************************************************************************
\r
290 ******************************************************************************/
\r
292 // 素直にHashMapつかっておけばよかった
\r
293 public String text2value(ArrayList<TextValueSet> tvs, String text) {
\r
294 for ( TextValueSet t : tvs ) {
\r
295 if (t.getText().equals(text)) {
\r
296 return(t.getValue());
\r
301 public String value2text(ArrayList<TextValueSet> tvs, String value) {
\r
302 for ( TextValueSet t : tvs ) {
\r
303 if (t.getValue().equals(value)) {
\r
304 return(t.getText());
\r
310 protected TextValueSet add2tvs(ArrayList<TextValueSet> tvs, String text, String value) {
\r
311 TextValueSet t = new TextValueSet();
\r
317 protected TextValueSet add2tvs(int n, ArrayList<TextValueSet> tvs, String text, String value) {
\r
318 TextValueSet t = new TextValueSet();
\r
325 // 予約日付をId化する(単日以外)
\r
326 protected int getRec_pattern_Id(String s) {
\r
328 for (; i<HDDRecorder.RPTPTN.length;i++) {
\r
329 //System.out.println(s + "->" + HDDRecorder.RPTPTN[i]);
\r
330 if (s.equals(HDDRecorder.RPTPTN[i])) {
\r
337 /* 予約IDが動的に変化するレコーダ向けの処理 */
\r
338 private int rsvcnt = 0;
\r
339 protected String getUniqId(String rsvId) { return (!rsvId.startsWith("U$"))?(String.format("U$%14s,%05d,%s",CommonUtils.getDateTimeYMD(0),(rsvcnt++)%100000,rsvId)):(rsvId); }
\r
340 protected String getRsvId(String uniqId) { return (uniqId.startsWith("U$"))?(uniqId.substring(23)):(uniqId); }
\r
344 public void getStartEndDateTime(ReserveList r) {
\r
346 GregorianCalendar c = CommonUtils.getCalendar(r.getRec_nextdate());
\r
348 // ★★★ MM/DDをYYYY/MM/DDに戻す? ★★★
\r
349 c.set(Calendar.MINUTE, Integer.valueOf(r.getAmm()));
\r
350 c.set(Calendar.HOUR_OF_DAY, Integer.valueOf(r.getAhh()));
\r
351 r.setStartDateTime(CommonUtils.getDateTime(c));
\r
353 c.add(Calendar.MINUTE, Integer.valueOf(r.getRec_min()));
\r
354 r.setEndDateTime(CommonUtils.getDateTime(c));
\r
359 public String[] _mmdd2yyyymmdd(String mm, String dd)
\r
361 GregorianCalendar c = new GregorianCalendar();
\r
362 c.setTime(new Date());
\r
363 if ( Integer.valueOf(mm) < c.get(Calendar.MONTH)+1 ) {
\r
364 c.add(Calendar.YEAR, 1);
\r
367 return (new String[] { String.format("%04d",c.get(Calendar.YEAR)), mm, dd });
\r
371 public String[] _hhmm2hhmm_min(String ahhmm, String zhhmm)
\r
378 Matcher ma = Pattern.compile("^(\\d+):(\\d+)").matcher(ahhmm);
\r
380 ahh = String.format("%02d",Integer.valueOf(ma.group(1)));
\r
381 amm = String.format("%02d",Integer.valueOf(ma.group(2)));
\r
384 ma = Pattern.compile("^(\\d+):(\\d+)").matcher(zhhmm);
\r
386 zhh = String.format("%02d",Integer.valueOf(ma.group(1)));
\r
387 zmm = String.format("%02d",Integer.valueOf(ma.group(2)));
\r
390 int min = Integer.valueOf(zhh)*60+Integer.valueOf(zmm) - (Integer.valueOf(ahh)*60+Integer.valueOf(amm));
\r
391 if ( min < 0 ) min += 24*60;
\r
393 return (new String[] {ahh, amm, zhh, zmm, Integer.toString(min)});
\r
396 // レコーダの設定情報をキャッシュする
\r
397 public ArrayList<TextValueSet> TVSload(String filename) {
\r
398 File f = new File(filename);
\r
399 if ( ! f.exists() ) {
\r
400 return new ArrayList<TextValueSet>();
\r
403 @SuppressWarnings("unchecked")
\r
404 ArrayList<TextValueSet> ar = (ArrayList<TextValueSet>) CommonUtils.readXML(filename);
\r
405 if ( ar == null ) {
\r
406 System.err.println("設定ファイルの読み込みに失敗しました: "+filename);
\r
407 return new ArrayList<TextValueSet>();
\r
412 public void TVSsave(ArrayList<TextValueSet> ar, String filename) {
\r
413 if ( ! CommonUtils.writeXML(filename, ar) ) {
\r
414 System.err.println("設定ファイルの保存に失敗しました: "+filename);
\r
419 * レコーダの予約リストをキャッシュする
\r
421 * @return nullは返さない!
\r
422 * @see #ReservesToFile(ArrayList, String)
\r
424 protected ArrayList<ReserveList> ReservesFromFile(String rsvedFile) {
\r
425 File f = new File(rsvedFile);
\r
426 if ( ! f.exists() ) {
\r
427 System.out.println("+予約キャッシュはありません: "+rsvedFile);
\r
428 return new ArrayList<ReserveList>();
\r
431 @SuppressWarnings("unchecked")
\r
432 ArrayList<ReserveList> tmp = (ArrayList<ReserveList>) CommonUtils.readXML(rsvedFile);
\r
433 if ( tmp == null ) {
\r
434 System.err.println("予約キャッシュの読み込みに失敗しました: "+rsvedFile);
\r
435 return new ArrayList<ReserveList>();
\r
440 for (ReserveList r : tmp) {
\r
441 if (r.getId() == null && r.getNo() > 0) {
\r
442 r.setId(String.valueOf(r.getNo()));
\r
447 System.out.println("+予約キャッシュを読み込みました("+tmp.size()+"): "+rsvedFile);
\r
454 * @see #ReservesFromFile(String)
\r
456 protected void ReservesToFile(ArrayList<ReserveList> reserves, String rsvedFile) {
\r
457 if ( ! CommonUtils.writeXML(rsvedFile, reserves) ) {
\r
458 System.err.println("予約キャッシュの保存に失敗しました: "+rsvedFile);
\r
463 * レコーダの録画結果リストをキャッシュする<BR>
\r
464 * ※キャッシュから取得したものはIDがnullでクリアされる
\r
466 * @return nullは返さない!
\r
467 * @see #RecordedToFile(ArrayList, String)
\r
469 protected ArrayList<RecordedInfo> RecordedFromFile(String recedFile) {
\r
471 File f = new File(recedFile);
\r
472 if ( ! f.exists() ) {
\r
473 System.out.println("+録画結果キャッシュはありません: "+recedFile);
\r
474 return new ArrayList<RecordedInfo>();
\r
477 @SuppressWarnings("unchecked")
\r
478 ArrayList<RecordedInfo> tmp = (ArrayList<RecordedInfo>) CommonUtils.readXML(recedFile);
\r
479 if ( tmp == null ) {
\r
480 System.err.println("録画結果キャッシュの読み込みに失敗しました: "+recedFile);
\r
481 return new ArrayList<RecordedInfo>();
\r
485 String critDate = CommonUtils.getDate(CommonUtils.getCalendar(-86400*getRecordedSaveScope()));
\r
486 String specialDate = CommonUtils.getDate(CommonUtils.getCalendar("1970/01/01"));
\r
487 for ( int i=tmp.size()-1; i>=0; i-- ) {
\r
488 if ( tmp.get(i).getDate().compareTo(critDate) < 0 && tmp.get(i).getDate().compareTo(specialDate) > 0) {
\r
490 if (debug) System.out.println("録画結果のキャッシュを削除しました: "+tmp.get(i).getDate()+" "+tmp.get(i).getTitle());
\r
499 for ( RecordedInfo ri : tmp ) {
\r
500 // キャッシュから読みだしたものはIDをクリアする
\r
503 if ( ri.getCh_orig() == null ) {
\r
504 ri.setCh_orig(ri.getCh_name());
\r
508 System.out.println("+録画結果キャッシュを読み込みました("+tmp.size()+"件): "+recedFile);
\r
515 * @see #RecordedToFile(ArrayList, String)
\r
517 protected void RecordedToFile(ArrayList<RecordedInfo> recorded, String recedFile) {
\r
518 if ( ! CommonUtils.writeXML(recedFile, recorded) ) {
\r
519 System.err.println("録画結果キャッシュの保存に失敗しました: "+recedFile);
\r
526 protected boolean matchReserveV1(ReserveList n, ReserveList o) {
\r
528 n.getTitle().equals(o.getTitle()) &&
\r
529 n.getChannel().equals(o.getChannel()) &&
\r
530 n.getRec_pattern().equals(o.getRec_pattern()) &&
\r
531 n.getAhh().equals(o.getAhh()) && n.getAmm().equals(o.getAmm())
\r
534 public void setReservesV1(ArrayList<ReserveList> r) {
\r
535 // ライン入力のチャンネル名を保持する
\r
536 //System.out.println(RESERVES.size()+","+r.size());
\r
537 for (ReserveList o : RESERVES) {
\r
538 for (ReserveList n : r) {
\r
539 if (matchReserveV1(n, o)) {
\r
541 if (o.getCh_name() != null && n.getCh_name() != null && n.getCh_name().startsWith("外部入力")) {
\r
542 System.out.println("外部入力を次の放送局で置き換えます: "+n.getCh_name()+"->"+o.getCh_name());
\r
543 n.setCh_name(o.getCh_name());
\r
547 n.setAutocomplete(o.getAutocomplete());
\r
549 n.setDetail(o.getDetail());
\r
550 n.setRec_genre(o.getRec_genre());
\r
551 n.setRec_device(o.getRec_device());
\r
552 n.setRec_folder(o.getRec_folder());
\r
553 n.setRec_dvdcompat(o.getRec_dvdcompat());
\r
554 n.setRec_xchapter(o.getRec_xchapter());
\r
555 n.setRec_mschapter(o.getRec_mschapter());
\r
556 n.setRec_mvchapter(o.getRec_mvchapter());
\r
558 n.setRec_aspect(o.getRec_aspect());
\r
559 n.setRec_bvperf(o.getRec_bvperf());
\r
560 n.setRec_lvoice(o.getRec_lvoice());
\r
561 n.setRec_autodel(o.getRec_autodel());
\r
570 public void setReserves(ArrayList<ReserveList> r) {
\r
571 // ライン入力のチャンネル名を保持する
\r
572 for (ReserveList o : RESERVES) {
\r
573 for (ReserveList n : r) {
\r
575 if (o.getCh_name() != null && n.getCh_name() != null && n.getCh_name().startsWith("外部入力")) {
\r
576 if (o.getId() == n.getId() && o.getChannel().equals(n.getChannel())) {
\r
577 System.out.println("外部入力を次の放送局で置き換えます: "+n.getCh_name()+"->"+o.getCh_name());
\r
578 n.setCh_name(o.getCh_name());
\r
585 if ( getTunerNum() >= 2 ) {
\r
589 ArrayList<ReserveList> s = new ArrayList<ReserveList>();
\r
590 for ( ReserveList o : r ) {
\r
592 for ( int i=0; i<s.size(); i++ ) {
\r
593 if ( o.getStartDateTime().compareTo(s.get(i).getStartDateTime()) < 0 ) {
\r
609 for ( int x=0; x<s.size(); x++ ) {
\r
611 ArrayList<String> tuns = new ArrayList<String>();
\r
612 for ( TextValueSet enc : encoder ) {
\r
613 tuns.add(enc.getText());
\r
615 // 残っているチューナーをリストアップする
\r
616 for ( int y=0; y<s.size() && tuns.size()>0; y++ ) {
\r
617 if ( x == y || s.get(y).getTuner().equals("") ) {
\r
618 // 自分自身と、チューナー番号が振られていない相手はスルー
\r
621 // 時間が重なっている予約が既に使用しているチューナーは除外する
\r
622 ArrayList<String> starts = new ArrayList<String>();
\r
623 ArrayList<String> ends = new ArrayList<String>();
\r
624 CommonUtils.getStartEndList(starts, ends, s.get(y));
\r
625 for ( int z=0; z<starts.size(); z++ ) {
\r
626 // 帯予約を正しく処理するために全予約日時をなめるようにする
\r
627 if ( CommonUtils.isOverlap(s.get(x).getStartDateTime(), s.get(x).getEndDateTime(), starts.get(z), ends.get(z), getAdjNotRep()) ) {
\r
628 tuns.remove(s.get(y).getTuner());
\r
634 if ( tuns.size() == 0 ) {
\r
636 s.get(x).setTuner(encoder.get(0).getText());
\r
639 // 余っているならそのうちの最初のものを使用
\r
640 s.get(x).setTuner(tuns.get(0));
\r
644 else if ( getTunerNum() == 1 ) {
\r
646 for ( int x=0; x<r.size(); x++ ) {
\r
647 r.get(x).setTuner("■");
\r
658 public void refreshReserves() {
\r
660 String curDateTime = CommonUtils.getCritDateTime();
\r
662 for (int i=RESERVES.size()-1; i>=0; i--) {
\r
663 ReserveList r = RESERVES.get(i);
\r
664 if (r.getRec_pattern_id() == HDDRecorder.RPTPTN_ID_BYDATE) {
\r
666 if (r.getEndDateTime().compareTo(curDateTime) < 0) {
\r
668 RESERVES.remove(r);
\r
673 String nextDate = CommonUtils.getNextDate(r);
\r
674 r.setRec_nextdate(nextDate);
\r
685 protected ArrayList<ReserveList> decodeReservedList(String response) {
\r
687 ArrayList<ReserveList> newReserveList = new ArrayList<ReserveList>();
\r
689 Matcher ma = Pattern.compile("(c1\\[\\d+?\\]=[\\s\\S]+?\";)\\n").matcher(response);
\r
690 while ( ma.find() ) {
\r
692 ReserveList entry = new ReserveList();
\r
696 String[] d = new String[17];
\r
697 mb = Pattern.compile("c\\d+?\\[\\d+?\\]=\"(.*?)\";").matcher(ma.group(1));
\r
698 for (int i=0; i<d.length; i++) {
\r
700 d[i] = mb.group(1);
\r
702 //System.out.println(i+") "+d[i]);
\r
706 if (d[1].equals("2")) {
\r
707 entry.setExec(false);
\r
711 //if (d[12].equals("0") || d[12].equals("4") || d[12].equals("3")) {
\r
712 if (d[12].equals("4")) {
\r
713 entry.setPursues(true);
\r
717 entry.setRec_device(d[8]);
\r
720 String title = CommonUtils.unEscape(d[2]).replaceAll("<BR>","");
\r
726 entry.setRec_pattern(d[5]);
\r
727 entry.setRec_pattern_id(getRec_pattern_Id(entry.getRec_pattern()));
\r
728 mb = Pattern.compile("(\\d\\d):(\\d\\d).*?(\\d\\d):(\\d\\d)").matcher(d[6]+"-"+d[7]);
\r
730 entry.setAhh(mb.group(1));
\r
731 entry.setAmm(mb.group(2));
\r
732 entry.setZhh(mb.group(3));
\r
733 entry.setZmm(mb.group(4));
\r
735 entry.setRec_nextdate(CommonUtils.getNextDate(entry));
\r
736 //entry.setRec_nextdate(getNextDate(entry.getRec_pattern(), entry.getZhh()+":"+entry.getZmm()));
\r
737 entry.setRec_min(CommonUtils.getRecMin(entry.getAhh(), entry.getAmm(), entry.getZhh(), entry.getZmm()));
\r
738 getStartEndDateTime(entry);
\r
741 if (d[3].equals("18") || d[3].equals("10") || d[3].equals("9")) {
\r
742 entry.setTuner("TS2");
\r
744 else if (d[3].equals("17") || d[3].equals("12") || d[3].equals("11")) {
\r
745 entry.setTuner("TS1");
\r
747 else if (d[3].equals("16") || d[3].equals("7")) {
\r
748 entry.setTuner("RE");
\r
751 entry.setTuner("--");
\r
755 if (d[10].equals(" ")) {
\r
756 if (d[9].equals("A1")) {
\r
757 d[9] = "[TSE] AT 4.7GB";
\r
759 else if (d[9].equals("A2")) {
\r
760 d[9] = "[TSE] AT 9.4GB";
\r
762 else if (d[9].equals("DL")) {
\r
763 d[9] = "[TSE] AT 8.5GB";
\r
766 Matcher mc = Pattern.compile("^MN").matcher(d[9]);
\r
768 d[9] = mc.replaceFirst("[TSE] ");
\r
773 if (d[9].equals("A1")) {
\r
774 d[9] = "[VR] AT 4.7GB";
\r
776 else if (d[9].equals("A2")) {
\r
777 d[9] = "[VR] AT 9.4GB";
\r
779 else if (d[9].equals("DL")) {
\r
780 d[9] = "[VR] AT 8.5GB";
\r
783 Matcher mc = Pattern.compile("^MN").matcher(d[9]);
\r
785 d[9] = mc.replaceFirst("[VR] ");
\r
787 else if ( d[9].startsWith("SP") || d[9].startsWith("LP")) {
\r
788 d[9] = "[VR] "+d[9];
\r
793 if (d[9].equals("TS")) {
\r
794 entry.setRec_mode("[TS]");
\r
797 entry.setRec_mode(d[9]);
\r
800 entry.setTitle(title);
\r
801 entry.setTitlePop(TraceProgram.replacePop(title));
\r
802 //entry.setCh_name(getChCode().getCH_NO2NAME(d[4])); // 機種固有領域に移動
\r
803 entry.setChannel(d[4]);
\r
805 entry.setRec_audio(d[10]);
\r
806 //entry.rec_folder = data.get(); // 予約一覧からはとれない
\r
807 //entry.rec_genre = data.get(); // 予約一覧からはとれない
\r
810 newReserveList.add(entry.clone());
\r
812 return(newReserveList);
\r
816 * レコーダーから取得できない情報は直接コピー(既存のリストから探して)
\r
818 protected void copyAttributes(ReserveList to, ArrayList<ReserveList> fromlist) {
\r
819 ReserveList olde = null;
\r
820 for ( ReserveList from : fromlist ) {
\r
821 if ( from.getId() != null && from.getId().equals(to.getId()) ) {
\r
822 copyAttribute(to, olde = from);
\r
827 // DIGAの終了時間"未定"対応だけど、別にDIGAかどうか確認したりはしない。
\r
828 setAttributesDiga(to,olde);
\r
832 * レコーダーから取得できない情報は直接コピー(既存エントリから直に)
\r
834 protected void copyAttribute(ReserveList to, ReserveList from) {
\r
836 to.setAutocomplete(from.getAutocomplete());
\r
838 to.setDetail(from.getDetail());
\r
839 to.setRec_genre(from.getRec_genre());
\r
840 //n.setRec_device(o.getRec_device());
\r
841 to.setRec_folder(from.getRec_folder());
\r
842 to.setRec_dvdcompat(from.getRec_dvdcompat());
\r
843 to.setRec_xchapter(from.getRec_xchapter());
\r
844 to.setRec_mschapter(from.getRec_mschapter());
\r
845 to.setRec_mvchapter(from.getRec_mvchapter());
\r
847 to.setRec_aspect(from.getRec_aspect());
\r
848 to.setRec_bvperf(from.getRec_bvperf());
\r
849 to.setRec_lvoice(from.getRec_lvoice());
\r
850 to.setRec_autodel(from.getRec_autodel());
\r
851 // BZ700以降の取得一覧から取得できない画質の対応
\r
852 if (to.getRec_mode().equals("")) {
\r
853 to.setRec_mode(from.getRec_mode());
\r
857 protected void setAttributesDiga(ReserveList to, ReserveList from) {
\r
858 if ( to.getZhh() != null && to.getZmm() != null && to.getRec_min() != null ) {
\r
863 if ( from != null && from.getZhh() != null ) {
\r
865 to.setZhh(from.getZhh());
\r
866 to.setZmm(from.getZmm());
\r
867 to.setRec_min(from.getRec_min());
\r
868 to.setRec_nextdate(CommonUtils.getNextDate(to));
\r
869 getStartEndDateTime(to);
\r
874 // 現在時刻から30分後か、開始時刻から1時間後の、どちらか短い方に強制設定する
\r
875 String curTM = CommonUtils.getTime(30);
\r
876 String endTM = String.format("%02d:%s", (Integer.valueOf(to.getAhh())+1)%24,to.getAmm());
\r
877 if ( curTM.compareTo(endTM) > 0 ) {
\r
880 to.setZhh(endTM.substring(0,2));
\r
881 to.setZmm(endTM.substring(3,5));
\r
882 to.setRec_min(CommonUtils.getRecMin(to.getAhh()+":"+to.getAmm(), endTM));
\r
885 // 開始時刻から1時間後に強制設定する
\r
886 to.setZhh(String.format("%02d", (Integer.valueOf(to.getAhh())+1)%24));
\r
887 to.setZmm(to.getAmm());
\r
888 to.setRec_min("60");
\r
890 to.setRec_nextdate(CommonUtils.getNextDate(to));
\r
891 getStartEndDateTime(to);
\r
897 protected void setRecordedFlag() {
\r
899 // 過去X日分までチェック(初期値は14日)
\r
900 final String critDateTime = CommonUtils.getDateTimeW(-86400*getRecordedCheckScope());
\r
902 for ( ReserveList reserved : RESERVES ) {
\r
903 reserved.setRecorded(false);
\r
906 for ( RecordedInfo recorded : RECORDED ) {
\r
907 if ( critDateTime.compareTo(recorded.getDate()+" "+recorded.getAhh()+":"+recorded.getAmm()) > 0 ) {
\r
910 String chktitle = recorded.getTitle().replaceFirst(TVProgram.titlePrefixRemoveExpr, "");
\r
911 for ( ReserveList reserved : RESERVES ) {
\r
912 if ( reserved.getRecorded() ) {
\r
913 // 既にフラグが立ってるものはスルー
\r
916 if ( reserved.getRec_pattern_id() != HDDRecorder.RPTPTN_ID_BYDATE ) {
\r
920 String restitle = reserved.getTitle().replaceFirst(TVProgram.titlePrefixRemoveExpr, "");
\r
921 boolean chchk = (recorded.getChannel() != null && recorded.getChannel().length() > 0) ? (recorded.getChannel().equals(reserved.getChannel())) : (true);
\r
922 if ( recorded.getSucceeded() && recorded.getDrop_mpeg() == 0 && chchk && chktitle.equals(restitle) ) {
\r
923 // 成功していて、放送局とタイトルが一致
\r
924 reserved.setRecorded(true);
\r
932 * @param newRecordedList
\r
935 protected RecordedInfo addRecorded(ArrayList<RecordedInfo> newRecordedList, RecordedInfo entry) {
\r
937 String endt = entry.getDate()+entry.getAhh()+entry.getAmm();
\r
941 for ( ; n<newRecordedList.size(); n++ ) {
\r
942 RecordedInfo ri = newRecordedList.get(n);
\r
943 String ridt = ri.getDate()+ri.getAhh()+ri.getAmm();
\r
944 int result = ridt.compareTo(endt);
\r
945 if ( result == 0 ) {
\r
947 // 開始時刻が同じ情報を発見したら、最終的にはそれの前に差し込みたいので、nを保存する
\r
952 if ( ri.getId() == null ) {
\r
953 // キャッシュから取得したものだった場合に重複チェックする
\r
954 if ( ri.getTitle().equals(entry.getTitle()) && ri.getCh_orig().equals(entry.getCh_orig()) && ri.getLength() == entry.getLength()/* && ri.getDrop() == entry.getDrop()*/ ) {
\r
956 System.out.println(MSGID+"録画結果はすでにキャッシュ上に存在していたようです: "+endt+" "+entry.getTitle());
\r
960 if (getDebug()) System.out.println(DBGID+"よく似た録画結果です: "+endt+" "+entry.getTitle()+" <-> "+ridt+ri.getTitle());
\r
964 else if ( result < 0 ) {
\r
969 entry.setDrop_mpeg(entry.getDrop()-entry.getDrop_mpeg());
\r
971 newRecordedList.add((dn!=-1)?(dn):(n),entry);
\r
973 if (getDebug()) System.out.println(DBGID+"録画結果を追加しました: "+endt+" "+entry.getTitle());
\r
978 /*******************************************************************************
\r
980 ******************************************************************************/
\r
982 private StatusWindow stw = null;
\r
983 public void setProgressArea(StatusWindow o) { stw = o; }
\r
984 protected void reportProgress(String msg) {
\r
988 System.out.println(msg);
\r
992 protected String getNewId(String response) {
\r
994 String newid = null;
\r
995 ma = Pattern.compile("c1\\[\\d+?\\]=\"(\\d+?)\";").matcher(response);
\r
996 while (ma.find()) {
\r
998 String idtmp = ma.group(1);
\r
1000 boolean flag = true;
\r
1001 for (ReserveList rx : getReserves()) {
\r
1002 if (rx.getId().equals(idtmp)) {
\r
1007 if (flag == true) {
\r
1015 /*******************************************************************************
\r
1017 ******************************************************************************/
\r
1019 private final DumpHttp dump = new DumpHttp();
\r
1022 public void wakeup() {
\r
1023 if ( ! getMacAddr().equals("") && ! getBroadcast().equals("")) {
\r
1025 byte[] magic = new byte[102];
\r
1027 for (; i<6; i++) {
\r
1028 magic[i] = (byte) 0xff;
\r
1030 for (int j=0; j<16; j++) {
\r
1031 for (int k=0; k<6; k++) {
\r
1032 short sv = Short.decode("0x"+getMacAddr().substring(k*2,k*2+2));
\r
1033 magic[i++] = (byte)sv;
\r
1039 InetSocketAddress remote = new InetSocketAddress(getBroadcast(), 1234);
\r
1040 DatagramPacket packet = new DatagramPacket(magic, magic.length, remote);
\r
1041 new DatagramSocket().send(packet);
\r
1042 } catch (SocketException e) {
\r
1043 e.printStackTrace();
\r
1044 } catch (IOException e) {
\r
1045 e.printStackTrace();
\r
1049 System.out.println("send magic packet to "+getBroadcast()+","+getMacAddr());
\r
1054 public void shutdown() {
\r
1056 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));
\r
1058 reqGET("http://"+getIPAddr()+":"+getPortNo()+"/remote/remote.htm?key=12", null);
\r
1060 System.out.println("send shutdown request to "+getBroadcast()+","+getMacAddr());
\r
1064 public class MyAuthenticator extends Authenticator {
\r
1065 private String username;
\r
1066 private String password;
\r
1068 public MyAuthenticator(String username, String password) {
\r
1069 this.username = username;
\r
1070 this.password = password;
\r
1072 protected PasswordAuthentication getPasswordAuthentication() {
\r
1073 return new PasswordAuthentication(username, password.toCharArray());
\r
1078 public String[] reqGET(String uri, Hashtable<String, String>property) {
\r
1079 return reqGET(uri, property, "MS932");
\r
1081 public String[] reqGET(String uri, Hashtable<String, String>property, String encoding)
\r
1083 //CookieManager manager = new CookieManager();
\r
1084 //CookieHandler.setDefault(manager);
\r
1086 String header = "";
\r
1087 String response = "";
\r
1088 boolean getSuccess = false;
\r
1090 HttpURLConnection conn = null;
\r
1091 BufferedReader reader = null;
\r
1092 InputStreamReader sr = null;
\r
1095 System.out.println("# GET: "+uri);
\r
1096 dump.request("# GET: "+uri);
\r
1100 URL url = new URL(uri);
\r
1101 conn = (HttpURLConnection)url.openConnection();
\r
1102 conn.setRequestMethod("GET");
\r
1103 conn.setConnectTimeout(5*1000);
\r
1104 conn.setReadTimeout(15*1000);
\r
1105 conn.addRequestProperty("User-Agent", userAgent);
\r
1106 if (property != null) {
\r
1107 for (String key : property.keySet()) {
\r
1108 conn.setRequestProperty(key, property.get(key));
\r
1114 Map<String, List<String>> h = conn.getHeaderFields();
\r
1115 for ( String key : h.keySet() ) {
\r
1117 if (key == null) {
\r
1118 header += h.get(key).get(0)+"\n";
\r
1119 Matcher ma = Pattern.compile(" 200 ").matcher(h.get(key).get(0).toString());
\r
1121 getSuccess = true;
\r
1125 header += key+": "+h.get(key).get(0)+"\n";
\r
1129 System.out.println("# Header");
\r
1130 System.out.println(header);
\r
1131 dump.res_header("# Header\n"+header);
\r
1133 if (getSuccess == false) {
\r
1134 // コネクション切断はfinallyで
\r
1135 return(new String[] {header,null});
\r
1139 sr = new InputStreamReader(conn.getInputStream(),encoding);
\r
1140 reader = new BufferedReader(sr);
\r
1143 StringBuilder sb = new StringBuilder();
\r
1144 while ((s = reader.readLine()) != null) {
\r
1149 response = sb.toString();
\r
1151 // コネクション切断はfinallyで
\r
1154 //System.out.printf("# RESPONSE\n%s\n", response);
\r
1155 System.out.println("# DUMP TO FILE: "+dump.res_body("<!-- # RESPONSE -->\n"+response));
\r
1158 return(new String[] {header,response});
\r
1160 catch (UnsupportedEncodingException e) {
\r
1161 System.err.println("[ERROR] レコーダへのアクセスで問題が発生しました(GET): "+e.toString());
\r
1162 if (getSuccess == true) {
\r
1163 return(new String[] {header,null});
\r
1166 catch (IOException e) {
\r
1167 System.err.println("[ERROR] レコーダへのアクセスで問題が発生しました(GET): "+e.toString());
\r
1168 if (getSuccess == true) {
\r
1169 return(new String[] {header,null});
\r
1173 CommonUtils.closing(reader);
\r
1174 CommonUtils.closing(sr);
\r
1175 CommonUtils.closing(conn);
\r
1178 return(new String[] {null,null});
\r
1182 public String[] reqPOST(String uri, String pstr, Hashtable<String, String>property) {
\r
1183 return reqPOST(uri, pstr, property, "MS932");
\r
1185 public String[] reqPOST(String uri, String pstr, Hashtable<String, String>property, String encoding)
\r
1187 //CookieManager manager = new CookieManager();
\r
1188 //CookieHandler.setDefault(manager);
\r
1190 boolean postSuccess = false;
\r
1191 String header = "";
\r
1192 String response = "";
\r
1194 HttpURLConnection conn = null;
\r
1195 OutputStreamWriter writer = null;
\r
1196 BufferedReader reader = null;
\r
1197 InputStreamReader sr = null;
\r
1200 System.out.println("# POST: "+uri+"?"+pstr);
\r
1201 dump.request("# POST: "+uri+"?"+pstr);
\r
1204 URL url = new URL(uri);
\r
1205 conn = (HttpURLConnection)url.openConnection();
\r
1206 conn.setRequestMethod("POST");
\r
1207 conn.setConnectTimeout(5*1000);
\r
1208 conn.setReadTimeout(15*1000);
\r
1209 conn.setDoOutput(true);
\r
1210 conn.addRequestProperty("User-Agent", userAgent);
\r
1211 if (property != null) {
\r
1212 for (String key : property.keySet()) {
\r
1213 conn.setRequestProperty(key, property.get(key));
\r
1219 writer = new OutputStreamWriter(conn.getOutputStream(),encoding);
\r
1220 writer.write(pstr);
\r
1224 Map<String, List<String>> h = conn.getHeaderFields();
\r
1225 for ( String key : h.keySet() ) {
\r
1227 if (key == null) {
\r
1228 header += h.get(key).get(0)+"\n";
\r
1229 Matcher ma = Pattern.compile(" 200 ").matcher(h.get(key).get(0).toString());
\r
1231 postSuccess = true;
\r
1235 header += key+": "+h.get(key).get(0)+"\n";
\r
1239 System.out.println("# Header");
\r
1240 System.out.println(header);
\r
1241 dump.res_header("# Header\n"+header);
\r
1243 if (postSuccess == false) {
\r
1244 // コネクション切断はfinallyで
\r
1245 return(new String[] {header,null});
\r
1248 sr = new InputStreamReader(conn.getInputStream(),encoding);
\r
1249 reader = new BufferedReader(sr);
\r
1252 StringBuilder sb = new StringBuilder();
\r
1253 while ((s = reader.readLine()) != null) {
\r
1258 response = sb.toString();
\r
1260 // コネクション切断はfinallyで
\r
1263 //System.out.printf("# RESPONSE\n%s\n", response);
\r
1264 System.out.println("# DUMP TO FILE: "+dump.res_body("<!-- # RESPONSE -->\n"+response));
\r
1267 return(new String[] {header,response});
\r
1269 catch (UnsupportedEncodingException e) {
\r
1270 System.err.println("[ERROR] レコーダへのアクセスで問題が発生しました(POST): "+e.toString());
\r
1271 if (postSuccess == true) {
\r
1272 return(new String[] {header,null});
\r
1275 catch (IOException e) {
\r
1276 System.err.println("[ERROR] レコーダへのアクセスで問題が発生しました(POST): "+e.toString());
\r
1277 if (postSuccess == true) {
\r
1278 return(new String[] {header,null});
\r
1282 CommonUtils.closing(writer);
\r
1283 CommonUtils.closing(reader);
\r
1284 CommonUtils.closing(sr);
\r
1285 CommonUtils.closing(conn);
\r
1288 return(new String[] {null,null});
\r
1291 /*******************************************************************************
\r
1292 * ここから下は該当機能が無効なプラグイン用のダミー
\r
1293 ******************************************************************************/
\r
1296 public RecType getType() {
\r
1297 // TODO Auto-generated method stub
\r
1301 public ChannelCode getChCode() {
\r
1302 // TODO Auto-generated method stub
\r
1306 public boolean ChangeChannel(String Channel) {
\r
1307 // TODO Auto-generated method stub
\r
1311 public boolean GetRdSettings(boolean force) {
\r
1312 // TODO Auto-generated method stub
\r
1316 public boolean GetRdReserve(boolean force) {
\r
1317 // TODO Auto-generated method stub
\r
1322 public boolean GetRdReserveDetails() {
\r
1323 // TODO Auto-generated method stub
\r
1327 public boolean GetRdRecorded(boolean force) {
\r
1328 // TODO Auto-generated method stub
\r
1332 public boolean PostRdEntry(ReserveList r) {
\r
1333 // TODO Auto-generated method stub
\r
1337 public boolean UpdateRdEntry(ReserveList o, ReserveList r) {
\r
1338 // TODO Auto-generated method stub
\r
1342 public ReserveList RemoveRdEntry(String delno) {
\r
1343 // TODO Auto-generated method stub
\r
1347 public String getErrmsg() {
\r
1348 // TODO Auto-generated method stub
\r