OSDN Git Service

add dist
authorgn64_jp <gn64_jp@4e526526-5e11-4fc0-8910-f8fd03428081>
Sat, 21 Apr 2012 01:59:40 +0000 (01:59 +0000)
committergn64_jp <gn64_jp@4e526526-5e11-4fc0-8910-f8fd03428081>
Sat, 21 Apr 2012 01:59:40 +0000 (01:59 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/rec10@934 4e526526-5e11-4fc0-8910-f8fd03428081

91 files changed:
dist/trunk/Makefile.base [new file with mode: 0755]
dist/trunk/b25-remote/BCasCard.cpp [new file with mode: 0755]
dist/trunk/b25-remote/BCasCard.h [new file with mode: 0755]
dist/trunk/b25-remote/CasClient.cpp [new file with mode: 0755]
dist/trunk/b25-remote/CasClient.h [new file with mode: 0755]
dist/trunk/b25-remote/CasProxy.cpp [new file with mode: 0755]
dist/trunk/b25-remote/CasProxy.h [new file with mode: 0755]
dist/trunk/b25-remote/CasServer.cpp [new file with mode: 0755]
dist/trunk/b25-remote/CasServer.h [new file with mode: 0755]
dist/trunk/b25-remote/Makefile [new file with mode: 0755]
dist/trunk/b25-remote/Readme.txt [new file with mode: 0755]
dist/trunk/b25-remote/SmartSock.cpp [new file with mode: 0755]
dist/trunk/b25-remote/SmartSock.h [new file with mode: 0755]
dist/trunk/b25-remote/TsUtilClass.cpp [new file with mode: 0755]
dist/trunk/b25-remote/TsUtilClass.h [new file with mode: 0755]
dist/trunk/b25-remote/W2L.h [new file with mode: 0755]
dist/trunk/b25-remote/b25-client.cpp [new file with mode: 0755]
dist/trunk/b25-remote/b25-server.cpp [new file with mode: 0755]
dist/trunk/diff [new file with mode: 0755]
dist/trunk/install.sh [new file with mode: 0755]
dist/trunk/readme.txt [new file with mode: 0755]
dist/trunk/rec10/Makefile.base [new file with mode: 0755]
dist/trunk/rec10/auto_move.py [new file with mode: 0755]
dist/trunk/rec10/auto_process.py [new file with mode: 0755]
dist/trunk/rec10/auto_rec.py [new file with mode: 0755]
dist/trunk/rec10/auto_test.py [new file with mode: 0755]
dist/trunk/rec10/chdata.py [new file with mode: 0755]
dist/trunk/rec10/chdb.py [new file with mode: 0755]
dist/trunk/rec10/checker.py [new file with mode: 0755]
dist/trunk/rec10/classify.py [new file with mode: 0755]
dist/trunk/rec10/configreader.py [new file with mode: 0755]
dist/trunk/rec10/configwriter.py [new file with mode: 0755]
dist/trunk/rec10/dbMySQL.py [new file with mode: 0755]
dist/trunk/rec10/epgdb.py [new file with mode: 0755]
dist/trunk/rec10/epgrefresh.py [new file with mode: 0755]
dist/trunk/rec10/guess.py [new file with mode: 0755]
dist/trunk/rec10/install.py [new file with mode: 0755]
dist/trunk/rec10/install.sh [new file with mode: 0755]
dist/trunk/rec10/license-ja.txt [new file with mode: 0755]
dist/trunk/rec10/license.txt [new file with mode: 0755]
dist/trunk/rec10/n_gram.py [new file with mode: 0755]
dist/trunk/rec10/readme.txt [new file with mode: 0755]
dist/trunk/rec10/rec10.conf [new file with mode: 0755]
dist/trunk/rec10/rec10d.py [new file with mode: 0755]
dist/trunk/rec10/recdb.py [new file with mode: 0755]
dist/trunk/rec10/recdblist.py [new file with mode: 0755]
dist/trunk/rec10/recque.py [new file with mode: 0755]
dist/trunk/rec10/scan_ch.py [new file with mode: 0755]
dist/trunk/rec10/status.py [new file with mode: 0755]
dist/trunk/rec10/tester.py [new file with mode: 0755]
dist/trunk/rec10/timerec.py [new file with mode: 0755]
dist/trunk/rec10/ts2epg.py [new file with mode: 0755]
dist/trunk/rec10/ts2x264.py [new file with mode: 0755]
dist/trunk/rec10/tv2audio.py [new file with mode: 0755]
dist/trunk/rec10/tv2avi.py [new file with mode: 0755]
dist/trunk/rec10/tv2mkv.py [new file with mode: 0755]
dist/trunk/rec10/tv2mp4.py [new file with mode: 0755]
dist/trunk/rec10/tv2ts.py [new file with mode: 0755]
dist/trunk/rec10/xml2db_dom.py [new file with mode: 0755]
dist/trunk/rec10/zenhan.py [new file with mode: 0755]
dist/trunk/rec10/zip.py [new file with mode: 0755]
dist/trunk/rec10Manual0.9.9.pdf [new file with mode: 0755]
dist/trunk/tstools/BonTsDemux/BonTsDemux.exe [new file with mode: 0755]
dist/trunk/tstools/BonTsDemux/BonTsDemux.txt [new file with mode: 0755]
dist/trunk/tstools/BonTsDemux/BonTsDemuxLib.dll [new file with mode: 0755]
dist/trunk/tstools/BonTsDemux/src.zip [new file with mode: 0755]
dist/trunk/tstools/Makefile [new file with mode: 0755]
dist/trunk/tstools/epgdump/Makefile [new file with mode: 0755]
dist/trunk/tstools/epgdump/aribstr.c [new file with mode: 0755]
dist/trunk/tstools/epgdump/aribstr.h [new file with mode: 0755]
dist/trunk/tstools/epgdump/eit.c [new file with mode: 0755]
dist/trunk/tstools/epgdump/eit.h [new file with mode: 0755]
dist/trunk/tstools/epgdump/epgdump.c [new file with mode: 0755]
dist/trunk/tstools/epgdump/epgdump_segfault_fix_patch(last).txt [new file with mode: 0755]
dist/trunk/tstools/epgdump/patch2ch [new file with mode: 0755]
dist/trunk/tstools/epgdump/patch_r2 [new file with mode: 0755]
dist/trunk/tstools/epgdump/readme.txt [new file with mode: 0755]
dist/trunk/tstools/epgdump/sdt.c [new file with mode: 0755]
dist/trunk/tstools/epgdump/sdt.h [new file with mode: 0755]
dist/trunk/tstools/epgdump/ts.c [new file with mode: 0755]
dist/trunk/tstools/epgdump/ts.h [new file with mode: 0755]
dist/trunk/tstools/epgdump/ts_ctl.h [new file with mode: 0755]
dist/trunk/tstools/epgdump/util.c [new file with mode: 0755]
dist/trunk/tstools/epgdump/util.h [new file with mode: 0755]
dist/trunk/tstools/epgdump/xmldata.c [new file with mode: 0755]
dist/trunk/tstools/jTsSplitter/jTsSplitter.jar [new file with mode: 0755]
dist/trunk/tstools/tunerec/Makefile [new file with mode: 0755]
dist/trunk/tstools/tunerec/README.ja [new file with mode: 0755]
dist/trunk/tstools/tunerec/tunerec.c [new file with mode: 0755]
dist/trunk/www/Makefile.PL [new file with mode: 0755]
dist/trunk/www/rectool.pl [new file with mode: 0755]

diff --git a/dist/trunk/Makefile.base b/dist/trunk/Makefile.base
new file mode 100755 (executable)
index 0000000..de63667
--- /dev/null
@@ -0,0 +1,17 @@
+MAJOR = 0
+MINOR = 9
+REVISION = 10
+VER = $(MAJOR).$(MINOR).$(REVISION)
+
+
+all: 
+       cd tstools;make all
+clean:
+       cd tstools;make clean
+install: 
+       cd rec10;make install
+       cd tstools;make install
+uninstall:
+       cd tstools;make uninstall
+       cd rec10;make uninstall
+       
diff --git a/dist/trunk/b25-remote/BCasCard.cpp b/dist/trunk/b25-remote/BCasCard.cpp
new file mode 100755 (executable)
index 0000000..7d8387f
--- /dev/null
@@ -0,0 +1,361 @@
+// BcasCard.cpp: CBcasCard \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include "W2L.h"\r
+#include "BCasCard.h"\r
+\r
+#ifdef _DEBUG\r
+#undef THIS_FILE\r
+static char THIS_FILE[]=__FILE__;\r
+#define new DEBUG_NEW\r
+#endif\r
+\r
+\r
+//#pragma comment(lib, "WinScard.lib")\r
+\r
+\r
+using std::auto_ptr;\r
+\r
+\r
+CBcasCard::CBcasCard()\r
+       : m_hBcasCard(NULL)\r
+       , m_bIsEstablish(false)\r
+       , m_dwLastError(BCEC_NOERROR)\r
+{\r
+       // \93à\95\94\8fó\91Ô\8f\89\8aú\89»\r
+       memset(&m_BcasCardInfo, 0, sizeof(m_BcasCardInfo));\r
+       memset(&m_EcmStatus,    0, sizeof(m_EcmStatus));\r
+\r
+       // \83\8a\83\\81[\83X\83}\83l\81[\83W\83\83\83R\83\93\83e\83L\83X\83g\8am\97§\r
+       if(::SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &m_ScardContext) != SCARD_S_SUCCESS){\r
+               m_dwLastError = BCEC_NOTESTABLISHED;\r
+               }\r
+       else{\r
+               m_bIsEstablish = true;\r
+               \r
+               // \83J\81[\83h\83\8a\81[\83_\97ñ\8b\93\r
+               EnumCardReader();\r
+               }\r
+}\r
+\r
+CBcasCard::~CBcasCard()\r
+{\r
+       CloseCard();\r
+\r
+       // \83\8a\83\\81[\83X\83}\83l\81[\83W\83\83\83R\83\93\83e\83L\83X\83g\82Ì\8aJ\95ú\r
+       if(m_bIsEstablish)::SCardReleaseContext(m_ScardContext);\r
+}\r
+\r
+const DWORD CBcasCard::GetCardReaderNum(void) const\r
+{\r
+       // \83J\81[\83h\83\8a\81[\83_\81[\90\94\82ð\95Ô\82·\r
+       return m_CardReaderArray.size();\r
+}\r
+\r
+LPCTSTR CBcasCard::GetCardReaderName(const DWORD dwIndex) const\r
+{\r
+       // \83J\81[\83h\83\8a\81[\83_\81[\96¼\82ð\95Ô\82·\r
+       return (dwIndex < GetCardReaderNum())? m_CardReaderArray[dwIndex].c_str() : NULL;\r
+}\r
+\r
+const bool CBcasCard::OpenCard(LPCTSTR lpszReader)\r
+{\r
+       // \83\8a\83\\81[\83X\83}\83l\81[\83W\83\83\83R\83\93\83e\83L\83X\83g\82Ì\8am\97§\r
+       if(!m_bIsEstablish){\r
+               m_dwLastError = BCEC_NOTESTABLISHED;\r
+               return false;\r
+               }\r
+       \r
+       // \88ê\92U\83N\83\8d\81[\83Y\82·\82é\r
+       CloseCard();\r
+\r
+\r
+       if(lpszReader){\r
+               // \8ew\92è\82³\82ê\82½\83J\81[\83h\83\8a\81[\83_\82É\91Î\82µ\82Ä\83I\81[\83v\83\93\82ð\8e\8e\82Ý\82é\r
+               DWORD dwActiveProtocol = SCARD_PROTOCOL_UNDEFINED;\r
+               \r
+               if(::SCardConnect(m_ScardContext, lpszReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &m_hBcasCard, &dwActiveProtocol) != SCARD_S_SUCCESS){\r
+                       m_dwLastError = BCEC_CARDOPENERROR;\r
+                       return false;\r
+                       }\r
+\r
+               if(dwActiveProtocol != SCARD_PROTOCOL_T1){\r
+                       CloseCard();\r
+                       m_dwLastError = BCEC_CARDOPENERROR;\r
+                       return false;\r
+                       }\r
+               }\r
+       else{\r
+               // \91S\82Ä\82Ì\83J\81[\83h\83\8a\81[\83_\82É\91Î\82µ\82Ä\83I\81[\83v\83\93\82ð\8e\8e\82Ý\82é\r
+               DWORD dwIndex = 0UL;\r
+       \r
+               while(GetCardReaderName(dwIndex)){\r
+                       if(OpenCard(GetCardReaderName(dwIndex++)))return true;                  \r
+                       }\r
+               \r
+               return false;\r
+               }\r
+\r
+       // \83J\81[\83h\8f\89\8aú\89»\r
+       if(!InitialSetting())return false;\r
+\r
+       m_dwLastError = BCEC_NOERROR;\r
+\r
+       return true;\r
+}\r
+\r
+void CBcasCard::CloseCard(void)\r
+{\r
+       // \83J\81[\83h\82ð\83N\83\8d\81[\83Y\82·\82é\r
+       if(m_hBcasCard){\r
+               ::SCardDisconnect(m_hBcasCard, SCARD_LEAVE_CARD);\r
+               m_hBcasCard = NULL;\r
+               }\r
+}\r
+\r
+const DWORD CBcasCard::GetLastError(void) const\r
+{\r
+       // \8dÅ\8cã\82É\94­\90\82µ\82½\83G\83\89\81[\82ð\95Ô\82·\r
+       return m_dwLastError;\r
+}\r
+\r
+const bool CBcasCard::EnumCardReader(void)\r
+{\r
+       // \83J\81[\83h\83\8a\81[\83_\82ð\97ñ\8b\93\82·\82é\r
+       DWORD dwBuffSize = 0UL;\r
+       \r
+       switch(::SCardListReaders(m_ScardContext, NULL, NULL, &dwBuffSize)){\r
+               case SCARD_E_NO_READERS_AVAILABLE :\r
+                       // \83J\81[\83h\83\8a\81[\83_\82ª\8c©\82Â\82©\82ç\82È\82¢\r
+                       m_dwLastError = BCEC_NOCARDREADERS;\r
+                       return false;\r
+\r
+               case SCARD_S_SUCCESS :\r
+                       // \83o\83b\83t\83@\83T\83C\83Y\8eæ\93¾\90¬\8c÷\r
+                       break;\r
+               \r
+               default:\r
+                       // \83G\83\89\81[\r
+                       m_dwLastError = BCEC_INTERNALERROR;             \r
+                       return false;\r
+               }\r
+\r
+       // \83o\83b\83t\83@\8am\95Û\r
+       auto_ptr<TCHAR> szReaders(new TCHAR[dwBuffSize]);\r
+\r
+       switch(::SCardListReaders(m_ScardContext, NULL, szReaders.get(), &dwBuffSize)){\r
+               case SCARD_E_NO_READERS_AVAILABLE :\r
+                       // \83J\81[\83h\83\8a\81[\83_\82ª\8c©\82Â\82©\82ç\82È\82¢\r
+                       m_dwLastError = BCEC_NOCARDREADERS;\r
+                       return false;\r
+\r
+               case SCARD_S_SUCCESS : {\r
+                       // \83J\81[\83h\83\8a\81[\83_\96¼\95Û\91\r
+                       LPTSTR lpszCurReader = szReaders.get();\r
+                       m_CardReaderArray.clear();\r
+                       \r
+                       while(*lpszCurReader){\r
+                               m_CardReaderArray.push_back(lpszCurReader);\r
+                               lpszCurReader += m_CardReaderArray.back().length() + 1UL;\r
+                               }\r
+                       \r
+                       break;\r
+                       }\r
+               \r
+               default:\r
+                       // \83G\83\89\81[\r
+                       m_dwLastError = BCEC_INTERNALERROR;             \r
+                       return false;\r
+               }\r
+\r
+       m_dwLastError = BCEC_NOERROR;\r
+\r
+       return true;\r
+}\r
+\r
+const bool CBcasCard::TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData, const DWORD dwMaxRecv, DWORD *pdwRecvSize)\r
+{\r
+       DWORD dwRecvSize = dwMaxRecv;\r
+\r
+       // \83f\81[\83^\91\97\8eó\90M\r
+       DWORD dwReturn = ::SCardTransmit(m_hBcasCard, SCARD_PCI_T1, pSendData, dwSendSize, NULL, pRecvData, &dwRecvSize);\r
+       \r
+       // \8eó\90M\83T\83C\83Y\8ai\94[\r
+       if(pdwRecvSize)*pdwRecvSize = dwRecvSize;\r
+\r
+       return (dwReturn == SCARD_S_SUCCESS)? true : false;\r
+}\r
+\r
+const bool CBcasCard::InitialSetting(void)\r
+{\r
+       static const BYTE InitSettingCmd[] = {0x90U, 0x30U, 0x00U, 0x00U, 0x00U};\r
+\r
+       // \81uInitial Setting Conditions Command\81v\82ð\8f\88\97\9d\82·\82é\r
+       if(!m_hBcasCard){\r
+               m_dwLastError = BCEC_CARDNOTOPEN;\r
+               return false;\r
+               }\r
+\r
+       // \83o\83b\83t\83@\8f\80\94õ\r
+       DWORD dwRecvSize = 0UL;\r
+       BYTE RecvData[1024];\r
+       memset(RecvData, 0, sizeof(RecvData));\r
+       \r
+       // \83R\83}\83\93\83h\91\97\90M\r
+       if(!TransmitCommand(InitSettingCmd, sizeof(InitSettingCmd), RecvData, sizeof(RecvData), &dwRecvSize)){\r
+               m_dwLastError = BCEC_TRANSMITERROR;\r
+               return false;\r
+               }\r
+\r
+       if(dwRecvSize < 57UL){\r
+               m_dwLastError = BCEC_TRANSMITERROR;\r
+               return false;           \r
+               }\r
+\r
+       // \83\8c\83X\83|\83\93\83X\89ð\90Í\r
+       memcpy(m_BcasCardInfo.BcasCardID, &RecvData[8], 6UL);           // +8   Card ID\r
+       memcpy(m_BcasCardInfo.SystemKey, &RecvData[16], 32UL);  // +16  Descrambling system key\r
+       memcpy(m_BcasCardInfo.InitialCbc, &RecvData[48], 8UL);  // +48  Descrambler CBC initial value\r
+\r
+       // ECM\83X\83e\81[\83^\83X\8f\89\8aú\89»\r
+       memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
+\r
+       return true;\r
+}\r
+\r
+const BYTE * CBcasCard::GetBcasCardID(void)\r
+{\r
+       // Card ID \82ð\95Ô\82·\r
+       if(!m_hBcasCard){\r
+               m_dwLastError = BCEC_CARDNOTOPEN;\r
+               return NULL;\r
+               }\r
+       \r
+       m_dwLastError = BCEC_NOERROR;\r
+       \r
+       return m_BcasCardInfo.BcasCardID;\r
+}\r
+\r
+const BYTE * CBcasCard::GetInitialCbc(void)\r
+{\r
+       // Descrambler CBC Initial Value \82ð\95Ô\82·\r
+       if(!m_hBcasCard){\r
+               m_dwLastError = BCEC_CARDNOTOPEN;\r
+               return NULL;\r
+               }\r
+       \r
+       m_dwLastError = BCEC_NOERROR;\r
+       \r
+       return m_BcasCardInfo.InitialCbc;\r
+}\r
+\r
+const BYTE * CBcasCard::GetSystemKey(void)\r
+{\r
+       // Descrambling System Key \82ð\95Ô\82·\r
+       if(!m_hBcasCard){\r
+               m_dwLastError = BCEC_CARDNOTOPEN;\r
+               return NULL;\r
+               }\r
+       \r
+       m_dwLastError = BCEC_NOERROR;\r
+       \r
+       return m_BcasCardInfo.SystemKey;\r
+}\r
+\r
+const BYTE * CBcasCard::GetKsFromEcm(const BYTE *pEcmData, const DWORD dwEcmSize)\r
+{\r
+       static const BYTE EcmReceiveCmd[] = {0x90U, 0x34U, 0x00U, 0x00U};\r
+\r
+       // \81uECM Receive Command\81v\82ð\8f\88\97\9d\82·\82é\r
+       if(!m_hBcasCard){\r
+               m_dwLastError = BCEC_CARDNOTOPEN;\r
+               return NULL;\r
+               }\r
+\r
+       // ECM\83T\83C\83Y\82ð\83`\83F\83b\83N\r
+       if(!pEcmData || (dwEcmSize < 30UL) || (dwEcmSize > 256UL)){\r
+               m_dwLastError = BCEC_BADARGUMENT;\r
+               return NULL;\r
+               }\r
+\r
+       // \83L\83\83\83b\83V\83\85\82ð\83`\83F\83b\83N\82·\82é\r
+       if(!StoreEcmData(pEcmData, dwEcmSize)){\r
+               // ECM\82ª\93¯\88ê\82Ì\8fê\8d\87\82Í\83L\83\83\83b\83V\83\85\8dÏ\82ÝKs\82ð\95Ô\82·\r
+               m_dwLastError = BCEC_NOERROR;\r
+               return m_EcmStatus.KsData;\r
+               }\r
+\r
+       // \83o\83b\83t\83@\8f\80\94õ\r
+       DWORD dwRecvSize = 0UL;\r
+       BYTE SendData[1024];\r
+       BYTE RecvData[1024];\r
+       memset(RecvData, 0, sizeof(RecvData));\r
+\r
+       // \83R\83}\83\93\83h\8d\\92z\r
+       memcpy(SendData, EcmReceiveCmd, sizeof(EcmReceiveCmd));                         // CLA, INS, P1, P2\r
+       SendData[sizeof(EcmReceiveCmd)] = (BYTE)dwEcmSize;                                                      // COMMAND DATA LENGTH\r
+       memcpy(&SendData[sizeof(EcmReceiveCmd) + 1], pEcmData, dwEcmSize);      // ECM\r
+       SendData[sizeof(EcmReceiveCmd) + dwEcmSize + 1] = 0x00U;                                        // RESPONSE DATA LENGTH\r
+\r
+       // \83R\83}\83\93\83h\91\97\90M\r
+       if(!TransmitCommand(SendData, sizeof(EcmReceiveCmd) + dwEcmSize + 2UL, RecvData, sizeof(RecvData), &dwRecvSize)){\r
+               memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
+               m_dwLastError = BCEC_TRANSMITERROR;\r
+               return NULL;\r
+               }\r
+\r
+       // \83T\83C\83Y\83`\83F\83b\83N\r
+       if(dwRecvSize != 25UL){\r
+               memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
+               m_dwLastError = BCEC_TRANSMITERROR;\r
+               return NULL;\r
+               }       \r
+       \r
+       // \83\8c\83X\83|\83\93\83X\89ð\90Í\r
+       memcpy(m_EcmStatus.KsData, &RecvData[6], sizeof(m_EcmStatus.KsData));\r
+\r
+       // \83\8a\83^\81[\83\93\83R\81[\83h\89ð\90Í\r
+       switch(((WORD)RecvData[4] << 8) | (WORD)RecvData[5]){\r
+               // Purchased: Viewing\r
+               case 0x0200U :  // Payment-deferred PPV\r
+               case 0x0400U :  // Prepaid PPV\r
+               case 0x0800U :  // Tier\r
+                       m_dwLastError = BCEC_NOERROR;\r
+                       return m_EcmStatus.KsData;\r
+               \r
+               // \8fã\8bL\88È\8aO(\8e\8b\92®\95s\89Â)\r
+               default :\r
+                       m_dwLastError = BCEC_ECMREFUSED;\r
+                       return NULL;\r
+               }\r
+}\r
+\r
+const bool CBcasCard::StoreEcmData(const BYTE *pEcmData, const DWORD dwEcmSize)\r
+{\r
+       bool bUpdate = false;\r
+       \r
+       // ECM\83f\81[\83^\94ä\8ar\r
+       if(m_EcmStatus.dwLastEcmSize != dwEcmSize){\r
+               // \83T\83C\83Y\82ª\95Ï\89»\82µ\82½\r
+               bUpdate = true;\r
+               }\r
+       else{\r
+               // \83T\83C\83Y\82ª\93¯\82\8fê\8d\87\82Í\83f\81[\83^\82ð\83`\83F\83b\83N\82·\82é\r
+               for(DWORD dwPos = 0UL ; dwPos < dwEcmSize ; dwPos++){\r
+                       if(pEcmData[dwPos] != m_EcmStatus.LastEcmData[dwPos]){\r
+                               // \83f\81[\83^\82ª\95s\88ê\92v\r
+                               bUpdate = true;\r
+                               break;\r
+                               }                       \r
+                       }\r
+               }\r
+\r
+       // ECM\83f\81[\83^\82ð\95Û\91\82·\82é\r
+       if(bUpdate){\r
+               m_EcmStatus.dwLastEcmSize = dwEcmSize;\r
+               memcpy(m_EcmStatus.LastEcmData, pEcmData, dwEcmSize);\r
+               }\r
+\r
+       return bUpdate;\r
+}\r
diff --git a/dist/trunk/b25-remote/BCasCard.h b/dist/trunk/b25-remote/BCasCard.h
new file mode 100755 (executable)
index 0000000..e793203
--- /dev/null
@@ -0,0 +1,85 @@
+// BcasCard.h: CBcasCard \83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+
+#include <memory>\r
+#include <vector>\r
+#include <string>\r
+#include <winscard.h>\r
+\r
+\r
+using std::vector;\r
+using std::wstring;\r
+using std::string;\r
+\r
+\r
+// \83G\83\89\81[\83R\81[\83h\r
+#define BCEC_NOERROR                   0x00000000UL    // \83G\83\89\81[\82È\82µ\r
+#define BCEC_INTERNALERROR             0x00000001UL    // \93à\95\94\83G\83\89\81[\r
+#define BCEC_NOTESTABLISHED            0x00000002UL    // \83R\83\93\83e\83L\83X\83g\8am\97§\8e¸\94s\r
+#define BCEC_NOCARDREADERS             0x00000003UL    // \83J\81[\83h\83\8a\81[\83_\82ª\82È\82¢\r
+#define BCEC_ALREADYOPEN               0x00000004UL    // \8aù\82É\83I\81[\83v\83\93\8dÏ\82Ý\r
+#define BCEC_CARDOPENERROR             0x00000005UL    // \83J\81[\83h\83I\81[\83v\83\93\8e¸\94s\r
+#define BCEC_CARDNOTOPEN               0x00000006UL    // \83J\81[\83h\96¢\83I\81[\83v\83\93\r
+#define BCEC_TRANSMITERROR             0x00000007UL    // \92Ê\90M\83G\83\89\81[\r
+#define BCEC_BADARGUMENT               0x00000008UL    // \88ø\90\94\82ª\95s\90³\r
+#define BCEC_ECMREFUSED                        0x00000009UL    // ECM\8eó\95t\8b\91\94Û\r
+\r
+\r
+class CBcasCard\r
+{\r
+public:\r
+       CBcasCard();\r
+       ~CBcasCard();\r
+\r
+       const DWORD GetCardReaderNum(void) const;\r
+       LPCTSTR GetCardReaderName(const DWORD dwIndex = 0UL) const;\r
+\r
+       const bool OpenCard(LPCTSTR lpszReader = NULL);\r
+       void CloseCard(void);\r
+\r
+       const BYTE * GetBcasCardID(void);\r
+       const BYTE * GetInitialCbc(void);\r
+       const BYTE * GetSystemKey(void);\r
+       const BYTE * GetKsFromEcm(const BYTE *pEcmData, const DWORD dwEcmSize);\r
+\r
+       const DWORD GetLastError(void) const;\r
+\r
+protected:\r
+       const bool EnumCardReader(void);\r
+       const bool TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData, const DWORD dwMaxRecv, DWORD *pdwRecvSize = NULL);\r
+       const bool InitialSetting(void);\r
+\r
+       SCARDCONTEXT m_ScardContext;\r
+       SCARDHANDLE m_hBcasCard;\r
+\r
+       bool m_bIsEstablish;\r
+\r
+#ifdef _UNICODE        \r
+       vector<wstring> m_CardReaderArray;\r
+#else\r
+       vector<string> m_CardReaderArray;\r
+#endif\r
+\r
+       struct TAG_BCASCARDINFO\r
+       {\r
+               BYTE BcasCardID[6];             // Card ID\r
+               BYTE SystemKey[32];             // Descrambling system key\r
+               BYTE InitialCbc[8];             // Descrambler CBC initial value\r
+       } m_BcasCardInfo;\r
+       \r
+       struct TAG_ECMSTATUS\r
+       {\r
+               DWORD dwLastEcmSize;    // \8dÅ\8cã\82É\96â\82¢\8d\87\82í\82¹\82Ì\82 \82Á\82½ECM\83T\83C\83Y\r
+               BYTE LastEcmData[256];  // \8dÅ\8cã\82É\96â\82¢\8d\87\82í\82¹\82Ì\82 \82Á\82½ECM\83f\81[\83^\r
+               BYTE KsData[16];                // Ks Odd + Even        \r
+       } m_EcmStatus;\r
+       \r
+       DWORD m_dwLastError;\r
+\r
+private:\r
+       const bool StoreEcmData(const BYTE *pEcmData, const DWORD dwEcmSize);\r
+};\r
diff --git a/dist/trunk/b25-remote/CasClient.cpp b/dist/trunk/b25-remote/CasClient.cpp
new file mode 100755 (executable)
index 0000000..4b6c6fb
--- /dev/null
@@ -0,0 +1,97 @@
+// CasClient.cpp: CCasClient \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include <stdio.h>\r
+#include "W2L.h"\r
+#include "CasClient.h"
+\r
+\r
+#define TCP_TIMEOUT            1000UL          // 1\95b\r
+\r
+\r
+CCasClient::CCasClient(ICasClientHandler *pEventHandler, CSmartSock *pSocket)\r
+       : CBcasCard()\r
+       , m_pSocket(pSocket)\r
+       , m_pEventHandler(pEventHandler)\r
+       , m_hClientThread(NULL)\r
+{\r
+       // \83N\83\89\83C\83A\83\93\83g\83X\83\8c\83b\83h\8bN\93®\r
+       pthread_create(&m_hClientThread, NULL, CCasClient::ClientThreadRaw, (LPVOID)this);\r
+       if(!m_hClientThread){\r
+               printf("ClientThread failed\n");
+               delete this;\r
+       }\r
+       printf("ClientThread started\n");
+}\r
+\r
+CCasClient::~CCasClient(void)\r
+{\r
+       delete m_pSocket;\r
+       if (m_hClientThread) pthread_join(m_hClientThread, NULL);\r
+}\r
+\r
+void CCasClient::CloseClient(void)\r
+{\r
+       // \83N\83\89\83C\83A\83\93\83g\82ð\90Ø\92f\82·\82é\r
+       m_pSocket->Close();\r
+}\r
+\r
+void CCasClient::ClientThread(void)\r
+{\r
+       // \83J\81[\83h\83\8a\81[\83_\82ð\8aJ\82­\r
+       if(!OpenCard())return;\r
+       \r
+       // \8eó\90M\83o\83b\83t\83@\r
+       BYTE byDataLen;\r
+       BYTE RecvBuf[256];\r
+       DWORD dwRecvSize;\r
+       \r
+       // \83\81\83b\83Z\81[\83W\8eó\90M\83\8b\81[\83v\r
+       while(1){\r
+               // \83w\83b\83_\82ð\8eó\90M\r
+               if(!m_pSocket->Recv(&byDataLen, 1UL, TCP_TIMEOUT)){\r
+                       if(m_pSocket->GetLastError() == CSmartSock::EC_TIMEOUT)continue;\r
+                       else break;\r
+               }
+\r
+               // \83f\81[\83^\82ð\8eó\90M\r
+               if(!m_pSocket->Recv(RecvBuf, byDataLen, TCP_TIMEOUT))break;
+       \r
+               // \83J\81[\83h\91\97\8eó\90M\r
+               if(!TransmitCommand(RecvBuf, byDataLen, &RecvBuf[1], sizeof(RecvBuf) - 1UL, &dwRecvSize))dwRecvSize = 0UL;
+\r
+               // \83f\81[\83^\82ð\91\97\90M\r
+               RecvBuf[0] = (BYTE)dwRecvSize;\r
+               if(!m_pSocket->Send(RecvBuf, dwRecvSize + 1UL, TCP_TIMEOUT))break;
+       }\r
+\r
+       printf("ClientThread exited\n");
+       // \83J\81[\83h\83\8a\81[\83_\82ð\95Â\82\82é\r
+       CloseCard();\r
+}\r
+\r
+void* CCasClient::ClientThreadRaw(LPVOID pParam)\r
+{\r
+       // \83N\83\89\83C\83A\83\93\83g\83X\83\8c\83b\83h\r
+       CCasClient *pThis = static_cast<CCasClient *>(pParam);\r
+\r
+       // \90Ú\91±\83C\83x\83\93\83g\92Ê\92m\r
+       pThis->SendEvent(EID_CONNECTED);
+\r
+       // \83\81\83\93\83o\8aÖ\90\94\82É\83\8a\83_\83C\83\8c\83N\83g\82·\82é\r
+       pThis->ClientThread();
+\r
+       // \90Ø\92f\83C\83x\83\93\83g\92Ê\92m\r
+       pThis->SendEvent(EID_DISCONNECTED);
+\r
+       delete pThis;
+\r
+       return 0UL;\r
+}\r
+\r
+void CCasClient::SendEvent(const DWORD dwEventID, PVOID pParam)\r
+{\r
+       // \83n\83\93\83h\83\89\82É\83C\83x\83\93\83g\82ð\92Ê\92m\82·\82é\r
+       if(m_pEventHandler)m_pEventHandler->OnCasClientEvent(this, dwEventID, pParam);\r
+}\r
diff --git a/dist/trunk/b25-remote/CasClient.h b/dist/trunk/b25-remote/CasClient.h
new file mode 100755 (executable)
index 0000000..ecd1c56
--- /dev/null
@@ -0,0 +1,41 @@
+// CasClient.h: CCasClient \83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+#include "W2L.h"\r
+#include "BCasCard.h"\r
+#include "SmartSock.h"\r
+\r
+\r
+class CCasClient : private CBcasCard\r
+{\r
+public:\r
+       class ICasClientHandler\r
+       {\r
+       public:\r
+               virtual void OnCasClientEvent(CCasClient *pClient, const DWORD dwEventID, PVOID pParam) = 0;\r
+       };\r
+\r
+       enum\r
+       {\r
+               EID_CONNECTED,          // \83N\83\89\83C\83A\83\93\83g\90Ú\91±\r
+               EID_DISCONNECTED        // \83N\83\89\83C\83A\83\93\83g\90Ø\92f\r
+       };\r
+\r
+       CCasClient(ICasClientHandler *pEventHandler, CSmartSock *pSocket);\r
+       ~CCasClient(void);\r
+\r
+       void CloseClient(void);\r
+\r
+protected:\r
+       void ClientThread(void);\r
+       static void* ClientThreadRaw(LPVOID pParam);\r
+\r
+       void SendEvent(const DWORD dwEventID, PVOID pParam = NULL);\r
+\r
+       CSmartSock *m_pSocket;\r
+       ICasClientHandler *m_pEventHandler;\r
+       pthread_t m_hClientThread;\r
+};\r
diff --git a/dist/trunk/b25-remote/CasProxy.cpp b/dist/trunk/b25-remote/CasProxy.cpp
new file mode 100755 (executable)
index 0000000..dbf0330
--- /dev/null
@@ -0,0 +1,87 @@
+// CasProxy.cpp: CCasProxy \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+\r
+#include "CasProxy.h"\r
+#include <stdio.h>\r
+\r
+#define TCP_TIMEOUT    1000UL  // 1\95b\r
+\r
+\r
+DWORD CCasProxy::dwErrorDelayTime = 0UL;\r
+\r
+\r
+CCasProxy::CCasProxy(void)\r
+{\r
+\r
+}\r
+\r
+CCasProxy::~CCasProxy(void)\r
+{\r
+       // \83T\81[\83o\82©\82ç\90Ø\92f\r
+       m_Socket.Close();\r
+}\r
+\r
+const BOOL CCasProxy::Connect(void)\r
+{\r
+/*
+       // \83G\83\89\81[\94­\90\8e\9e\82Ì\83K\81[\83h\83C\83\93\83^\81[\83o\83\8b\r
+       if(dwErrorDelayTime){\r
+               if((::GetTickCount() - dwErrorDelayTime) < TCP_TIMEOUT)return FALSE;\r
+               else dwErrorDelayTime = 0UL;\r
+               }\r
+*/\r
+       // \83T\81[\83o\82É\90Ú\91±
+       char* env = getenv("B25_SERVER_IP");
+       LPCTSTR lpszHost;
+       WORD wPort;
+       if (env) {
+               lpszHost = env;
+       }
+       else {
+               lpszHost = "127.0.0.1";
+       }
+       env = getenv("B25_SERVER_PORT");
+       if (env) {
+               wPort = atoi(env);
+       }
+       else {
+               wPort = 6900;
+       }
+
+       if(m_Socket.Connect(lpszHost, wPort, TCP_TIMEOUT)){\r
+               return TRUE;\r
+       }\r
+       else{
+               //dwErrorDelayTime = ::GetTickCount();\r
+               return FALSE;\r
+       }\r
+}\r
+\r
+const DWORD CCasProxy::TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData)\r
+{\r
+       // \91\97\90M\83f\81[\83^\8f\80\94õ\r
+       BYTE SendBuf[256];\r
+       SendBuf[0] = (BYTE)dwSendSize;\r
+       memcpy(&SendBuf[1], pSendData, dwSendSize);\r
+\r
+       try{\r
+               // \83\8a\83N\83G\83X\83g\91\97\90M\r
+               if(!m_Socket.Send(SendBuf, dwSendSize + 1UL, TCP_TIMEOUT))throw (const DWORD)__LINE__;\r
+       \r
+               // \83\8c\83X\83|\83\93\83X\83w\83b\83_\8eó\90M\r
+               if(!m_Socket.Recv(SendBuf, 1UL, TCP_TIMEOUT))throw (const DWORD)__LINE__;\r
+\r
+               // \83\8c\83X\83|\83\93\83X\83f\81[\83^\8eó\90M\r
+               if(!m_Socket.Recv(pRecvData, SendBuf[0], TCP_TIMEOUT))throw (const DWORD)__LINE__;\r
+               }\r
+       catch(const DWORD dwLine){\r
+               // \92Ê\90M\83G\83\89\81[\94­\90\r
+               m_Socket.Close();\r
+               return 0UL;\r
+               }\r
+               \r
+       return SendBuf[0];\r
+}
+
diff --git a/dist/trunk/b25-remote/CasProxy.h b/dist/trunk/b25-remote/CasProxy.h
new file mode 100755 (executable)
index 0000000..2b0d6e4
--- /dev/null
@@ -0,0 +1,36 @@
+// CasProxy.h: CCasProxy \83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+\r
+#pragma once\r
+\r
+\r
+#include "SmartSock.h"\r
+#include <stdlib.h>\r
+\r
+class CCasProxy\r
+{\r
+public:\r
+       enum\r
+       {\r
+               CPEI_ENTERPROCESS,              // \83v\83\8d\83Z\83X\8aJ\8en\92Ê\92m\r
+               CPEI_EXITPROCESS,               // \83v\83\8d\83Z\83X\8fI\97¹\92Ê\92m\r
+               CPEI_GETSERVERIP,               // \83T\81[\83oIP\8eæ\93¾\r
+               CPEI_GETSERVERPORT,             // \83T\81[\83o\83|\81[\83g\8eæ\93¾\r
+               CPEI_CONNECTSUCCESS,    // \90Ú\91±\8a®\97¹\r
+               CPEI_CONNECTFAILED,             // \90Ú\91±\8e¸\94s\r
+               CPEI_DISCONNECTED               // \90Ú\91±\90Ø\92f\r
+       };\r
+       \r
+       CCasProxy(void);\r
+       ~CCasProxy(void);\r
+\r
+       const BOOL Connect(void);\r
+       const DWORD TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData);\r
+\r
+protected:\r
+       CSmartSock m_Socket;\r
+       \r
+       static DWORD dwErrorDelayTime;\r
+};\r
diff --git a/dist/trunk/b25-remote/CasServer.cpp b/dist/trunk/b25-remote/CasServer.cpp
new file mode 100755 (executable)
index 0000000..4c733b8
--- /dev/null
@@ -0,0 +1,110 @@
+// CasServer.cpp: CCasServer \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+\r
+#include "CasServer.h"\r
+#include "BCasCard.h"\r
+\r
+#define FALSE 0
+#define TRUE 1\r
+\r
+CCasServer::CCasServer(ICasServerHandler *pEventHandler)\r
+       : m_pEventHandler(pEventHandler)\r
+       , m_hServerThread(NULL)\r
+{\r
+\r
+}\r
+\r
+CCasServer::~CCasServer(void)\r
+{\r
+       CloseServer();\r
+}\r
+\r
+const BOOL CCasServer::OpenServer(const WORD wServerPort)\r
+{\r
+       // \83J\81[\83h\83\8a\81[\83_\91\8dÝ\83`\83F\83b\83N\r
+       CBcasCard BCasCard;\r
+       if(!BCasCard.OpenCard())return FALSE;\r
+\r
+       // \83T\81[\83o\83\\83P\83b\83g\83I\81[\83v\83\93\r
+       if(!m_pSocket.Listen(wServerPort))return FALSE;\r
+\r
+       // \83T\81[\83o\83X\83\8c\83b\83h\8bN\93®\r
+       pthread_create(&m_hServerThread, NULL, CCasServer::ServerThreadRaw, (LPVOID)this);\r
+       if(!m_hServerThread){\r
+               m_pSocket.Close();\r
+               return FALSE;\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+void CCasServer::CloseServer(void)\r
+{\r
+       // \83T\81[\83o\83\\83P\83b\83g\83N\83\8d\81[\83Y\r
+       m_pSocket.Close();\r
+\r
+       // \83X\83\8c\83b\83h\83n\83\93\83h\83\8b\8aJ\95ú\r
+       if(m_hServerThread){\r
+               pthread_join(m_hServerThread, NULL);\r
+               m_hServerThread = NULL;\r
+       }\r
+\r
+       // \91S\83N\83\89\83C\83A\83\93\83g\90Ø\92f\r
+       m_Lock.Lock();\r
+       \r
+       for(ClientList::iterator It = m_ClientList.begin() ; It != m_ClientList.end() ; It++){\r
+               It->first->CloseClient();\r
+               }\r
+\r
+       m_Lock.Unlock();\r
+       \r
+       // \91S\83N\83\89\83C\83A\83\93\83g\82Ì\8fI\97¹\82ð\91Ò\82Â\r
+       while(m_ClientList.size()) sleep(1UL);\r
+}\r
+\r
+const DWORD CCasServer::GetClientNum(void) const\r
+{\r
+       // \90Ú\91±\92\86\82Ì\83N\83\89\83C\83A\83\93\83g\90\94\82ð\95Ô\82·\r
+       return m_ClientList.size();\r
+}\r
+\r
+void CCasServer::OnCasClientEvent(CCasClient *pClient, const DWORD dwEventID, PVOID pParam)\r
+{\r
+       CBlockLock AutoLock(&m_Lock);\r
+\r
+       // \83N\83\89\83C\83A\83\93\83g\83C\83x\83\93\83g\r
+       switch(dwEventID){\r
+               case CCasClient::EID_CONNECTED :\r
+                       // \83\8a\83X\83g\82É\92Ç\89Á\r
+                       m_ClientList[pClient] = pClient;\r
+                       if (m_pEventHandler) m_pEventHandler->OnCasServerEvent(this, CSEI_CONNECTED);\r
+                       break;\r
+                       \r
+               case CCasClient::EID_DISCONNECTED :\r
+                       // \83\8a\83X\83g\82©\82ç\8dí\8f\9c\r
+                       m_ClientList.erase(pClient);\r
+                       if (m_pEventHandler) m_pEventHandler->OnCasServerEvent(this, CSEI_DISCONNECTED);\r
+                       break;\r
+               }\r
+}\r
+\r
+void CCasServer::ServerThread(void)\r
+{\r
+       // \83A\83N\83Z\83v\83g\83\8b\81[\83v\r
+       CSmartSock *pNewSocket;\r
+       \r
+       while(pNewSocket = m_pSocket.Accept()){\r
+               // \83N\83\89\83C\83A\83\93\83g\83C\83\93\83X\83^\83\93\83X\90\90¬\r
+               new CCasClient(this, pNewSocket);\r
+               }\r
+}\r
+\r
+void* CCasServer::ServerThreadRaw(LPVOID pParam)\r
+{\r
+       // \83T\81[\83o\83X\83\8c\83b\83h\r
+       static_cast<CCasServer *>(pParam)->ServerThread();\r
+\r
+       return 0UL;\r
+}\r
diff --git a/dist/trunk/b25-remote/CasServer.h b/dist/trunk/b25-remote/CasServer.h
new file mode 100755 (executable)
index 0000000..35d7732
--- /dev/null
@@ -0,0 +1,56 @@
+// CasServer.h: CCasServer \83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+\r
+#include <map>\r
+#include "CasClient.h"\r
+#include "TsUtilClass.h"\r
+#include "SmartSock.h"\r
+\r
+\r
+using std::map;\r
+\r
+\r
+class CCasServer : protected CCasClient::ICasClientHandler\r
+{\r
+public:\r
+       class ICasServerHandler\r
+       {\r
+       public:\r
+               virtual void OnCasServerEvent(CCasServer *pCasServer, const WORD wEventID) = 0;\r
+       };\r
+\r
+       enum\r
+       {\r
+               CSEI_CONNECTED,         // \83N\83\89\83C\83A\83\93\83g\90Ú\91±\r
+               CSEI_DISCONNECTED,      // \83N\83\89\83C\83A\83\93\83g\90Ø\92f\r
+       };\r
+\r
+       CCasServer(void);\r
+       CCasServer(ICasServerHandler *pEventHandler);\r
+       ~CCasServer(void);\r
+\r
+       const BOOL OpenServer(const WORD wServerPort);\r
+       void CloseServer(void);\r
+       \r
+       const DWORD GetClientNum(void) const;\r
+\r
+protected:\r
+       virtual void OnCasClientEvent(CCasClient *pClient, const DWORD dwEventID, PVOID pParam);\r
+\r
+       void ServerThread(void);\r
+       static void* ServerThreadRaw(LPVOID pParam);\r
+\r
+       ICasServerHandler *m_pEventHandler;\r
+\r
+       CSmartSock m_pSocket;\r
+       pthread_t m_hServerThread;
+\r
+       typedef map<CCasClient *, CCasClient *> ClientList;\r
+       ClientList m_ClientList;\r
+       \r
+       CCriticalLock m_Lock;\r
+};\r
diff --git a/dist/trunk/b25-remote/Makefile b/dist/trunk/b25-remote/Makefile
new file mode 100755 (executable)
index 0000000..ed4d823
--- /dev/null
@@ -0,0 +1,45 @@
+PREFIX                 = /usr/local
+TARGET_SERVER          = b25-server
+TARGET_CLIENT          = b25-client.so
+OBJ_SERVER             = BCasCard.o CasClient.o CasServer.o SmartSock.o TsUtilClass.o b25-server.o
+HEADER_SERVER          = BCasCard.h CasClient.h CasServer.h SmartSock.h TsUtilClass.h
+OBJ_CLIENT             = CasProxy.o SmartSock.o b25-client.o
+HEADER_CLIENT          = CasProxy.h SmartSock.h
+PCSC_CFLAGS            = `pkg-config libpcsclite --cflags`
+PCSC_LDLIBS            = `pkg-config libpcsclite --libs`
+
+CC                     = g++
+CFLAGS                 = -fPIC -O2 -Wall -g ${PCSC_CFLAGS}
+CFLAGS_FOR_LIB = -fPIC -shared
+LDFLAGS                = -pthread ${PCSC_LDLIBS}
+LIBS                   = 
+
+.cpp.o:
+                       ${CC} $(CFLAGS) -c $<
+
+.c.o:
+                       ${CC} $(CFLAGS) -c $<
+
+all:                   ${TARGET_SERVER} ${TARGET_CLIENT}
+
+${TARGET_SERVER}:      ${OBJ_SERVER}
+                       ${CC} ${CFLAGS} ${OBJ_SERVER} -o $@ ${LDFLAGS} ${LIBS}
+
+${TARGET_CLIENT}:      ${OBJ_CLIENT}
+                       ${CC} ${CFLAGS_FOR_LIB} ${OBJ_CLIENT} -o $@ ${LDFLAGS} ${LIBS}
+
+${OBJ_SERVER}: ${HEADER_SERVER}
+
+${OBJ_CLIENT}: ${HEADER_CLIENT}
+
+install:               ${TARGET_SERVER} ${TARGET_CLIENT}
+                       install -m755 ${TARGET_SERVER} ${PREFIX}/bin
+                       install -m755 ${TARGET_CLIENT} ${PREFIX}/lib
+
+uninstall:
+                       rm ${PREFIX}/bin/${TARGET_SERVER}
+                       rm ${PREFIX}/lib/${TARGET_CLIENT}
+
+clean:
+                       rm -f core ${TARGET_SERVER} *.o *.so
+
diff --git a/dist/trunk/b25-remote/Readme.txt b/dist/trunk/b25-remote/Readme.txt
new file mode 100755 (executable)
index 0000000..0f591d0
--- /dev/null
@@ -0,0 +1,56 @@
+
+- b25-remote Ver.0.0.1 -
+
+
+1.概要
+  ・スマートカードリーダをLANを経由で共有するためのシステムです。
+  ・BonCasLink互換プロトコルを使用します。
+
+ 
+2.注意事項
+  ・一般的にスマートカードには個人を特定可能な情報が含まれている可能性があります。
+  ・本ソフトウェアは通信の暗号化を行わないためこのリスクを十分に考えた上でご使用ください。
+  ・本ソフトウェアの警告を無視しLAN以外のネットワークにおいて使用した結果発生したいかなる
+   損害も作者に責任を求めないこととします。
+
+
+3.ライセンスについて
+  ・本パッケージに含まれる全てのソースコード、バイナリについて著作権は一切主張しません。
+  ・オリジナルのまま又は改変し、各自のソフトウェアに自由に添付、組み込むことができます。
+  ・但しGPLに従うことを要求しますのでこれらを行う場合はソースコードの開示が必須となります。
+  ・このとき本ソフトウェアの著作権表示を行うかどうかは任意です。
+
+  ・通信プロトコルの変更及び追加を含むソースコードの改変は一切許可できません。
+  ・上記を禁止するいかなる根拠または拘束力も作者にはありませんがこれに反して、
+   作成した改変物を配布する場合は下記を要求します。
+  ・ソフトウェアの名称を「b25-remote」以外に変更すること。
+  ・「Rec10」の著作権表示を一切行わないこと。
+  ・ソースコードの流用元の表示を一切行わないこと。
+  ・このソースコードは拡張ツール中の人(nakanohito@2sen.dip.jp)が作成されたBonCasLink(公式サイト:http://2sen.dip.jp/friio/)のソースコードを流用しています。
+
+  ・ビルドに必要な環境
+   - pcsc-lite-devel ※Fedora系
+   - libpcsclite-dev ※Debian系
+
+
+4.使用方法
+  ①スマートカードリーダが接続されたPCで「b25-server」を起動します。
+
+  ②LANに参加している他のPCでPCSCを利用するアプリケーションを起動します。
+
+  ③このとき環境変数を以下のように設定します。
+   LD_PRELOAD      = {b25-client.soの絶対パス}
+   B25_REMOTE_IP   = {サーバーのアドレス(DNS可)}
+   B25_REMOTE_PORT = {サーバーの使用ポート(デフォルト:6900)}
+
+   ※ファイヤウォールやフィルタリングを使用している場合は共有に使用するポートを開放してください。
+
+
+6.サポート、連絡先
+   連絡先  : Rec10
+   公式サイト: http://sourceforge.jp/projects/rec10/
+
+
+8.更新履歴
+ Ver.0.0.1 ・初回リリース
+
diff --git a/dist/trunk/b25-remote/SmartSock.cpp b/dist/trunk/b25-remote/SmartSock.cpp
new file mode 100755 (executable)
index 0000000..cbf802c
--- /dev/null
@@ -0,0 +1,572 @@
+// SmartSock.cpp: CSmartSock \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include "SmartSock.h"\r
+#include <stdio.h>
+#include <sys/time.h>\r
+\r
+#ifdef _DEBUG\r
+#define new DEBUG_NEW\r
+#endif\r
+
+//#pragma warning(disable: 4101) // warning C4101: "\83\8d\81[\83J\83\8b\95Ï\90\94\82Í 1 \93x\82à\8eg\82í\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B"\r
+//#pragma warning(disable: 4996) // warning C4996: "This function or variable may be unsafe. Consider using _wsplitpath_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details"\r
+\r
+\r
+//#pragma comment(lib, "WS2_32")\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// \83}\83N\83\8d\92è\8b`\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#define CHECK_FREESOCK(R)      if(m_Socket != INVALID_SOCKET){m_dwLastError = EC_SOCKINVALID; return (R);}\r
+#define CHECK_TCPSOCK(R)       if((m_Socket == INVALID_SOCKET) || (m_bSockType != SOCKTYPE_TCP)){m_dwLastError = EC_SOCKINVALID; return (R);}\r
+#define CHECK_UDPSOCK(R)       if((m_Socket == INVALID_SOCKET) || (m_bSockType != SOCKTYPE_UDP)){m_dwLastError = EC_SOCKINVALID; return (R);}\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// \8d\\92z/\8fÁ\96Å\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+DWORD CSmartSock::dwInstanceNum = 0UL;\r
+\r
+CSmartSock::CSmartSock()\r
+       : m_Socket(INVALID_SOCKET)\r
+       , m_bSockType(SOCKTYPE_NON)\r
+       , m_dwLastError(EC_NOERROR)\r
+{\r
+       // WinSock2\8f\89\8aú\89»\r
+       if(!(dwInstanceNum++))InitWinSock2();\r
+}\r
+\r
+CSmartSock::~CSmartSock()\r
+{\r
+       Close();\r
+\r
+       // WinSock2\8aJ\95ú\r
+       if(!(--dwInstanceNum))FreeWinSock2();\r
+}\r
+\r
+const BOOL CSmartSock::Connect(LPCTSTR lpszHost, const WORD wPort, const DWORD dwTimeOut)\r
+{\r
+       CHECK_FREESOCK(FALSE);\r
+\r
+       if(!lpszHost){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return FALSE;\r
+               }\r
+               \r
+       // \83A\83h\83\8c\83X\96¼\82©\82çIP\83A\83h\83\8c\83X\8eæ\93¾\r
+       const DWORD dwIP = HostToIP(lpszHost);\r
+\r
+       if(dwIP == INADDR_NONE){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;           \r
+               }\r
+       \r
+       return Connect(dwIP, wPort, dwTimeOut);\r
+}\r
+\r
+const BOOL CSmartSock::Connect(const DWORD dwIP, const WORD wPort, const DWORD dwTimeOut)\r
+{\r
+       CHECK_FREESOCK(FALSE);\r
+\r
+       // \83\\83P\83b\83g\8dì\90¬\r
+       if((m_Socket = ::socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;           \r
+               }\r
+\r
+       // \83A\83h\83\8c\83X\90Ý\92è\r
+       SOCKADDR_IN SockAddr;\r
+       SockAddr.sin_family = AF_INET;\r
+       SockAddr.sin_port = htons(wPort);\r
+       SockAddr.sin_addr.s_addr = htonl(dwIP);\r
+\r
+       // \93¯\8aú\83R\83l\83N\83g\r
+       if(!dwTimeOut){\r
+               if(::connect(m_Socket, (PSOCKADDR)&SockAddr, sizeof(sockaddr))){\r
+                       Close();\r
+                       m_dwLastError = EC_SOCKERROR;\r
+                       return FALSE;           \r
+                       }\r
+       \r
+               m_dwLastError = EC_NOERROR;\r
+               return TRUE;\r
+       }\r
+\r
+       // \94ñ\93¯\8aú\83R\83l\83N\83g\r
+       u_long nArg;\r
+       fd_set FdSet;\r
+       struct timeval TimeVal;\r
+       TimeVal.tv_sec = 10UL;\r
+       TimeVal.tv_usec = 0UL;
+       nArg = fcntl(m_Socket, F_GETFL, 0);\r
+       FD_ZERO(&FdSet);\r
+       FD_SET(m_Socket, &FdSet);\r
+\r
+       try{\r
+               // \94ñ\93¯\8aú\82É\90Ø\82è\91Ö\82¦\r
+               if(::fcntl(m_Socket, F_SETFL, nArg | O_NONBLOCK) == SOCKET_ERROR)throw (const DWORD)__LINE__;\r
+\r
+               // \83R\83l\83N\83g\r
+               if(::connect(m_Socket, (PSOCKADDR)&SockAddr, sizeof(sockaddr)) != SOCKET_ERROR)throw (const DWORD)__LINE__;\r
+\r
+               if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINPROGRESS)throw (const DWORD)__LINE__;\r
+\r
+               // \90Ú\91±\8a®\97¹\91Ò\82¿\r
+               if(!::select(32, NULL, &FdSet, NULL, &TimeVal))throw (const DWORD)__LINE__;\r
+\r
+               // \83^\83C\83\80\83A\83E\83g\94»\92è\r
+               if(!FD_ISSET(m_Socket, &FdSet)){\r
+                       Close();\r
+                       m_dwLastError = EC_TIMEOUT;\r
+                       return FALSE;\r
+                       }\r
+\r
+               // \93¯\8aú\82É\90Ø\82è\91Ö\82¦\r
+               if(::fcntl(m_Socket, F_SETFL, nArg) == SOCKET_ERROR)throw (const DWORD)__LINE__;\r
+               }\r
+       catch(const DWORD dwLine){\r
+               // \83G\83\89\81[\94­\90\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       m_bSockType = SOCKTYPE_TCP;\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return TRUE;\r
+}\r
+\r
+const BOOL CSmartSock::Listen(const WORD wPort)\r
+{\r
+       CHECK_FREESOCK(FALSE);\r
+\r
+       // \83\\83P\83b\83g\8dì\90¬\r
+       if((m_Socket = ::socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;           \r
+               }\r
+\r
+       // \83A\83h\83\8c\83X\90Ý\92è\r
+       SOCKADDR_IN SockAddr;\r
+       SockAddr.sin_family = AF_INET;\r
+       SockAddr.sin_port = htons(wPort);\r
+       SockAddr.sin_addr.s_addr = INADDR_ANY;\r
+\r
+       try{\r
+               // \81u\83A\83h\83\8c\83X\8eg\97p\92\86\81v\83G\83\89\81[\82ð\89ñ\94ð
+               int on = 1;
+               setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+               // \83o\83C\83\93\83h\r
+               if(::bind(m_Socket, (PSOCKADDR)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR)throw (const DWORD)__LINE__;\r
+\r
+               // \90Ú\91±\8eó\82¯\93ü\82ê\r
+               if(::listen(m_Socket, 5) == SOCKET_ERROR)throw (const DWORD)__LINE__;\r
+               }\r
+       catch(const DWORD dwLine){\r
+               // \83G\83\89\81[\94­\90\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       m_bSockType = SOCKTYPE_TCP;\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return TRUE;\r
+}\r
+\r
+CSmartSock * CSmartSock::Accept(void)\r
+{\r
+       CHECK_TCPSOCK(FALSE);\r
+       \r
+       SOCKADDR_IN AddrIn;\r
+       memset(&AddrIn, 0, sizeof(AddrIn));\r
+       socklen_t iAddrLen = sizeof(AddrIn);\r
+\r
+       // \83R\83l\83N\83g\8eó\82¯\93ü\82ê\r
+       SOCKET SockIn = ::accept(m_Socket, (sockaddr *)&AddrIn, &iAddrLen);\r
+\r
+       if(SockIn == INVALID_SOCKET){\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return NULL;\r
+               }\r
+\r
+       CSmartSock *pNewSock = new CSmartSock;\r
+       pNewSock->m_Socket = SockIn;\r
+       pNewSock->m_bSockType = SOCKTYPE_TCP;\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return pNewSock;\r
+}\r
+\r
+const BOOL CSmartSock::Send(const BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut)\r
+{\r
+       CHECK_TCPSOCK(FALSE);\r
+\r
+       if(!pBuff || !dwLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return FALSE;\r
+               }\r
+\r
+       // \8ew\92è\83T\83C\83Y\91\97\90M\r
+       DWORD dwRef = 0UL, dwSend = 0UL;\r
+\r
+       do{
+               dwRef = SendOnce(pBuff + dwSend, dwLen - dwSend, dwTimeOut);
+               if(!dwRef) return FALSE;\r
+       }\r
+       while((dwSend += dwRef) < dwLen);\r
+\r
+       return TRUE;\r
+}\r
+\r
+const BOOL CSmartSock::Recv(BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut)\r
+{\r
+       CHECK_TCPSOCK(FALSE);\r
+\r
+       if(!pBuff || !dwLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return FALSE;\r
+       }\r
+\r
+       // \8ew\92è\83T\83C\83Y\8eó\90M\r
+       DWORD dwRef = 0UL, dwRecv = 0UL;\r
+
+       do{\r
+               if(!(dwRef = RecvOnce(pBuff + dwRecv, dwLen - dwRecv, dwTimeOut)))return FALSE;\r
+       }\r
+       while((dwRecv += dwRef) < dwLen);
+\r
+       return TRUE;\r
+}\r
+\r
+const DWORD CSmartSock::SendOnce(const BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut)\r
+{\r
+       CHECK_TCPSOCK(0UL);\r
+\r
+       if(!pBuff || !dwMaxLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return FALSE;\r
+               }\r
+       \r
+       // \83^\83C\83\80\83A\83E\83g\90Ý\92è\r
+       struct timeval stTimeOut;\r
+\r
+       stTimeOut.tv_sec = 10UL;
+       stTimeOut.tv_usec = 0UL;\r
+       if(::setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&stTimeOut, sizeof(struct timeval))){\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;
+               return 0UL;\r
+       }\r
+
+       // \91\97\90M\r
+       const int iRef = ::send(m_Socket, (const char *)pBuff, dwMaxLen, 0);\r
+\r
+       if((iRef == SOCKET_ERROR) || !iRef){\r
+               if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS){\r
+                       m_dwLastError = EC_TIMEOUT;\r
+                       return 0UL;\r
+                       }\r
+               else{\r
+                       Close();\r
+                       m_dwLastError = EC_SOCKERROR;\r
+                       return 0UL;\r
+                       }\r
+               }\r
+               \r
+       m_dwLastError = EC_NOERROR;\r
+               \r
+       return (DWORD)iRef;\r
+}\r
+\r
+const DWORD CSmartSock::RecvOnce(BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut)\r
+{\r
+       CHECK_TCPSOCK(0UL);\r
+       \r
+       if(!pBuff || !dwMaxLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return FALSE;\r
+               }\r
+\r
+       // \83^\83C\83\80\83A\83E\83g\92l\90Ý\92è\r
+       struct timeval stTimeOut;\r
+
+       stTimeOut.tv_sec = 10UL;
+       stTimeOut.tv_usec = 0UL;\r
+       if(::setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&stTimeOut, sizeof(struct timeval))){\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;
+               return 0UL;\r
+       }\r
+       
+       // \8eó\90M\r
+       int iRef = ::recv(m_Socket, (char *)pBuff, dwMaxLen, 0);\r
+\r
+       if((iRef == SOCKET_ERROR) || !iRef){
+               if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS){
+                       m_dwLastError = EC_TIMEOUT;\r
+                       return 0UL;\r
+                       }\r
+               else{\r
+                       Close();\r
+                       m_dwLastError = EC_SOCKERROR;\r
+                       return 0UL;\r
+                       }\r
+               }\r
+
+       m_dwLastError = EC_NOERROR;\r
+               \r
+       return (DWORD)iRef;\r
+}\r
+\r
+const BOOL CSmartSock::GetLocalAddr(DWORD *pdwIP, WORD *pwPort)\r
+{\r
+       CHECK_TCPSOCK(FALSE);\r
+\r
+       struct sockaddr_in LocalAddr;\r
+       socklen_t AddrLen = sizeof(LocalAddr);\r
+       \r
+       // \83\8d\81[\83J\83\8b\83A\83h\83\8c\83X\8eæ\93¾\r
+       if(::getsockname(m_Socket, (struct sockaddr *)&LocalAddr, &AddrLen) == SOCKET_ERROR){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       if(pdwIP)*pdwIP = htonl(LocalAddr.sin_addr.s_addr);\r
+       if(pwPort)*pwPort = ntohs(LocalAddr.sin_port);\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return TRUE;\r
+}\r
+\r
+const BOOL CSmartSock::GetPeerAddr(DWORD *pIP, WORD *pPort)\r
+{\r
+       CHECK_TCPSOCK(FALSE);\r
+\r
+       struct sockaddr_in PeerAddr;\r
+       socklen_t AddrLen = sizeof(PeerAddr);\r
+       \r
+       // \83s\83A\83A\83h\83\8c\83X\8eæ\93¾\r
+       if(::getpeername(m_Socket, (struct sockaddr *)&PeerAddr, &AddrLen) == SOCKET_ERROR){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       if(pIP)*pIP = htonl(PeerAddr.sin_addr.s_addr);\r
+       if(pPort)*pPort = ntohs(PeerAddr.sin_port);\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return TRUE;\r
+}\r
+\r
+const BOOL CSmartSock::Bind()\r
+{\r
+       CHECK_FREESOCK(FALSE);\r
+\r
+       // UDP\83\\83P\83b\83g\8dì\90¬\r
+       if((m_Socket = ::socket(PF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       // \83A\83h\83\8c\83X\90Ý\92è\r
+       SOCKADDR_IN SockAddr;\r
+       SockAddr.sin_family = AF_INET;\r
+       SockAddr.sin_port = 0U;\r
+       SockAddr.sin_addr.s_addr = INADDR_ANY;\r
+\r
+       // \83o\83C\83\93\83h\r
+       if(::bind(m_Socket, (struct sockaddr *)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR){\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+       m_bSockType = SOCKTYPE_UDP;\r
+       \r
+       return TRUE;\r
+}\r
+\r
+const DWORD CSmartSock::SendTo(const DWORD dwIP, const WORD wPort, const BYTE *pBuff, const DWORD dwLen)\r
+{\r
+       CHECK_UDPSOCK(0UL);\r
+\r
+       if(!pBuff || !dwLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return 0UL;\r
+               }\r
+\r
+       // \83A\83h\83\8c\83X\90Ý\92è\r
+       SOCKADDR_IN SockAddr;\r
+       SockAddr.sin_family = AF_INET;\r
+       SockAddr.sin_port = htons(wPort);\r
+       SockAddr.sin_addr.s_addr = htonl(dwIP);\r
+\r
+       // \91\97\90M\r
+       int iSend = sendto(m_Socket, (const char *)pBuff, dwLen, 0, (struct sockaddr *)&SockAddr, sizeof(SockAddr));\r
+       \r
+       if(iSend == SOCKET_ERROR){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return 0UL;\r
+               }\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return (DWORD)iSend;\r
+}\r
+\r
+const DWORD CSmartSock::SendTo(LPCTSTR lpszHost, const WORD wPort, const BYTE *pBuff, const DWORD dwLen)\r
+{\r
+       CHECK_UDPSOCK(0UL);\r
+\r
+       if(!lpszHost || !pBuff || !dwLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return 0UL;\r
+               }\r
+               \r
+       // \83A\83h\83\8c\83X\96¼\82©\82çIP\83A\83h\83\8c\83X\8eæ\93¾\r
+       const DWORD dwIP = HostToIP(lpszHost);\r
+\r
+       if(dwIP == INADDR_NONE){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return 0UL;             \r
+               }\r
+       \r
+       return SendTo(dwIP, wPort, pBuff, dwLen);\r
+}\r
+\r
+const DWORD CSmartSock::RecvFrom(BYTE *pBuff, const DWORD dwLen, DWORD *pdwIP, WORD *pwPort)\r
+{\r
+       CHECK_UDPSOCK(0UL);\r
+\r
+       if(!pBuff || !dwLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return 0UL;\r
+               }\r
+\r
+       // \83A\83h\83\8c\83X\90Ý\92è\r
+       socklen_t iSockSize = sizeof(SOCKADDR_IN);\r
+       SOCKADDR_IN SockAddr;\r
+       SockAddr.sin_family = AF_INET;\r
+       SockAddr.sin_port = 0U;\r
+       SockAddr.sin_addr.s_addr = 0UL;\r
+\r
+       // \8eó\90M\r
+       const int iRecv = ::recvfrom(m_Socket, (char *)pBuff, dwLen, 0, (struct sockaddr *)&SockAddr, &iSockSize);\r
+\r
+       if(iRecv == SOCKET_ERROR){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return 0UL;\r
+               }\r
+\r
+       if(pdwIP)*pdwIP = SockAddr.sin_addr.s_addr;\r
+       if(pwPort)*pwPort = ntohs(SockAddr.sin_port);\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return (DWORD)iRecv;\r
+}\r
+\r
+const BOOL CSmartSock::Close()\r
+{\r
+       // \83\\83P\83b\83g\83N\83\8d\81[\83Y\r
+       if(m_Socket != INVALID_SOCKET){\r
+               if(m_bSockType == SOCKTYPE_TCP){\r
+                       char byData;\r
+                       ::shutdown(m_Socket, SD_BOTH);\r
+                       while(::recv(m_Socket, &byData, 1, 0) == 1);\r
+                       }\r
+\r
+               ::close(m_Socket);\r
+               m_Socket = INVALID_SOCKET;\r
+               }\r
+       \r
+       m_bSockType = SOCKTYPE_NON;\r
+       m_dwLastError = EC_NOERROR;\r
+       \r
+       return TRUE;\r
+}\r
+\r
+const DWORD CSmartSock::HostToIP(LPCTSTR lpszHost)\r
+{\r
+#ifdef _UNICODE\r
+       char szHost[1024] = {"\0"};\r
+       ::wcstombs(szHost, lpszHost, sizeof(szHost) - 1);\r
+#else\r
+       LPCSTR szHost = lpszHost;\r
+#endif\r
+\r
+       // \83z\83X\83g\96¼\82©\82çIP\83A\83h\83\8c\83X\8eæ\93¾\r
+       const DWORD dwIP = ::inet_addr(szHost);\r
+\r
+       if(dwIP == INADDR_NONE){\r
+               struct hostent *pHost = ::gethostbyname(szHost);\r
+               if(!pHost){             \r
+                       return INADDR_NONE;\r
+                       }\r
+               else return *((DWORD *)pHost->h_addr_list[0]);\r
+               }\r
+       else return htonl(dwIP);\r
+}\r
+\r
+const DWORD CSmartSock::IPToHost(LPTSTR lpszHost, const DWORD dwIP)\r
+{\r
+       if(!lpszHost)return FALSE;\r
+\r
+       // IP\83A\83h\83\8c\83X\82©\82ç\83z\83X\83g\96¼\8eæ\93¾\r
+       const DWORD dwNetIP = htonl(dwIP);\r
+       struct hostent *pHost = ::gethostbyaddr((const char *)&dwNetIP, sizeof(dwNetIP), AF_INET);\r
+       if(!pHost)return FALSE;\r
+\r
+#ifdef _UNICODE\r
+       ::mbstowcs(lpszHost, pHost->h_name, ::lstrlenA(pHost->h_name));\r
+#else\r
+       ::strcpy(lpszHost, pHost->h_name);\r
+#endif\r
+\r
+       return ::strlen(lpszHost);\r
+}\r
+\r
+const DWORD CSmartSock::GetLastError() const\r
+{\r
+       // \8dÅ\8cã\82É\94­\90\82µ\82½\83G\83\89\81[\82ð\95Ô\82·\r
+       return m_dwLastError;\r
+}\r
+\r
+const BOOL CSmartSock::InitWinSock2(void)\r
+{\r
+#ifdef _UNICODE\r
+       ::setlocale(LC_ALL, "japanese");\r
+#endif\r
+/*\r
+       WSADATA WsaData;\r
+\r
+       // WinSock2\8f\89\8aú\89»\r
+       if(::WSAStartup(MAKEWORD(2, 2), &WsaData))return FALSE;\r
+\r
+       if((LOBYTE(WsaData.wVersion) != 2U) || (HIBYTE(WsaData.wVersion) != 2U))return FALSE;\r
+*/\r
+       return TRUE;\r
+}\r
+\r
+const BOOL CSmartSock::FreeWinSock2(void)\r
+{\r
+/*
+       // WinSock2\8aJ\95ú\r
+       return (::WSACleanup())? TRUE : FALSE;\r
+*/
+       return TRUE;
+}\r
diff --git a/dist/trunk/b25-remote/SmartSock.h b/dist/trunk/b25-remote/SmartSock.h
new file mode 100755 (executable)
index 0000000..d735339
--- /dev/null
@@ -0,0 +1,79 @@
+// SmartSock.h: CSmartSock \83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+#include "W2L.h"\r
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+\r
+#define BOOL bool
+#define LPTSTR char*
+#define LPCTSTR const char*
+#define LPCSTR const char*
+#define BYTE  unsigned char
+#define WORD  unsigned short
+#define DWORD unsigned long
+#define SOCKET int
+\r
+// WinSock2\83^\83C\83\80\83A\83E\83g\91Î\89\9e\83\89\83b\83p\81[\83N\83\89\83X      http://2sen.dip.jp/friio/\r
+class CSmartSock\r
+{\r
+public:\r
+       enum                                    // LastError\83R\81[\83h\r
+       {\r
+               EC_NOERROR,                     // \90³\8fí\8fI\97¹\r
+               EC_SOCKERROR,           // \83\\83P\83b\83g\83G\83\89\81[\r
+               EC_TIMEOUT,                     // \83^\83C\83\80\83A\83E\83g\r
+               EC_SOCKINVALID,         // \83\\83P\83b\83g\82ª\96³\8cø\r
+               EC_PARAMINVALID         // \83p\83\89\83\81\81[\83^\82ª\96³\8cø\r
+       };\r
+\r
+       CSmartSock();\r
+       virtual ~CSmartSock();\r
+\r
+// TCP\83\\83P\83b\83g\r
+       const BOOL Connect(LPCTSTR lpszHost, const WORD wPort, const DWORD dwTimeOut = 0UL);\r
+       const BOOL Connect(const DWORD dwIP, const WORD wPort, const DWORD dwTimeOut = 0UL);\r
+\r
+       const BOOL Listen(const WORD wPort);\r
+       CSmartSock * Accept(void);\r
+\r
+       const BOOL Send(const BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut = 0UL);\r
+       const BOOL Recv(BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut = 0UL);\r
+       const DWORD SendOnce(const BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut = 0UL);\r
+       const DWORD RecvOnce(BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut = 0UL);\r
+\r
+       const BOOL GetLocalAddr(DWORD *pdwIP, WORD *pwPort = NULL);\r
+       const BOOL GetPeerAddr(DWORD *pdwIP, WORD *pwPort = NULL);\r
+\r
+// UDP\83\\83P\83b\83g\r
+       const BOOL Bind(void);\r
+\r
+       const DWORD SendTo(const DWORD dwIP, const WORD wPort, const BYTE *pBuff, const DWORD dwLen);\r
+       const DWORD SendTo(LPCTSTR lpszHost, const WORD wPort, const BYTE *pBuff, const DWORD dwLen);\r
+       const DWORD RecvFrom(BYTE *pBuff, const DWORD dwLen, DWORD *pdwIP = NULL, WORD *pwPort = NULL);\r
+\r
+       const BOOL Close(void);\r
+\r
+       static const DWORD HostToIP(LPCTSTR lpszHost);\r
+       static const DWORD IPToHost(LPTSTR lpszHost, const DWORD dwIP);\r
+\r
+       const DWORD GetLastError(void) const;\r
+\r
+protected:\r
+       static const BOOL InitWinSock2(void);\r
+       static const BOOL FreeWinSock2(void);\r
+\r
+       enum {SOCKTYPE_NON, SOCKTYPE_TCP, SOCKTYPE_UDP};\r
+\r
+       int m_Socket;                           // \83\\83P\83b\83g\83n\83\93\83h\83\8b\r
+       BYTE m_bSockType;                               // \83\\83P\83b\83g\83^\83C\83v\r
+       DWORD m_dwLastError;                    // \8dÅ\8fI\83G\83\89\81[\83R\81[\83h\r
+       static DWORD dwInstanceNum;             // \83C\83\93\83X\83^\83\93\83X\82Ì\90\94\r
+};\r
diff --git a/dist/trunk/b25-remote/TsUtilClass.cpp b/dist/trunk/b25-remote/TsUtilClass.cpp
new file mode 100755 (executable)
index 0000000..ec4c298
--- /dev/null
@@ -0,0 +1,88 @@
+// TsUtilClass.cpp: TS\83\86\81[\83e\83B\83\8a\83e\83B\81[\83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include "TsUtilClass.h"\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// CDynamicReferenceable \83N\83\89\83X\82Ì\8d\\92z/\8fÁ\96Å\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+CDynamicReferenceable::CDynamicReferenceable()\r
+       : m_dwRefCount(0UL)\r
+{\r
+\r
+}\r
+\r
+CDynamicReferenceable::~CDynamicReferenceable()\r
+{\r
+\r
+}\r
+\r
+void CDynamicReferenceable::AddRef(void)\r
+{\r
+       // \8eQ\8fÆ\83J\83E\83\93\83g\83C\83\93\83N\83\8a\83\81\83\93\83g\r
+       m_dwRefCount++;\r
+}\r
+\r
+void CDynamicReferenceable::ReleaseRef(void)\r
+{\r
+       // \8eQ\8fÆ\83J\83E\83\93\83g\83f\83N\83\8a\83\81\83\93\83g\r
+       if(m_dwRefCount){\r
+               // \83C\83\93\83X\83^\83\93\83X\8aJ\95ú\r
+               if(!(--m_dwRefCount))delete this;\r
+               }\r
+#ifdef _DEBUG\r
+       else{\r
+               ::DebugBreak();\r
+               }\r
+#endif\r
+}\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// CCriticalLock \83N\83\89\83X\82Ì\8d\\92z/\8fÁ\96Å\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+CCriticalLock::CCriticalLock()\r
+{\r
+       // \83N\83\8a\83e\83B\83J\83\8b\83Z\83N\83V\83\87\83\93\8f\89\8aú\89»\r
+       pthread_mutex_init(&m_CriticalSection, NULL);\r
+}\r
+\r
+CCriticalLock::~CCriticalLock()\r
+{\r
+       // \83N\83\8a\83e\83B\83J\83\8b\83Z\83N\83V\83\87\83\93\8dí\8f\9c\r
+       pthread_mutex_destroy(&m_CriticalSection);\r
+}\r
+\r
+void CCriticalLock::Lock(void)\r
+{\r
+       // \83N\83\8a\83e\83B\83J\83\8b\83Z\83N\83V\83\87\83\93\8eæ\93¾\r
+       pthread_mutex_lock(&m_CriticalSection);\r
+}\r
+\r
+void CCriticalLock::Unlock(void)\r
+{\r
+       // \83N\83\8a\83e\83B\83J\83\8b\83Z\83N\83V\83\87\83\93\8aJ\95ú\r
+       pthread_mutex_unlock(&m_CriticalSection);\r
+}\r
+       \r
+       \r
+//////////////////////////////////////////////////////////////////////\r
+// CBlockLock \83N\83\89\83X\82Ì\8d\\92z/\8fÁ\96Å\r
+//////////////////////////////////////////////////////////////////////\r
+       \r
+CBlockLock::CBlockLock(CCriticalLock *pCriticalLock)\r
+       : m_pCriticalLock(pCriticalLock)\r
+{\r
+       // \83\8d\83b\83N\8eæ\93¾\r
+       m_pCriticalLock->Lock();\r
+}\r
+\r
+CBlockLock::~CBlockLock()\r
+{\r
+       // \83\8d\83b\83N\8aJ\95ú\r
+       m_pCriticalLock->Unlock();\r
+}\r
diff --git a/dist/trunk/b25-remote/TsUtilClass.h b/dist/trunk/b25-remote/TsUtilClass.h
new file mode 100755 (executable)
index 0000000..ebae86b
--- /dev/null
@@ -0,0 +1,61 @@
+// TsUtilClass.h: TS\83\86\81[\83e\83B\83\8a\83e\83B\81[\83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+#include "W2L.h"\r
+#include <pthread.h>
+\r
+#define DWORD unsigned long
+
+/////////////////////////////////////////////////////////////////////////////\r
+// \83_\83C\83i\83~\83b\83N\83\8a\83t\83@\83\8c\83\93\83X\8aÇ\97\9d\83x\81[\83X\83N\83\89\83X\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+class CDynamicReferenceable\r
+{\r
+public:\r
+       CDynamicReferenceable();\r
+       virtual ~CDynamicReferenceable();\r
+\r
+       void AddRef(void);\r
+       void ReleaseRef(void);\r
+\r
+private:\r
+       DWORD m_dwRefCount;\r
+};\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// \83N\83\8a\83e\83B\83J\83\8b\83Z\83N\83V\83\87\83\93\83\89\83b\83p\81[\83N\83\89\83X\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+class CCriticalLock\r
+{\r
+public:\r
+       CCriticalLock();\r
+       virtual ~CCriticalLock();\r
+       \r
+       void Lock(void);\r
+       void Unlock(void);\r
+       \r
+private:\r
+       pthread_mutex_t m_CriticalSection;\r
+};\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// \83u\83\8d\83b\83N\83X\83R\81[\83v\83\8d\83b\83N\83N\83\89\83X\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+class CBlockLock\r
+{\r
+public:\r
+       CBlockLock(CCriticalLock *pCriticalLock);\r
+       virtual ~CBlockLock();\r
+               \r
+private:\r
+       CCriticalLock *m_pCriticalLock;\r
+};\r
+\r
+\r
diff --git a/dist/trunk/b25-remote/W2L.h b/dist/trunk/b25-remote/W2L.h
new file mode 100755 (executable)
index 0000000..678823d
--- /dev/null
@@ -0,0 +1,14 @@
+#include <string.h>
+
+#define TCHAR char
+#define PVOID void*
+#define HANDLE void*
+#define TRUE 1
+#define FALSE 0
+#define INVALID_SOCKET (-1)
+#define SOCKET_ERROR (-1)
+#define SOCKADDR_IN struct sockaddr_in
+#define SOCKADDR struct sockaddr
+#define PSOCKADDR SOCKADDR*
+#define SD_BOTH SHUT_RDWR
+
diff --git a/dist/trunk/b25-remote/b25-client.cpp b/dist/trunk/b25-remote/b25-client.cpp
new file mode 100755 (executable)
index 0000000..f108e00
--- /dev/null
@@ -0,0 +1,87 @@
+// MllMain.cpp : DLL \83A\83v\83\8a\83P\81[\83V\83\87\83\93\82Ì\83G\83\93\83g\83\8a \83|\83C\83\93\83g\82ð\92è\8b`\82µ\82Ü\82·\81B\r
+//\r
+#include <winscard.h>
+#include <stdio.h>\r
+#include "CasProxy.h"\r
+#include "W2L.h"\r
+#ifndef SCARD_AUTOALLOCATE
+  #define SCARD_AUTOALLOCATE (DWORD)(-1)  /**< see SCardFreeMemory() */
+#endif\r
+
+//////////////////////////////////////////////////////////////////////\r
+// WinSCard\83t\83b\83N\r
+//////////////////////////////////////////////////////////////////////\r
+LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)\r
+{\r
+       // \83v\83\8d\83L\83V\83C\83\93\83X\83^\83\93\83X\90\90¬\r
+       CCasProxy *pCasProxy = new CCasProxy();\r
+
+       // \83T\81[\83o\82É\90Ú\91±\r
+       if(!pCasProxy->Connect()){\r
+               delete pCasProxy;\r
+               *phCard = NULL;\r
+               return SCARD_E_READER_UNAVAILABLE;\r
+               }
+\r
+       // \83n\83\93\83h\83\8b\82É\96\84\82ß\8d\9e\82Þ\r
+       *phCard = reinterpret_cast<SCARDHANDLE>(pCasProxy);\r
+       if(pdwActiveProtocol)*pdwActiveProtocol = SCARD_PROTOCOL_T1;\r
+\r
+       return SCARD_S_SUCCESS;\r
+}\r
+\r
+LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)\r
+{\r
+       // \83T\81[\83o\82©\82ç\90Ø\92f\r
+       CCasProxy *pCasProxy = reinterpret_cast<CCasProxy *>(hCard);\r
+       if(pCasProxy)delete pCasProxy;\r
+\r
+       return SCARD_S_SUCCESS;\r
+}\r
+\r
+LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)\r
+{
+       return SCARD_S_SUCCESS;\r
+}\r
+\r
+LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)\r
+{\r
+       return SCARD_S_SUCCESS;\r
+}\r
+\r
+LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)\r
+{\r
+       const char szReaderName[] = "BonCasLink Proxy Card Reader\0";\r
+\r
+       if(pcchReaders){\r
+               if((*pcchReaders == SCARD_AUTOALLOCATE) && mszReaders){\r
+                       *((LPCSTR *)mszReaders) = szReaderName;         \r
+                       return SCARD_S_SUCCESS;\r
+                       }\r
+               else{\r
+                       *pcchReaders = sizeof(szReaderName);\r
+                       }\r
+               }\r
+\r
+       if(mszReaders) memcpy(mszReaders, szReaderName, sizeof(szReaderName));\r
+\r
+       return SCARD_S_SUCCESS;\r
+}\r
+\r
+LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)\r
+{\r
+       // \83T\81[\83o\82É\83\8a\83N\83G\83X\83g\91\97\8eó\90M\r
+       CCasProxy *pCasProxy = reinterpret_cast<CCasProxy *>(hCard);\r
+       if(!pCasProxy)return SCARD_E_READER_UNAVAILABLE;\r
+\r
+       DWORD dwRecvLen = pCasProxy->TransmitCommand(pbSendBuffer, cbSendLength, pbRecvBuffer);\r
+       if(pcbRecvLength)*pcbRecvLength = dwRecvLen;\r
+\r
+       return (dwRecvLen)? SCARD_S_SUCCESS : SCARD_E_TIMEOUT;\r
+}\r
+\r
+LONG SCardReleaseContext(SCARDCONTEXT hContext)\r
+{\r
+       return SCARD_S_SUCCESS;\r
+}\r
+
diff --git a/dist/trunk/b25-remote/b25-server.cpp b/dist/trunk/b25-remote/b25-server.cpp
new file mode 100755 (executable)
index 0000000..674af68
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include "CasServer.h"
+
+CCasServer m_CasServer(NULL);
+int m_dwServerPort = 6900UL;
+
+int main() {
+       if(!m_CasServer.OpenServer(m_dwServerPort)){\r
+               printf("サーバの起動に失敗しました。\nTCPポートまたはカードリーダをオープンできません。\n");\r
+               return TRUE;\r
+       }
+       getchar();
+}
+
diff --git a/dist/trunk/diff b/dist/trunk/diff
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/dist/trunk/install.sh b/dist/trunk/install.sh
new file mode 100755 (executable)
index 0000000..028100b
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+SELF_DIR=`dirname $0`
+cd ${SELF_DIR}
+cd rec10
+bash install.sh
+cd ../
+mv Makefile.base Makefile
diff --git a/dist/trunk/readme.txt b/dist/trunk/readme.txt
new file mode 100755 (executable)
index 0000000..8087507
--- /dev/null
@@ -0,0 +1,210 @@
+###########################################
+#     Rec10 -Ts Recording system-         #
+#                          Ver.0.9.9.2    #
+# 2011/03/23         Yukikaze & long.inus #
+#  Copyright (C) 2009-2011 Yukikaze      #
+###########################################
+
+本ソフトはpythonおよびperlによって書かれた録画ツールです。
+ライセンスは LGPL v3に準拠します(license.txt参照)
+
+[必要コマンド]
+python(2.6,2.7にて動作確認)
+wine
+mencoder
+ffmpeg
+x264
+mp4box
+MySQL
+MySQLdb(MySQL-pythonなどの名前)
+mkvmerge(mkv使用時)
+java(jre1.6で動作を確認)
+
+[必要環境:Webインターフェース部分]
+perl
+一部のperlモジュール(rectool.pl,rec10webg2)
+
+[必要環境:外部ツール]
+jTsSplitter(included)
+BonTsDemux(included)
+epgdump(included)
+b25(not included)
+recpt1(recfriioでもいいはずです)(not included)
+MySQLdb
+
+事前準備:
+ネットの情報を参考にpt1ドライバーを無効化する
+pt1などのドライバーをインストールした上(chardev版)で、recpt1などのソフトを導入、
+b25をインストールしておいてください。
+*注意
+11年10月01日からのBS新チャンネル対応のためには、10/02現在ではrecpt1にパッチを当てる必要があります。
+rec10同梱版のepgrecはts解析によってチャンネルデータを得るように改変してあるので
+変更は不要です。
+
+1:install.shを実行
+2:表示にしたがって設定の変更(チャンネルなど)
+3:make
+4:su
+5:make install
+6:rec10を実行するユーザーで/usr/local/share/rec10を実行
+7:cronに書き加える
+8:rectool.plをインストール(Makefile.PLの実行 rectool.plの配置)
+
+付け足し
+
+7.cronの設定
+
+最後にrec10d.pyをcronで五分おきに実行するようにしてください
+crontab -e を実行するとcronを編集できるようになるので
+*/5 * * * * python /usr/local/bin/rec10
+のように書いてください(5扮ごとに実行)
+
+ログは/var/log/rec10に移動しました。
+
+8.rectoolのインストール
+Makefile.PLを実行します。
+実行した後にrectool.plをhttpの公開ディレクトリ(wwwフォルダなど)に置いてください。
+
+ちなみに
+エンコードの設定を変えたい場合はts2x264を参照してください
+
+
+チャンネルの設定を変えた場合はを編集した後に
+chdata.pyを実行してください(python chdata.py)
+その後番組表が更新されます
+
+バグだらけのコードですが、改善点などを指摘していただけるとうれしいです。
+yukikaze.jp@gmail.com
+
+
+動作確認のとれたディストリ
+
+11/03/10 SVN Centos 5.5 (yukikaze)
+11/03/10 0.9.9.1+a ArchLinux (yukikaze)
+11/02/20 0.9.9.1+a Debian 6.0
+11/02/XX 0.9.9 Ubuntu 10.10
+10/12/XX 0.9.8 Centos 5.5 (yukikaze)
+10/XX/XX 0.9.8 Fedora13 (long.inus)
+
+
+[History]
+11/XX/XX 0.9.10
+add Bluray compatible option("B")
+ステレオ音声時のBonTsDemux仕様オプション追加("b")
+lameの実行パスチェックを実装
+mencoderのコマンドラインを最新版対応へ
+ffmpegのオプション追加
+epggenreを追加
+keywordの重複チェックをより賢く
+logoのインポートに対応
+ArchLinuxサポートのための細かな変更
+新BSチャンネル対応
+
+11/02/02 0.9.9
+BonTsDemuxを最新版へ(nogui化によりXvfbが不要)
+一部CSチャンネルの追加
+epg_chを変更(ontvの削除)
+チャンネルスキャン機能を実装
+キーワード予約の自動実行オプション追加(in_auto_jbkにauto,optの追加)
+番組初頭の解像度変更に対応
+キーワード予約自動実行オプションの重複チェック実装
+延長対応機能の修正
+移動後のオプション引き継ぎに対応
+
+10/10/09 0.9.8 release
+インターレース保持エンコードに対応
+色空間を修正
+放送大学のマルチチャンネルに仮対応
+verboseモードの実装
+ログレベルの実装
+画面サイズが取得できなかったときの処理を追加
+python2.5/2.7に対応
+音声の自動復帰を修正
+
+10/07/10 0.9.7 release
+ヒストリーチャンネルのタイトルを修正
+ffmpeg使用時にscale拡大をするように修正
+一時ファイル削除機能の修正
+sarの変更を実装
+最新版のCaption2Assに対応
+
+10/05/29 0.9.6 release
+バグ修正
+ログシステムの修正
+
+0.9.5(内部リリース)
+b25自動削除機能の改善
+自動仕分け機能のアップデート
+Caption2Assやaac取り出しがうまくいかないときの自動復帰処理の実装
+バグ修正
+
+10/04/02 0.9.4 release
+バグ修正
+インストーラーの大幅な改善
+ログシステムの変更
+エンコードの変更
+チャンネル変更に対応(CS)
+
+10/03/20 0.9.3 release(internal)
+lots of bug fixes.
+change DB.
+implement updating function(from 0.9.1 or 0.9.2)
+10/03/06 0.9.2 release(internal)
+few bug fix.(!!! amazing i think)
+implement new encoding system.
+use x264cli and mencoder throwgh fifo.
+implement final production changing system(you can choose mkv and mp4 now.)
+
+10/02/21 0.9.1 release
+Lots of bug fixes.
+change video filter.
+change encode option.
+implement installer.
+
+09/12/07 0.9.0 release
+change config path.(config.ini to rec10.conf)
+add Makefile
+change large number of var name.
+support b25_remote(thanks long.inus)
+support auto copy function.
+change video filter.
+change encode option.
+fix a lot of bugs.
+finish to support iEPG(iRec10EPG).
+
+09/10/27 0.8.0 relaase
+Lots of bug fixes.
+Use mkvmerge to mux avi to mkv.
+Many changes.
+
+09/08/22 0.6.0 release
+Lots of bug fixes.
+Implement db using MySQL.
+Change Ts splitting soft from Tssplitter to tssplitter_lite(included.)
+
+09/08/01 0.5.0 release
+バグフィックス
+検索録画のパターンマッチングアルゴリズムの変更(推測的な検索ができるようになった)
+rectool.plを同梱するようにした。
+周辺ソフトのうちライセンスの問題がないものを同梱するようにした。
+
+09/07/01 0.4.1 release
+lots of bug fixes
+add some cs-ch.
+release pl src.
+09/05/24 0.3.1 release
+fix
+チャンネルの増加
+エンコードオプションを実際に使えるようにした。
+1passモード実装
+niceコマンドをより広範囲に適用するようにした。
+09/05/08 0.1.1 release
+fix
+2passエンコードのログファイルがかぶるのを訂正
+一部チャンネル指定が間違っていたのを訂正
+その他多くのバグの訂正
+09/05/05 0.0.1b release
+fix
+replace tab to 4 spaces(it caused errors)
+add some cs-e2 channels
+09/05/04 0.0.1a release
diff --git a/dist/trunk/rec10/Makefile.base b/dist/trunk/rec10/Makefile.base
new file mode 100755 (executable)
index 0000000..0da6338
--- /dev/null
@@ -0,0 +1,33 @@
+PREFIX = /usr/local/share
+MAJOR = 0
+MINOR = 9
+REVISION = 10
+VER = $(MAJOR).$(MINOR).$(REVISION)
+
+DEST = $(PREFIX)/rec10
+
+install:
+       if ! [ -d $(PREFIX)/rec10 ]; then mkdir -p $(PREFIX)/rec10 ;fi
+       cp ./*.py $(DEST)/
+       /bin/echo -e "#!/bin/bash" > ./rec10
+       /bin/echo -e "if type -P python2.6 > /dev/null\nthen\nexport LANG=\"ja_JP.UTF-8\" && python2.6 ${DEST}/rec10d.py" >> ./rec10
+       /bin/echo -e "elif type -P python26 > /dev/null\nthen\nexport LANG=\"ja_JP.UTF-8\" && python26 ${DEST}/rec10d.py\n" >> ./rec10
+       /bin/echo -e "elif type -P python2.5 > /dev/null\nthen\nexport LANG=\"ja_JP.UTF-8\" && python2.5 ${DEST}/rec10d.py\n" >> ./rec10
+       /bin/echo -e "elif type -P python25 > /dev/null\nthen\nexport LANG=\"ja_JP.UTF-8\" && python25 ${DEST}/rec10d.py" >> ./rec10
+       /bin/echo -e "elif type -P python2.7 > /dev/null\nthen\nexport LANG=\"ja_JP.UTF-8\" && python2.7 ${DEST}/rec10d.py" >> ./rec10
+       /bin/echo -e "elif type -P python27 > /dev/null\nthen\nexport LANG=\"ja_JP.UTF-8\" && python27 ${DEST}/rec10d.py" >> ./rec10
+       /bin/echo -e "else export LANG=\"ja_JP.UTF-8\" && python ${DEST}/rec10d.py" >> ./rec10
+       /bin/echo -e "fi\n" >> ./rec10
+       install -m755 ./rec10 $(DEST)/
+       if ! [ -f /usr/local/bin/rec10 ]; then ln $(DEST)/rec10 /usr/local/bin;fi
+       chmod 755 /usr/local/bin/rec10
+       if [ -f /etc/rec10.conf ]; then rm /etc/rec10.conf;fi
+       cp ./rec10.conf /etc/rec10.conf
+       if ! [ -d /tmp/rec10 ]; then mkdir -p /tmp/rec10 ;fi
+       chmod 777 /tmp/rec10
+       if ! [ -d /var/log/rec10 ]; then echo "" > /var/log/rec10 ;fi
+       chmod 777 /var/log/rec10
+uninstall:
+       rm -rf $(DEST)
+       rm -rf /tmp/rec10
+       rm -f /usr/local/bin/rec10
diff --git a/dist/trunk/rec10/auto_move.py b/dist/trunk/rec10/auto_move.py
new file mode 100755 (executable)
index 0000000..288e49d
--- /dev/null
@@ -0,0 +1,150 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+\r
+import glob\r
+import os\r
+import os.path\r
+import re\r
+import time\r
+import shutil\r
+import traceback\r
+import sys\r
+\r
+import recdblist\r
+import guess\r
+def getTitle(title):\r
+    rT=re.compile("(.+)_(\d+)\Z")\r
+    tT=rT.match(title)\r
+    rT2=re.compile("(.+)_(.+)_(\d*)\Z")#_(aichi)_2010-02-06T01:59:00.mkv\r
+    tT2=rT2.match(title)\r
+    rT3=re.compile("(.+)_(.+)_\d+-\d+-\d+T\d+:\d+:\d+\Z")#_(aichi)_2010-02-06T01:59:00.mkv\r
+    tT3=rT3.match(title)\r
+    rT4=re.compile("(.+)_(.+)_\d+-\d+-\d+T\d+-\d+-\d+\Z")#_(aichi)_2010-02-06T01-59-00.mkv\r
+    tT4=rT4.match(title)\r
+    rT5=re.compile("(.+)_(.+)_(.+)\Z")#_(aichi)_2010-02-06T01-59-00.mkv\r
+    tT5=rT5.match(title)\r
+    ntitle=title\r
+    if tT :\r
+        ntitle=tT.group(1)\r
+    elif tT2:\r
+        ntitle=tT2.group(1)\r
+    elif tT3:\r
+        ntitle=tT3.group(1)\r
+    elif tT4:\r
+        ntitle=tT4.group(1)\r
+    elif tT5:\r
+        ntitle=tT5.group(1)\r
+    return ntitle\r
+def searchFile(temppath,recpath,ext):\r
+    """\r
+    録画一時フォルダ内ファイルを検索\r
+    """\r
+    avilist = glob.glob(temppath + "/*"+ext)\r
+    ret=[]\r
+    for avif in avilist:\r
+        ##b25f is title.ts.b25  avi is title.avi\r
+        dir = os.path.split(avif)[0]\r
+        title = os.path.split(avif)[1]\r
+        title = title.replace(ext, "")\r
+        avipath = os.path.join(dir, title + ext)\r
+        if os.path.exists(avipath):\r
+            dtime = time.time()-os.path.getmtime(avipath)\r
+            dtime = int(dtime)\r
+            if dtime > 300:\r
+                if veryfySize(avipath):\r
+                    ret.append(title)\r
+    return ret\r
+def getMoveDestpath(title,temppath,recpath,ext):\r
+    dstpath=os.path.join(recpath,title+ext)\r
+    srcpath=os.path.join(temppath,title+ext)\r
+    if os.path.exists(dstpath):\r
+        if not os.path.getsize(dstpath) == os.path.getsize(srcpath):\r
+            gmtime=time.gmtime(os.path.getmtime(srcpath))\r
+            iff=""\r
+            try:\r
+                iff=u"("+configreader.getConfEnv("iff")+u")_"\r
+                if iff==u"()_":\r
+                    iff = u""\r
+            except:\r
+                iff=""\r
+            title=title+u"_"+iff+time.strftime("%Y-%m-%dT%H-%M-%S",gmtime)\r
+        else:\r
+            recdblist.printutf8(u"同サイズのファイルが存在します")\r
+\r
+    return title\r
+def getDelpath(temppath,title,addfp=1):\r
+    delpath=[os.path.join(temppath,title+".ts")]\r
+    delpath.append(os.path.join(temppath,title+".avi"))\r
+    if addfp==1:\r
+        delpath.append(os.path.join(temppath,title+".mp4"))\r
+        delpath.append(os.path.join(temppath,title+".mkv"))\r
+    delpath.append(os.path.join(temppath,title+".m2v"))\r
+    delpath.append(os.path.join(temppath,title+".120.avi"))\r
+    delpath.append(os.path.join(temppath,title+".timecode.txt"))\r
+    delpath.append(os.path.join(temppath,title+".aac"))\r
+    delpath.append(os.path.join(temppath,title+".ts.b25"))\r
+    delpath.append(os.path.join(temppath,title+".ts.tsmix"))\r
+    delpath.append(os.path.join(temppath,title+".ts.log"))\r
+    delpath.append(os.path.join(temppath,title+".sa.avi"))\r
+    delpath.append(os.path.join(temppath,title+".sa.avi.log"))\r
+    delpath.append(os.path.join(temppath,title+".log"))\r
+    delpath.append(os.path.join(temppath,title+".log.zip"))\r
+    return delpath\r
+def veryfySize(path):\r
+    #vsize=[297,497,596,1196]#SD 30m 1h 1.5h 2h\r
+    vsize=[245,275,295,591,830]\r
+    vsize=vsize+[325,449,560,590,602,690,805,860,1014,1138,1237]\r
+    vsize=vsize+[261,535,540,616,740]#HD 30m 1h\r
+    #vsize=vsize+[381,895,447]\r
+    ret = 0\r
+    for size in vsize:\r
+        if os.path.getsize(path)>(size-10)*1024*1024 and os.path.getsize(path)<(size+10)*1024*1024:\r
+            ret=1\r
+    if os.path.getsize(path)>270*1024*1024:\r
+        ret=1\r
+    return ret\r
+def execMove(title,temppath,recpath,ext,autodel):\r
+    srcpath=os.path.join(temppath,title+ext)\r
+    sf=guess.searchFolder(title, recpath)\r
+    if sf!="":\r
+        destpath=os.path.join(sf,getMoveDestpath(title, temppath, sf, ext)+ext)\r
+        if os.path.exists(destpath):\r
+            if os.path.getsize(destpath) == os.path.getsize(srcpath):\r
+                recdblist.printutf8(u"同名同サイズのファイルが存在します。")\r
+                if autodel==1:\r
+                    recdblist.printutf8(u"関連ファイルを削除します。")\r
+                    delpath=getDelpath(temppath, title)\r
+                    for dp in delpath:\r
+                        try:\r
+                            os.remove(dp)\r
+                            ""\r
+                        except:\r
+                            ""\r
+        else:\r
+            recdblist.printutf8("moving now..")\r
+            recdblist.printutf8(srcpath+" : "+destpath)\r
+            print srcpath\r
+            shutil.copy(srcpath, destpath)\r
+            #shutil.copy(srcpath, destpath)\r
+            if autodel==1:\r
+                delpath=getDelpath(temppath, title)\r
+                for dp in delpath:\r
+                    try:\r
+                        os.remove(dp)\r
+                        ""\r
+                    except:\r
+                        ""\r
+def execDelete(title,temppath):\r
+    delpath=getDelpath(temppath, title,0)\r
+    recdblist.printutf8(title+u" 関連の一時ファイルを削除します")\r
+    for dp in delpath:\r
+        try:\r
+            if os.path.exists(dp):\r
+                recdblist.printutf8(dp)\r
+                os.remove(dp)\r
+        except Exception, inst:\r
+            print type(inst)\r
+            print str(inst)\r
+            print traceback.print_exc(file=sys.stdout)\r
diff --git a/dist/trunk/rec10/auto_process.py b/dist/trunk/rec10/auto_process.py
new file mode 100755 (executable)
index 0000000..175df6b
--- /dev/null
@@ -0,0 +1,285 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import os\r
+import glob\r
+import time\r
+import datetime\r
+import commands\r
+import re\r
+import os.path\r
+\r
+import chdb\r
+import status\r
+import configreader\r
+import recdblist\r
+import rec10d\r
+import tv2mp4\r
+import epgdb\r
+def updateToMP4(path):\r
+    """\r
+    !現在未使用!\r
+    録画一時フォルダ内mp4ファイルを検索\r
+    """\r
+    avilist = glob.glob(path + "/*.avi")\r
+    mkvlist = glob.glob(path+"/*.mkv")\r
+    avilist=avilist+mkvlist\r
+    for avif in avilist:\r
+        if avif.rfind("sa.avi")==-1:\r
+            dir = os.path.split(avif)[0]\r
+            title = os.path.split(avif)[1]\r
+            title = title.replace(".avi", "")\r
+            title = title.replace(".mkv", "")\r
+            avipath = os.path.join(dir, title + ".avi")\r
+            mkvpath = os.path.join(dir, title + ".mkv")\r
+            mp4path = os.path.join(dir, title + ".mp4")\r
+            if not os.path.exists(mp4path):\r
+                if os.path.exists(avipath):\r
+                    avidtime = int(time.time()-os.path.getmtime(avipath))\r
+                    if avidtime>300:\r
+                        if os.path.exists(mkvpath):\r
+                            mkvdtime = int(time.time()-os.path.getmtime(mkvpath))\r
+                            if mkvdtime>300:\r
+                                recdblist.printutf8(mkvpath+":"+mp4path)\r
+                                tv2mp4.mkv2mp4(mkvpath,mp4path)\r
+                            else:\r
+                                recdblist.printutf8(avipath+":"+mp4path)\r
+                                tv2mp4.avi2mp4(avipath,mp4path)\r
+                        else:\r
+                            recdblist.printutf8(avipath+":"+mp4path)\r
+                            tv2mp4.avi2mp4(avipath,mp4path)\r
+                else:\r
+                    if not os.path.exists(avipath):\r
+                        if os.path.exists(mkvpath):\r
+                            mkvdtime = int(time.time()-os.path.getmtime(mkvpath))\r
+                            if mkvdtime>300:\r
+                                recdblist.printutf8(mkvpath+":"+mp4path)\r
+                                tv2mp4.mkv2mp4(mkvpath,mp4path)\r
+def autoCheck(path):\r
+    avilist = glob.glob(path + "/*.avi")\r
+    mkvlist = glob.glob(path+"/*.mkv")\r
+    mp4list = glob.glob(path+"/*.mp4")\r
+    tslist = glob.glob(path+"/*.ts")\r
+    b25list = glob.glob(path+"/*.ts.b25")\r
+    filelist=avilist+mkvlist+tslist+b25list+mp4list\r
+    add=[]\r
+    tbtime=datetime.datetime.now()+datetime.timedelta(seconds=60)\r
+    tbtime2=datetime.datetime.now()+datetime.timedelta(seconds=1200)\r
+    for fn in filelist:\r
+        if os.path.exists(fn):\r
+            if fn.rfind("sa.avi")==-1 and fn.rfind(".120.avi")==-1 and os.path.getsize(fn)>1*1000*1000:\r
+                dir = os.path.split(fn)[0]\r
+                file = os.path.split(fn)[1]\r
+                title = os.path.splitext(file)[0]\r
+                title = unicode(title,'utf-8')\r
+                ext = os.path.splitext(file)[1]\r
+                if ext == ".b25":\r
+                    title=title.replace(".ts","")\r
+                dbs=rec10d.rec10db.select_by_name_time_timeline(title,tbtime,tbtime2)\r
+                if len(dbs)==0:\r
+                    proc=checkProcess(dir, title)\r
+                    chtxtt=rec10d.rec10db.select_chtxt_by_title_timeline_log(title)\r
+                    nchtxt=""\r
+                    if chtxtt!=None:\r
+                        nchtxt=chtxtt\r
+                    if proc=="b25":\r
+                        add.append([recdblist.REC_AUTO_SUGGEST_DECODE,title,nchtxt])\r
+                    elif proc=="ts":\r
+                        add.append([recdblist.REC_AUTO_SUGGEST_ENCODE,title,nchtxt])\r
+                    elif proc =="264":\r
+                        add.append([recdblist.REC_AUTO_SUGGEST_AVI2FP,title,nchtxt])\r
+                    #elif proc =="mp4":\r
+                    #    add.append([recdblist.REC_AUTO_SUGGEST_AP2FP,title,nchtxt])\r
+        #print add\r
+    if len(add)>0:\r
+        rec10d.rec10db.new_auto_proc()\r
+        for a in add:\r
+            rec10d.rec10db.add_auto_proc(a[0],a[1],a[2])\r
+        time.sleep(1)\r
+"""\r
+    処理がどの段階まで言ったのかを調査し返す。\r
+    return\r
+    recording\r
+    b25\r
+    b25decoding\r
+    tssplitting\r
+    ts\r
+    encoding\r
+    avi\r
+    mp4making\r
+    mp4\r
+"""\r
+def checkProcess(path,title):\r
+    path1 = os.path.join(path,title+".mkv")\r
+    if os.path.exists(path1):\r
+        if int(time.time()-os.path.getmtime(path1))>300:\r
+            return "mkv"\r
+        else:\r
+            return "mkvmaking"\r
+    elif os.path.exists(os.path.join(path,title+".mp4")):\r
+        if int(time.time()-os.path.getmtime(os.path.join(path,title+".mp4")))>300:\r
+            return "mp4"\r
+        else:\r
+            return "mp4making"\r
+    elif os.path.exists(os.path.join(path,title+".264")):\r
+        if int(time.time()-os.path.getmtime(os.path.join(path,title+".264")))>300:\r
+            return "264"\r
+        else:\r
+            return "encoding"\r
+    elif os.path.exists(os.path.join(path,title+".ts.log")):\r
+        if int(time.time()-os.path.getmtime(os.path.join(path,title+".ts")))<300:\r
+            return "encoding"\r
+        else:\r
+            return "ts"\r
+    elif os.path.exists(os.path.join(path,title+".ts")):\r
+        if int(time.time()-os.path.getmtime(os.path.join(path,title+".ts")))>300:\r
+            return "ts"\r
+        else:\r
+            return "tssplitting"\r
+    elif os.path.exists(os.path.join(path,title+".sa.avi")):\r
+        if int(time.time()-os.path.getmtime(os.path.join(path,title+".sa.avi")))>300:\r
+            return "ts"\r
+        else:\r
+            return "tssplitting"\r
+    elif os.path.exists(os.path.join(path,title+".ts.b25")):\r
+        if int(time.time()-os.path.getmtime(os.path.join(path,title+".ts.b25")))>300:\r
+            return "b25"\r
+        else:\r
+            return "recording"\r
+def update_all_timeline_epg():\r
+    now=datetime.datetime.now()\r
+    et=now+datetime.timedelta(days=7)\r
+    update_timeline_epg(now.strftime("%Y-%m-%d %H:%M:%S"), et.strftime("%Y-%m-%d %H:%M:%S"))\r
+def update_timeline_epg(btime,etime):\r
+    update_timeline_epg_schedule(btime,etime)\r
+    update_timeline_dup(btime,etime)\r
+def update_timeline_epg_schedule(btime,etime):\r
+    dbl=rec10d.rec10db.select_bytime_all_timeline(btime, etime)\r
+    #print dbl\r
+    for db in dbl:\r
+        ret=[]\r
+        #[chtxtt, title, btime, etime,exp,longexp,category]\r
+        if db['type']==recdblist.REC_KEYWORD or db['type']==recdblist.REC_KEYWORD_EVERY_SOME_DAYS:\r
+            ret=epgdb.searchTime(db['title'], db['btime'], db['deltatime'], db['chtxt'])\r
+            if len(ret)>4 and len(ret[2])>18:\r
+                rec10d.rec10db.update_epg_timeline(db['type'], db['chtxt'], db['title'], db['btime'], ret[2],ret[3],ret[1],ret[4],ret[6])\r
+                if not (db['btime'] == ret[2] and  db['etime']==ret[3]):\r
+                    rec10d.rec10db.update_status_change_timeline(db['type'], db['chtxt'], db['title'], db['btime'], "1")\r
+                else:\r
+                    rec10d.rec10db.update_status_change_timeline(db['type'], db['chtxt'], db['title'], db['btime'], "0")\r
+            else:\r
+                rec10d.rec10db.update_status_change_timeline(db['type'], db['chtxt'], db['title'], db['btime'], "1")\r
+        elif db['type']==recdblist.REC_RESERVE or db['type']==recdblist.REC_FINAL_RESERVE :\r
+            ret=epgdb.searchTime(db['title'], db['btime'],"5", db['chtxt'])\r
+            if len(ret)>4 and len(ret[2])>18:\r
+                rec10d.rec10db.update_epg_timeline(db['type'], db['chtxt'], db['title'], db['btime'], ret[2],ret[3],ret[1],ret[4],ret[6])\r
+                if not (db['btime'] == ret[2] and  db['etime']==ret[3]):\r
+                    rec10d.rec10db.update_status_change_timeline(db['type'], db['chtxt'], db['title'], db['btime'], "1")\r
+                else:\r
+                    rec10d.rec10db.update_status_change_timeline(db['type'], db['chtxt'], db['title'], db['btime'], "0")\r
+            else:\r
+                rec10d.rec10db.update_status_change_timeline(db['type'], db['chtxt'], db['title'], db['btime'], "1")\r
+def update_timeline_dup(epgbtime,epgetime):\r
+    dbl=rec10d.rec10db.select_byepgtime_all_timeline(epgbtime, epgetime)\r
+    for db in dbl:\r
+        if db['type']==recdblist.REC_KEYWORD or db['type']==recdblist.REC_KEYWORD_EVERY_SOME_DAYS:\r
+            dbn=epgdb.countEpgSchedule(db['epgbtime'], db['epgetime'])\r
+            try:\r
+                bctypet=chdb.searchCHFromChtxt(db['chtxt'])['bctype']\r
+                if bctypet.find("cs") > -1 or bctypet.find("bs") > -1 :\r
+                    if dbn[1]>status.getRecordingMax()[1]:\r
+                        rec10d.rec10db.update_status_dup_timeline(db['type'], db['chtxt'], db['title'], db['btime'], "1")\r
+                    else:\r
+                        rec10d.rec10db.update_status_dup_timeline(db['type'], db['chtxt'], db['title'], db['btime'], "0")\r
+                else:\r
+                    if dbn[0]>status.getRecordingMax()[0]:\r
+                        rec10d.rec10db.update_status_dup_timeline(db['type'], db['chtxt'], db['title'], db['btime'], "1")\r
+                    else:\r
+                        rec10d.rec10db.update_status_dup_timeline(db['type'], db['chtxt'], db['title'], db['btime'], "0")\r
+            except:\r
+                ""\r
+def killDeadEncode(path):\r
+    rawlist = glob.glob(path + "/*.264")\r
+    for fn in rawlist:\r
+        if int(time.time()-os.path.getmtime(fn))>3000:\r
+            m2vpath=unicode(fn.replace(".264",".m2v"),'utf-8')\r
+            x264path=os.path.split(fn)[1]\r
+            folderpath=unicode(os.path.split(fn)[0],'utf-8')\r
+            x264path=re.sub("\\[","[",x264path)\r
+            x264path=re.sub("\[","\\\[",x264path)\r
+            x264path=re.sub("\\]","]",x264path)\r
+            x264path=re.sub("]","\\]",x264path)\r
+            tspath=unicode(x264path.replace(".264",".ts"),'utf-8')\r
+            m2vpath=unicode(x264path.replace(".264",".m2v"),'utf-8')\r
+            x264path=unicode(x264path,'utf-8')\r
+            os.environ['LANG']="ja_JP.UTF-8"\r
+            ktmp=[]\r
+            ktmp.append(u"ps auxww | grep \""+folderpath+"\" | grep \""+x264path+u"\" | egrep -v grep | egrep -v \"sh -c\" | grep x264 | awk '{print $2}'")\r
+            ktmp.append(u"ps auxww | grep \""+folderpath+"\" | grep \""+tspath+u"\" | egrep -v grep | egrep -v \"sh -c\" | grep mencoder | awk '{print $2}'")\r
+            ktmp.append(u"ps auxww | grep \""+folderpath+"\" | grep \""+m2vpath+u"\" | egrep -v grep | egrep -v \"sh -c\" | grep ffmpeg | awk '{print $2}'")\r
+            recdblist.printutf8(u"エンコード処理異常終了タスク終了")\r
+            for istr in ktmp:\r
+                recdblist.printutf8(istr)\r
+                ktmt=commands.getoutput(istr.encode('utf-8'))\r
+                #print ktmt\r
+                #print len(ktmt)\r
+                if len(ktmt)>0:\r
+                    #print ktmt\r
+                    if len(ktmt[0])>0:\r
+                        ktmt=ktmt[0]\r
+                    #print ktmt\r
+                try:\r
+                    if int(ktmt)>0:\r
+                        ktmp=u"kill -9 `"+istr+u"`"\r
+                        recdblist.printutf8(ktmp)\r
+                        #print ktmp\r
+                        os.system(ktmp.encode('utf-8'))\r
+                except:\r
+                    ""\r
+def deleteTmpFile(path,title,ext):\r
+    level= 0##0:b25 1:ts(del tsmix and ts.b25) 5:x264(del 2 and so on) 10:mp4/mkv\r
+    smsize= 0\r
+    if re.search(".ts",ext):\r
+        level= 1\r
+        smsize = 100*1000*1000\r
+    elif re.search(".264",ext):\r
+        level= 5\r
+        smsize = 10*1000*1000\r
+    elif re.search(".mp4",ext):\r
+        level = 10\r
+        smsize = 10*1000*1000\r
+    elif re.search(".mkv",ext):\r
+        level = 15\r
+        smsize = 10*1000*1000\r
+    dp=[]\r
+    if level > 0 :\r
+        if os.path.exists(os.path.join(path,title+".ts")) and os.path.exists(os.path.join(path,title+".ts.b25")):\r
+            if os.path.getsize(os.path.join(path,title+".ts"))*12>os.path.getsize(os.path.join(path,title+".ts.b25")):\r
+                dp.append(os.path.join(path,title+".ts.b25"))\r
+            elif os.path.getsize(os.path.join(path,title+".ts"))>200*1000*1000:\r
+                dp.append(os.path.join(path,title+".ts.b25"))\r
+    if level > 4 :\r
+        if configreader.getConfEnv("remove_ts")=="1":\r
+            dp.append(os.path.join(path,title+".ts"))\r
+    if level > 9 :\r
+        dp.append(os.path.join(path,title+".avi"))\r
+        dp.append(os.path.join(path,title+".264"))\r
+        dp.append(os.path.join(path,title+".120.avi"))\r
+        dp.append(os.path.join(path,title+".noodml.avi"))\r
+        dp.append(os.path.join(path,title+".aac"))\r
+        dp.append(os.path.join(path,title+".m2v"))\r
+        dp.append(os.path.join(path,title+"_1.aac"))\r
+        dp.append(os.path.join(path,title+"_2.aac"))\r
+        dp.append(os.path.join(path,title+"_1.mp3"))\r
+        dp.append(os.path.join(path,title+"_2.mp3"))\r
+        dp.append(os.path.join(path,title+".srt"))\r
+    if level > 14 :\r
+        dp.append(os.path.join(path,title+".mp4"))\r
+    if os.path.exists(os.path.join(path,title+ext)):\r
+        if os.path.getsize(os.path.join(path,title+ext))>smsize:\r
+            for ip in dp:\r
+                try:\r
+                    os.remove(ip)\r
+                except:\r
+                    ""\r
diff --git a/dist/trunk/rec10/auto_rec.py b/dist/trunk/rec10/auto_rec.py
new file mode 100755 (executable)
index 0000000..5e4b8d5
--- /dev/null
@@ -0,0 +1,85 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+import n_gram
+import rec10d
+def getDBKey(key,chtxt):
+    return rec10d.rec10db.select_by_key_in_auto_bayes_key(key, chtxt)
+def changeDBEpg(chtxt,beforenum,newnum):
+    rec10d.rec10db.change_ratio_all_reduce_in_auto_bayes_key(chtxt, beforenum, newnum)
+def changeDBNum(chtxt,recaddnum,alladdnum):
+    """
+    add num.(Not change)
+    """
+    rec10d.rec10db.add_num_in_auto_bayes_key(chtxt, recaddnum,alladdnum)
+def changeDBRatioRec(key,chtxt,beforenum,addnum):
+    rec10d.rec10db.change_ratio_rec_in_auto_bayes_key(key, chtxt, beforenum, addnum)
+def changeDBRatioMultiRec(chtxt,beforenum,list):
+    rec10d.rec10db.change_multi_ratio_rec_in_auto_bayes_key(chtxt, beforenum, list)
+def changeDBReduceRatioRec(chtxt,beforenum,addnum):
+    rec10d.rec10db.change_ratio_rec_reduce_in_auto_bayes_key(chtxt, beforenum, addnum)
+def changeDBRatioAll(key,chtxt,beforenum,addnum):
+    rec10d.rec10db.change_ratio_all_in_auto_bayes_key(key, chtxt, beforenum, addnum)
+def changeDBRatioMultiAll(chtxt,beforenum,list):
+    rec10d.rec10db.change_multi_ratio_all_in_auto_bayes_key(chtxt,beforenum, list)
+def getDBNum(chtxt):
+    ret=getDBKey("NUM", chtxt)
+    if len(ret)<3:
+        rec10d.rec10db.add_in_auto_bayes_key("NUM", chtxt, 1,1)
+        ret=getDBKey("NUM", chtxt)
+    return ret
+def updateRecall(chtxt,titles,descs,newnum):
+    """
+    update recall
+    """
+    titles=" "+titles+" "
+    descs=" "+descs+" "
+    str1=titles*2+descs+titles*2
+    noun=n_gram.getNounQuadGram(str1)
+    bnum=getDBNum(chtxt)[3]
+    if bnum<1:
+        bnum=100
+    changeDBRatioMultiAll(chtxt, bnum,noun)
+    changeDBEpg(chtxt, bnum, newnum)
+    changeDBNum(chtxt, 0, newnum)
+def addKey(chtxt,title,desc):
+    title=u" "+title+u" "
+    desc=u" "+desc+u" "
+    str1=title*2+desc+title*2##タイトルは重視したいので幾度か足す。
+    noun=n_gram.getNounQuadGram(str1)#nounは辞書のキーに文字を、中身に出現回数を書いたもの。
+    bnum=getDBNum(chtxt)[2]
+    if bnum<1:
+        bnum=1
+    changeDBRatioMultiRec(chtxt, bnum, noun)
+    changeDBNum(chtxt,1,0)
+    changeDBReduceRatioRec(chtxt, bnum,1)
+def calcKey(chtxt,title,desc):
+    """
+
+    """
+    title=u" "+title+u" "
+    desc=u" "+desc+u" "
+    str1=title*2+desc+title*2##タイトルは重視したいので幾度か足す。
+    noun=n_gram.getNounQuadGram(str1)#nounは辞書のキーに文字を、中身に出現回数を書いたもの。
+    tnum=1
+    nump=0
+    for key,num in noun.items():
+        pp=getDBKey(key,chtxt)
+        pp2=getDBKey(key,"ALL")
+        if len(pp)>3:
+            tarec=0
+            taall=0
+            if len(pp2)>3:
+                tarec=pp2[2]
+                taall=pp2[3]
+            trec=pp[2]
+            tall=pp[3]
+            
+            tnum=tnum+1
+            p=(1000*trec+5)/(1000*tall+5)
+            p=p*p*100
+            p2=(1000*tarec+5)/(1000*taall+5)
+            p2=p2*100
+            nump=nump+p+p2
+    return int(nump/tnum)
diff --git a/dist/trunk/rec10/auto_test.py b/dist/trunk/rec10/auto_test.py
new file mode 100755 (executable)
index 0000000..0a81861
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import os\r
+import os.path\r
+import time\r
+import optparse\r
+import sys\r
+import datetime\r
+\r
+import configreader\r
+import chdb\r
+import tv2mp4\r
+import tv2ts\r
+def testAllCHEncode(option,stime):\r
+    chl=chdb.getAllCH()\r
+    print chl\r
+    path= configreader.getConfPath("test")\r
+    tpath=os.path.join(path, "encode_test")\r
+    if not os.path.exists(tpath):\r
+        os.mkdir(tpath)\r
+    dnowt=datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")+"_"+option+""\r
+    tpatht=os.path.join(tpath,dnowt)\r
+    if not os.path.exists(tpatht):\r
+        os.mkdir(tpatht)\r
+    if len(chl)>0:\r
+        for t in chl:\r
+            print t\r
+            pathname=os.path.join(tpatht,t['chtxt'])\r
+            print pathname\r
+            tv2ts.tv2ts(pathname+".ts",t['ch'],t['csch'], stime)\r
+            tv2mp4.ts2mp4(pathname+".ts", pathname+".mp4", option)\r
+            time.sleep(2)\r
+if __name__ == "__main__":\r
+    usage="usage: "\r
+    version="%prog 0.9.7"\r
+    parser=optparse.OptionParser(usage=usage,version=version)\r
+    parser.add_option("-e","--Encode",action="store",type="string",dest="encode_option",default="",metavar="TITLE",help="encode test(option)")\r
+    (opts,args)=parser.parse_args(sys.argv)\r
+    if opts.encode_option != "":##-sの場合\r
+        print "test_all_ch_encode"\r
+        testAllCHEncode(opts.encode_option, "10")\r
diff --git a/dist/trunk/rec10/chdata.py b/dist/trunk/rec10/chdata.py
new file mode 100755 (executable)
index 0000000..861719b
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import os.path\r
+import configreader\r
+import xml.dom.minidom\r
+import scan_ch\r
+import datetime\r
+\r
+import rec10d\r
+\r
+path = str(os.path.dirname(os.path.abspath(__file__))) + "/"\r
+\r
+def chAdd(bctype, chtxt, ch, csch):#すべて文字列\r
+    tnow=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")\r
+    rec10d.rec10db.add_epg_ch(bctype,chtxt, ch, csch, u"2010-01-01 00:00:00",u"2010-01-01 00:00:00",tnow)\r
+def addCHlist(cl):\r
+    if len(cl)>0:\r
+        for c in cl:\r
+            chAdd(c[0],c[1],c[2],c[3])\r
+def getChList(xmlpath):\r
+    dom=xml.dom.minidom.parse(file(xmlpath))\r
+    chlist=[]\r
+    for ch in dom.getElementsByTagName('channel'):\r
+        bctype=ch.getAttribute("bctype")\r
+        chd=ch.getAttribute("ch")\r
+        csch=ch.getAttribute("csch")\r
+        chtxt=ch.getAttribute("chtxt")\r
+        ontv=ch.getAttribute("ontvcode")\r
+        chlist.append([bctype,ontv,chtxt,chd,csch])\r
+    return chlist\r
+def deleteChListALL():\r
+    rec10d.rec10db.new_epg_ch()\r
+if __name__ == "__main__":\r
+    deleteChListALL()\r
+    scan_ch.searchCh()\r
diff --git a/dist/trunk/rec10/chdb.py b/dist/trunk/rec10/chdb.py
new file mode 100755 (executable)
index 0000000..b53c220
--- /dev/null
@@ -0,0 +1,101 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+    # モジュール属性 argv を取得するため\r
+import rec10d\r
+\r
+def searchCHFromChtxt(chtxtin):\r
+    chtxtt=chtxtin.replace("_0","_%")\r
+    ret = []\r
+    for datum in rec10d.rec10db.select_by_chtxt_epg_ch(chtxtt):\r
+        rett = {'bctype':datum[0], 'chtxt':datum[1], 'ch':datum[2], 'csch':datum[3], 'update':datum[4], 'chname':datum[5], 'visible':datum[7]}\r
+        ret.append(rett)\r
+    if len(ret) == 0:\r
+        ret.append(None)\r
+    return ret[0]\r
+def searchCHFromBctype(bctypein):\r
+    ret = []\r
+    for datum in rec10d.rec10db.select_by_bctype_epg_ch(bctypein):\r
+        rett = {'bctype':datum[0], 'chtxt':datum[1], 'ch':datum[2], 'csch':datum[3], 'update':datum[4], 'chname':datum[5], 'visible':datum[7]}\r
+        ret.append(rett)\r
+    if len(ret) == 0:\r
+        ret.append(None)\r
+    return ret[0]\r
+def searchCHFromCh(chin):\r
+    ret = []\r
+    for datum in rec10d.rec10db.select_by_ch_epg_ch(chin):\r
+        rett = {'bctype':datum[0], 'chtxt':datum[1], 'ch':datum[2], 'csch':datum[3], 'update':datum[4], 'chname':datum[5], 'visible':datum[7]}\r
+        ret.append(rett)\r
+    if len(ret) == 0:\r
+        ret.append(None)\r
+    return ret[0]\r
+def searchCHFromCsch(cschin):\r
+    ret = []\r
+    for datum in rec10d.rec10db.select_by_csch_epg_ch(cschin):\r
+        rett = {'bctype':datum[0], 'chtxt':datum[1], 'ch':datum[2], 'csch':datum[3], 'update':datum[4], 'chname':datum[5], 'visible':datum[7]}\r
+        ret.append(rett)\r
+    if len(ret) == 0:\r
+        ret.append(None)\r
+    return ret[0]\r
+def searchAllCHFromCh(chin):\r
+    ret = []\r
+    for datum in rec10d.rec10db.select_by_ch_epg_ch(chin):\r
+        rett = {'bctype':datum[0], 'chtxt':datum[1], 'ch':datum[2], 'csch':datum[3], 'update':datum[4], 'chname':datum[5], 'visible':datum[7]}\r
+        ret.append(rett)\r
+    if len(ret) == 0:\r
+        ret.append(None)\r
+    return ret\r
+def getAllCH():\r
+    ret = []\r
+    for datum in rec10d.rec10db.select_all_epg_ch():\r
+        rett = {'bctype':datum[0], 'chtxt':datum[1], 'ch':datum[2], 'csch':datum[3], 'update':datum[4], 'chname':datum[5], 'visible':datum[7]}\r
+        ret.append(rett)\r
+    if len(ret) == 0:\r
+        ret.append(None)\r
+    return ret\r
+def update():\r
+    ret = []\r
+    CSupdate = 0\r
+    CS2update = 0\r
+    BSupdate = 0\r
+    rec10d.rec10db.set_new_status("8")\r
+    for datum in rec10d.rec10db.select_get_update_epg_ch("6"):\r
+        bctype = datum[0]\r
+        if bctype == "cs1" or bctype == u"cs1":\r
+            if CSupdate == 0:\r
+                ret.append(u"cs1")\r
+                CSupdate = 1\r
+        elif bctype == "cs2" or bctype == u"cs2":\r
+            if CS2update == 0:\r
+                ret.append(u"cs2")\r
+                CS2update = 1\r
+        elif bctype == "bs" or bctype == u"bs":\r
+            if BSupdate == 0:\r
+                ret.append(u"bs")\r
+                BSupdate = 1\r
+        else:\r
+            ret.append(bctype)\r
+    return ret\r
+def changeCHShow(chtxt,isshow):\r
+    rec10d.rec10db.change_visible_epg_ch(chtxt, isshow)\r
+def updateLogo():\r
+    ret=[]\r
+    BSCSUpdate=0\r
+    for datum in rec10d.rec10db.select_get_updatelogo_epg_ch("720"):\r
+        bctype=datum[0]\r
+        if bctype == "cs1" or bctype == u"cs1":\r
+            if BSCSUpdate==0:\r
+                ret.append(u"bs")\r
+                BSCSUpdate=1\r
+        elif bctype == "cs2" or bctype == u"cs2":\r
+            if BSCSUpdate==0:\r
+                ret.append(u"bs")\r
+                BSCSUpdate=1\r
+        elif bctype == "bs" or bctype == u"bs":\r
+            if BSCSUpdate==0:\r
+                ret.append(u"bs")\r
+                BSCSUpdate=1\r
+        else:\r
+            ret.append(bctype)\r
+    return ret\r
diff --git a/dist/trunk/rec10/checker.py b/dist/trunk/rec10/checker.py
new file mode 100755 (executable)
index 0000000..4e9bcc0
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+import os
+import os.path
+import time
+
+def checkB25Decode(b25filepath, decodedfilepath , csch):
+    ret = 0
+    if os.path.isfile(decodedfilepath):##tsファイルが存在している
+        dtime = time.time()-os.path.getmtime(decodedfilepath)
+        dtime = int(dtime)
+        if dtime > 20:
+            if csch>0:
+                if (compareFilesize(b25filepath, decodedfilepath, 10) and minimizeCheck(decodedfilepath, 800)):
+                    ret = 1
+            else:
+                if (compareFilesize(b25filepath, decodedfilepath, 60) and minimizeCheck(decodedfilepath, 800)):
+                    ret = 1
+        else:
+            time.sleep(30)
+            dtime = time.time()-os.path.getmtime(decodedfilepath)
+            dtime = int(dtime)
+            if dtime > 20:
+                if csch>0:
+                    if (compareFilesize(b25filepath, decodedfilepath, 10) and minimizeCheck(decodedfilepath, 800)):
+                        ret = 1
+                else:
+                    if (compareFilesize(b25filepath, decodedfilepath, 60) and minimizeCheck(decodedfilepath, 800)):
+                        ret = 1
+    #recdblist.printutf8("deleting b25 is " + str(ret))
+    return ret
+def compareFilesize(pathbase, path, percentage):
+    """
+    return true if size of path is larger than that of pathbase.
+    percentage is int(0< <100)
+    """
+    if not os.path.exists(pathbase):
+        return 0
+    basesize = os.path.getsize(pathbase)
+    pathsize = os.path.getsize(path)
+    size = pathsize * 100-basesize * percentage
+    if size < 0:
+        return 0
+    else:
+        return 1
+def minimizeCheck(filepath, minsize):
+    """
+    minsize is Megabytes
+    """
+    if os.path.getsize(filepath) > minsize * 1000 * 1000:
+        return 1
+    else:
+        return 0
diff --git a/dist/trunk/rec10/classify.py b/dist/trunk/rec10/classify.py
new file mode 100755 (executable)
index 0000000..29c72ee
--- /dev/null
@@ -0,0 +1,143 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+\r
+import os\r
+import os.path\r
+import optparse\r
+import sys\r
+\r
+import configreader\r
+import recdblist\r
+import auto_move\r
+import guess\r
+recordedpath=unicode(configreader.getConfPath("recorded"),'utf-8')\r
+recpath=unicode(configreader.getConfPath("recpath"),'utf-8')\r
+\r
+if __name__ == "__main__":\r
+    usage="usage: %prog read -h"\r
+    version="%prog 0.9.4"\r
+    parser=optparse.OptionParser(usage=usage,version=version)\r
+    parser.add_option("-s","--search",action="store",type="string",dest="ltitle",default="",metavar="TITLE",help="test to search where the title should be contained(test for -e)")\r
+    parser.add_option("-A","--Auto",action="store_true",dest="auto",default=False,help="auto classifying mode(not a test)")\r
+    parser.add_option("-D","--Delete",action="store_true",dest="delete",default=False,help="auto delete tempfile mode(not a test)")\r
+    parser.add_option("-e","--exec",action="store",type="string",dest="etitle",default="",metavar="TITLE",help="exec move(not a test)")\r
+    parser.add_option("-l","--list",action="store_true",dest="list",default=False,help="File listing mode(test for -A)")\r
+    parser.add_option("-t","--tssearch",action="store_true",dest="tssearch",default=False,help="Ts move auto search")\r
+    parser.add_option("-T","--Tsmove",action="store_true",dest="tsmove",default=False,help="Ts auto move.")\r
+    parser.add_option("-S","--SeriesNum",action="store",type="string",dest="seriespath",default="",metavar="TITLE",help="Search Series Number in the path.")\r
+    #parser.add_option("-f","--filenumlist",action="store_true",dest="filenumlist",default=False,help="Guess Program Number.")\r
+\r
+    (opts,args)=parser.parse_args(sys.argv)\r
+    if opts.ltitle!="":##-sの場合\r
+        ltitle=unicode(opts.ltitle,'utf-8')\r
+        sf=guess.searchFolder(ltitle, recordedpath)\r
+        print "###MKV###"\r
+        recdblist.printutf8(os.path.join(sf, auto_move.getMoveDestpath(ltitle,recpath,sf,".mkv")+".mkv"),verbose_level=100)\r
+        print "\n"\r
+        print "###MP4###"\r
+        recdblist.printutf8(os.path.join(sf, auto_move.getMoveDestpath(ltitle,recpath,sf,".mp4")+".mp4"),verbose_level=100)\r
+        print "\n"\r
+    elif opts.auto:##-A の場合\r
+        sa=auto_move.searchFile(recpath, recordedpath, ".mkv")\r
+        for t in sa:\r
+            recdblist.printutf8(u"自動推測実行中-MKV",verbose_level=100)\r
+            sf=guess.searchFolder(t,recordedpath)\r
+            if sf!="":\r
+                recdblist.printutf8(u"移動先",verbose_level=100)\r
+                recdblist.printutf8(t+" : "+os.path.join(sf, auto_move.getMoveDestpath(t, recpath,sf,".mkv")+".mkv"),verbose_level=100)\r
+                recdblist.printutf8(u"実行中",verbose_level=100)\r
+                auto_move.execMove(t, recpath, recordedpath,".mkv",1)\r
+            else:\r
+                recdblist.printutf8(t+" can't find matching folder",verbose_level=100)\r
+        sa=auto_move.searchFile(recpath, recordedpath, ".mp4")\r
+        for t in sa:\r
+            recdblist.printutf8(u"自動推測実行中-MP4",verbose_level=100)\r
+            sf=guess.searchFolder(t,recordedpath)\r
+            if sf!="":\r
+                recdblist.printutf8(u"移動先",verbose_level=100)\r
+                recdblist.printutf8(t+" : "+os.path.join(sf, auto_move.getMoveDestpath(t, recpath,sf,".mp4")+".mp4"),verbose_level=100)\r
+                recdblist.printutf8(u"実行中",verbose_level=100)\r
+                auto_move.execMove(t, recpath, recordedpath,".mp4",1)\r
+            else:\r
+                recdblist.printutf8(t+" can't find matching folder",verbose_level=100)\r
+    elif opts.delete:##-Dの場合\r
+        sa=auto_move.searchFile(recpath, recordedpath,".mkv")\r
+        for t in sa:\r
+            auto_move.execDelete(t, recpath)\r
+        sa=auto_move.searchFile(recpath, recordedpath,".mp4")\r
+        for t in sa:\r
+            auto_move.execDelete(t, recpath)\r
+    elif opts.list:##-lの場合\r
+        sa=auto_move.searchFile(recpath, recordedpath,".mkv")\r
+        for t in sa:\r
+            sf=guess.searchFolder(t,recordedpath)\r
+            if sf!="":\r
+                recdblist.printutf8(t+u" : "+os.path.join(sf, auto_move.getMoveDestpath(t, recpath,sf,".mkv")+".mkv"),verbose_level=100)\r
+        sa=auto_move.searchFile(recpath, recordedpath,".mp4")\r
+        for t in sa:\r
+            sf=guess.searchFolder(t,recordedpath)\r
+            if sf!="":\r
+                recdblist.printutf8(t+u" : "+os.path.join(sf, auto_move.getMoveDestpath(t, recpath,sf,".mp4")+".mp4"),verbose_level=100)\r
+    elif opts.etitle!="":\r
+        if os.path.exists(os.path.join(recpath, etitle+".mkv")):\r
+            auto_move.execMove(etitle,recpath, recordedpath,".mkv",1)\r
+        elif os.path.exists(os.path.join(recpath, etitle+".mp4")):\r
+            auto_move.execMove(etitle,recpath, recordedpath,".mp4",1)\r
+    elif opts.tssearch:## -tの場合\r
+        tsmovepath=""\r
+        try:\r
+            tsmovepath=unicode(configreader.getConfPath("ts_movepath"),'utf-8')\r
+        except:\r
+            ""\r
+        if tsmovepath!="":\r
+            sa=auto_move.searchFile(recpath, tsmovepath,".ts")\r
+            for t in sa:\r
+                sf=guess.searchFolder(t,tsmovepath,700)\r
+                if sf!="":\r
+                    recdblist.printutf8(t+u" : "+os.path.join(sf, auto_move.getMoveDestpath(t, recpath,sf,".ts")+".ts"))\r
+                    print "\n"\r
+            sa=auto_move.searchFile(recpath, tsmovepath,".ts")\r
+        else:\r
+            recdblist.printutf8(u"ts_movepathが設定されていません。/etc/rec10.confを設定してください。",verbose_level=100)\r
+    elif opts.tsmove:##-Tの場合\r
+        tsmovepath=""\r
+        try:\r
+            tsmovepath=unicode(configreader.getConfPath("ts_movepath"),'utf-8')\r
+        except:\r
+            ""\r
+        if tsmovepath!="":\r
+            sa=auto_move.searchFile(recpath, tsmovepath,".ts")\r
+            for t in sa:\r
+                sf=guess.searchFolder(t,tsmovepath,700)\r
+                if sf!="":\r
+                    recdblist.printutf8(u"移動先",verbose_level=100)\r
+                    recdblist.printutf8(t+" : "+os.path.join(sf, auto_move.getMoveDestpath(t, recpath,sf,".ts")+".ts"),verbose_level=100)\r
+                    recdblist.printutf8(u"実行中",verbose_level=100)\r
+                    auto_move.execMove(t, recpath, tsmovepath,".ts",0)\r
+            sa=auto_move.searchFile(recpath, tsmovepath,".ts")\r
+        else:\r
+            recdblist.printutf8(u"ts_movepathが設定されていません。/etc/rec10.confを設定してください。",verbose_level=100)\r
+    elif opts.seriespath!="":##-Sの場合##与えられたパスにシリーズがそろっているかを調べる。\r
+        ss=guess.detSeriesNum(opts.seriespath)\r
+        for sstitle, ssv in ss.iteritems():\r
+            if len(ssv)>0:\r
+                maxt=0\r
+                bt=0\r
+                alr=[]\r
+                for ssi,ssiv in ssv.iteritems():\r
+                    alr.append(ssi)\r
+                    if maxt<ssi:\r
+                        maxt=ssi\r
+                alr=list(set(alr))\r
+                alr.sort()\r
+                alr.reverse()\r
+                nuke=""\r
+                for i in xrange(1,maxt+1,1):\r
+                    if alr.count(i)==0:\r
+                        nuke=nuke+str(i)+","\r
+                if len(nuke)==0:\r
+                    recdblist.printutf8(sstitle+" "+str(maxt))\r
+                else:\r
+                    recdblist.printutf8(u"**"+sstitle+" |"+str(maxt)+"| "+nuke)\r
diff --git a/dist/trunk/rec10/configreader.py b/dist/trunk/rec10/configreader.py
new file mode 100755 (executable)
index 0000000..cf1eee5
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import ConfigParser\r
+import os\r
+import os.path\r
+mypath = str(os.path.dirname(os.path.abspath(__file__)))\r
+confp = ConfigParser.SafeConfigParser()\r
+Conf = 'rec10.conf'\r
+confpath=""\r
+if os.path.exists(os.path.join(mypath,Conf)):\r
+    confpath=os.path.join(mypath,Conf)\r
+elif os.path.exists(os.path.join("/etc","rec10.conf")):\r
+    confpath=os.path.join("/etc","rec10.conf")\r
+elif os.path.exists(os.path.join("/etc/rec10","rec10.conf")):\r
+    confpath=os.path.join("/etc/rec10","rec10.conf")\r
+confp.read(confpath)\r
+def getConfPath(string):\r
+    global confp\r
+    return confp.get('path', string)\r
+def getConfDB(string):\r
+    global confp\r
+    return confp.get('db', string)\r
+def getConfEnv(string):\r
+    global confp\r
+    return confp.get('env', string)\r
+def getConfLog(string):\r
+    global confp\r
+    return confp.get('log', string)\r
diff --git a/dist/trunk/rec10/configwriter.py b/dist/trunk/rec10/configwriter.py
new file mode 100755 (executable)
index 0000000..aa67867
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import ConfigParser\r
+import os\r
+import os.path\r
+mypath = str(os.path.dirname(os.path.abspath(__file__)))\r
+confp = ConfigParser.SafeConfigParser()\r
+Conf = 'rec10.conf'\r
+confpath=os.path.join(mypath,Conf)\r
+confp.read(confpath)\r
+def getTempConfPath(string):\r
+    global confp\r
+    return confp.get('path', string)\r
+def setTempConfPath(option,value):\r
+    global confp\r
+    return confp.set('path',option,value)\r
+def setTempConfDB(option,value):\r
+    global confp\r
+    return confp.set('db',option,value)\r
+def setTempConfEnv(option,value):\r
+    global confp\r
+    return confp.set('env',option,value)\r
+def writeTempConf():\r
+    global confp\r
+    f=open(confpath,"w")\r
+    confp.write(f)\r
+    f.close\r
diff --git a/dist/trunk/rec10/dbMySQL.py b/dist/trunk/rec10/dbMySQL.py
new file mode 100755 (executable)
index 0000000..8a88b6e
--- /dev/null
@@ -0,0 +1,1323 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+import MySQLdb
+import recdblist
+import warnings
+import traceback
+
+from decimal import Decimal
+class DB_MySQL:
+    dbname = ""
+    dbhost = ""
+    dbusr = ""
+    dbpasswd = ""
+    dbport = 0
+    def __init__(self, dbname, user, passwd, host="localhost", port=3306):
+        warnings.filterwarnings('ignore', "Data truncated for column")
+        self.dbname = dbname
+        self.dbhost = host
+        self.dbusr = user
+        self.dbpasswd = passwd
+        self.dbport = port
+        try:
+            con = MySQLdb.connect(user=user, passwd=passwd)
+            cur = con.cursor()
+            cur.execute('CREATE DATABASE ' + dbname + " DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;")
+            cur.close()
+            con.close()
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "init (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        db = self.connect_db()
+        try:
+            db[1].execute('\
+            CREATE TABLE timeline \
+            (\
+            id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,\
+            type VARCHAR(40),\
+            chtxt VARCHAR(40),\
+            title VARCHAR(100),\
+            btime DATETIME,\
+            etime DATETIME,\
+            deltatime VARCHAR(5),\
+            deltaday VARCHAR(5),\
+            opt VARCHAR(20),\
+            epgtitle VARCHAR(100),\
+            epgbtime DATETIME,\
+            epgetime DATETIME,\
+            epgduplicate TINYINT DEFAULT 0,\
+            epgchange TINYINT DEFAULT 0,\
+            epgexp VARCHAR(200),\
+            epgcategory VARCHAR(100),\
+            counter TINYINT DEFAULT -1,\
+            UNIQUE uni (type,chtxt,title,btime,deltaday)\
+            )')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "init (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        self.close_db(db)
+        self.new_epg_timeline("")
+        self.new_in_timeline_log()
+        self.new_in_auto_bayes_key()
+        self.new_in_auto_jbk_key()
+        self.new_in_status()
+        self.new_in_settings()
+        self.new_auto_timeline_bayes()
+        self.new_auto_timeline_keyword()
+    def connect_db(self):
+        """
+        dbへの接続
+        """
+        con = MySQLdb.connect(db=self.dbname, host=self.dbhost, port=self.dbport, user=self.dbusr, passwd=self.dbpasswd, charset="utf8")
+        cur = con.cursor()
+        try:
+            con.autocommit(1)
+        except:
+            ""
+        cur.execute('set names utf8;')
+        return [con, cur]
+    def close_db(self, db):
+        db[1].close()
+        db[0].close()
+    def new_epg_ch(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('drop table epg_ch')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and (inst[0]==1050 or inst[0]==1051))):
+                recdblist.addCommonlogEX("Error", "new_epg_ch drop (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+
+        try:
+            db[1].execute('\
+            CREATE TABLE epg_ch \
+            (\
+            bctype VARCHAR(15),\
+            chtxt VARCHAR(20) PRIMARY KEY,\
+            ch VARCHAR(20),\
+            csch VARCHAR(20),\
+            chname VARCHAR(100),\
+            updatetime DATETIME,\
+            status TINYINT,\
+            visible TINYINT DEFAULT 1,\
+            logo0 BLOB,\
+            logo1 BLOB,\
+            logo2 BLOB,\
+            logo3 BLOB,\
+            logo4 BLOB,\
+            logo5 BLOB,\
+            logoupdate DATETIME,\
+            logostatus TINYINT DEFAULT 2,\
+            scanupdate DATETIME\
+            )')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_epg_ch (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+
+        self.close_db(db)
+    def add_epg_ch(self, bctype, chtxt, ch, csch, updatetime,logoupdate,scanupdate):
+        db = self.connect_db()
+        db[1].execute('\
+        INSERT INTO epg_ch (bctype,chtxt,ch,csch,chname,updatetime,status,visible,logoupdate,scanupdate)\
+        VALUES (%s,%s,%s,%s,"",%s,%s,%s,%s,%s)', \
+                      (bctype, chtxt, ch, csch, updatetime, "1","1",logoupdate,scanupdate))
+        self.close_db(db)
+    def delete_all_epg_ch(self):
+        db = self.connect_db()
+        db[1].execute('\
+        DROP TABLE epg_ch ')
+        self.close_db(db)
+    def select_by_chtxt_epg_ch(self, chtxt):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT bctype,chtxt,ch,csch,updatetime,chname,status,visible,logoupdate,scanupdate \
+        FROM epg_ch \
+        WHERE chtxt LIKE %s", \
+                              (chtxt,))
+        ret = []
+        dls = []
+        if dbexe > 0:
+            dls = db[1].fetchall()
+        self.close_db(db)
+        for dl in dls:
+            r = list(dl)
+            r[4] = r[4].strftime("%Y-%m-%d %H:%M:%S")
+            if r[8]!=None:
+                r[8] = r[8].strftime("%Y-%m-%d %H:%M:%S")
+            else:
+                r[8]="2011-04-01 00:00:00"
+            r[9] = r[9].strftime("%Y-%m-%d %H:%M:%S")
+            ret.append(r)
+        return ret
+    def select_by_bctype_epg_ch(self, bctype):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT bctype,chtxt,ch,csch,updatetime,status,chname,status,visible,logoupdate,scanupdate \
+        FROM epg_ch \
+        WHERE bctype = %s", \
+                              (bctype,))
+        ret = []
+        dls = []
+        if dbexe > 0:
+            dls = db[1].fetchall()
+        self.close_db(db)
+        for dl in dls:
+            #recdblist.printutf8(dl)
+            r = list(dl)
+            r[4] = r[4].strftime("%Y-%m-%d %H:%M:%S")
+            if r[9]!=None:
+                r[9] = r[9].strftime("%Y-%m-%d %H:%M:%S")
+            else:
+                r[9]="2011-04-01 00:00:00"
+            r[10] = r[10].strftime("%Y-%m-%d %H:%M:%S")
+            r[5] = str(r[5])
+            ret.append(r)
+        import random
+        ret.insert(0,ret[random.randint(0,len(ret)-1)])
+        return ret
+    def select_by_ch_epg_ch(self, ch):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT \
+        bctype,chtxt,ch,csch,updatetime,chname,status,visible,logoupdate,scanupdate \
+        FROM epg_ch \
+        WHERE ch = %s", \
+                              (ch,))
+        ret = []
+        dls = []
+        if dbexe > 0:
+            dls = db[1].fetchall()
+        self.close_db(db)
+        for dl in dls:
+            r = list(dl)
+            r[4] = r[4].strftime("%Y-%m-%d %H:%M:%S")
+            r[8] = r[8].strftime("%Y-%m-%d %H:%M:%S")
+            r[9] = r[9].strftime("%Y-%m-%d %H:%M:%S")
+            ret.append(r)
+        return ret
+    def select_by_csch_epg_ch(self, csch):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT \
+        bctype,chtxt,ch,csch,updatetime,chname,status,visible,logoupdate,scanupdate \
+        FROM epg_ch \
+        WHERE csch = %s", \
+                              (csch,))
+        ret = []
+        dls = []
+        if dbexe > 0:
+            dls = db[1].fetchall()
+        self.close_db(db)
+        for dl in dls:
+            r = list(dl)
+            r[4] = r[4].strftime("%Y-%m-%d %H:%M:%S")
+            r[8] = r[8].strftime("%Y-%m-%d %H:%M:%S")
+            r[9] = r[9].strftime("%Y-%m-%d %H:%M:%S")
+            ret.append(r)
+        return ret
+    def select_all_epg_ch(self):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT bctype,chtxt,ch,csch,updatetime,chname,status,visible,logoupdate,scanupdate \
+        FROM epg_ch \
+        ")
+        ret = []
+        dls = []
+        if dbexe > 0:
+            dls = db[1].fetchall()
+        self.close_db(db)
+        for dl in dls:
+            r = list(dl)
+            r[4] = r[4].strftime("%Y-%m-%d %H:%M:%S")
+            r[8] = r[8].strftime("%Y-%m-%d %H:%M:%S")
+            r[9] = r[9].strftime("%Y-%m-%d %H:%M:%S")
+            ret.append(r)
+        return ret
+    def change_visible_epg_ch(self,chtxt,visible):
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE epg_ch SET visible=%s WHERE chtxt=%s",(visible,chtxt))
+        self.close_db(db)
+    def change_logodata_epg_ch(self,chtxt,logonum,logodata):
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE epg_ch SET logo"+str(logonum)+"=%s WHERE chtxt=%s",(logodata,chtxt))
+        self.close_db(db)
+    def set_new_status(self,dhour):
+        db = self.connect_db()
+        dbexe = db[1].execute("UPDATE epg_ch \
+        SET status = 1 \
+        WHERE \
+        ( \
+        updatetime < DATE_SUB(now(),INTERVAL " + dhour + " HOUR) \
+        AND \
+        status = 0 \
+        )"\
+        )
+    def select_get_update_epg_ch(self, dhour):
+        db = self.connect_db()
+        dbexe = db[1].execute("SELECT bctype,chtxt,status FROM epg_ch \
+        WHERE (\
+        ( \
+        updatetime < DATE_SUB(now(),INTERVAL " + dhour + " HOUR) \
+        AND \
+        status = 1 \
+        ) \
+        OR \
+        status > 1 )\
+        ORDER BY status DESC")
+        ret = []
+        #recdblist.printutf8(dbexe)
+        if dbexe > 0:
+            ret = db[1].fetchall()
+        self.close_db(db)
+        return ret
+    def select_get_updatelogo_epg_ch(self, dhour):
+        db = self.connect_db()
+        dbexe = db[1].execute("SELECT bctype,chtxt,logostatus FROM epg_ch \
+        WHERE (\
+        ( \
+        updatetime < DATE_SUB(now(),INTERVAL " + dhour + " HOUR) \
+        AND \
+        logostatus = 1 \
+        ) \
+        OR \
+        logostatus > 1 )\
+        ORDER BY status DESC")
+        ret = []
+        #recdblist.printutf8(dbexe)
+        if dbexe > 0:
+            ret = db[1].fetchall()
+        self.close_db(db)
+        return ret
+    def update_by_bctype_epg_ch(self, bctype):
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE epg_ch \
+        SET \
+        updatetime=now() , \
+        status = 1 \
+        WHERE bctype = %s", (bctype,))
+        self.close_db(db)
+
+    def update_by_bctype_and_chtxt_epg_ch(self, bctype, chtxt):
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE epg_ch \
+        SET \
+        updatetime=now() , \
+        status = 1\
+        WHERE bctype = %s AND chtxt = %s", (bctype, chtxt))
+        self.close_db(db)
+    def update_chname_by_chtxt_epg_ch(self,chtxt,chname):
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE epg_ch \
+        SET \
+        chname = %s \
+        WHERE chtxt = %s", (chname,chtxt))
+        self.close_db(db)
+    def update_status_by_bctype_epg_ch(self, bctype, status):
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE epg_ch \
+        SET \
+        status=%s , \
+        updatetime=now() \
+        WHERE bctype = %s", \
+                      (status, bctype)\
+                      )
+        self.close_db(db)
+    def update_logostatus_by_bctype_epg_ch(self,bctype,logostatus):
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE epg_ch \
+        SET \
+        logostatus=%s , \
+        logoupdate=now() \
+        WHERE bctype = %s", \
+                      (logostatus, bctype)\
+                      )
+        self.close_db(db)
+    def add_auto_proc_tmp(self,type,title,chtxt):
+        db = self.connect_db()
+        db[1].execute('\
+        INSERT IGNORE into auto_proc_tmp \
+        (type,title,chtxt) \
+        values (%s,%s,%s)',(type,title,chtxt))
+        ##db.commit()
+        self.close_db(db)
+    def new_auto_proc_tmp(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('drop table auto_proc_tmp')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and (inst[0]==1050 or inst[0]==1051))):
+                recdblist.addCommonlogEX("Error", "new_auto_proc_tmp drop (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+
+        try:
+            db[1].execute('\
+            CREATE TABLE auto_proc_tmp \
+            (\
+            type VARCHAR(20),\
+            title VARCHAR(100) PRIMARY KEY,\
+            chtxt VARCHAR(30),\
+            UNIQUE unibayeskey(title)\
+            )')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_auto_proc_tmp (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+
+        self.close_db(db)
+    def update_auto_proc(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('INSERT INTO auto_proc SELECT * FROM auto_proc_tmp')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "update_auto_proc (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+
+        self.close_db(db)
+    def new_auto_proc(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('drop table auto_proc')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and (inst[0]==1050 or inst[0]==1051))):
+                recdblist.addCommonlogEX("Error", "new_auto_proc drop (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+
+        try:
+            db[1].execute('\
+            CREATE TABLE auto_proc \
+            (\
+            type VARCHAR(20),\
+            title VARCHAR(100) PRIMARY KEY,\
+            chtxt VARCHAR(30),\
+            UNIQUE unibayeskey(title)\
+            )')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_auto_proc (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+
+        self.close_db(db)
+    def add_auto_proc(self,type,title,chtxt):
+        db = self.connect_db()
+        db[1].execute('\
+        INSERT IGNORE into auto_proc \
+        (type,title,chtxt) \
+        values (%s,%s,%s)',(type,title,chtxt))
+        ##db.commit()
+        self.close_db(db)
+    def drop_in_settings(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('drop table in_settings')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and (inst[0]==1050 or inst[0]==1051))):
+                recdblist.addCommonlogEX("Error", "drop_in_settings (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        self.close_db(db)
+    def new_in_settings(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('\
+            CREATE TABLE in_settings \
+            (\
+            auto_jbk TINYINT,\
+            auto_bayes TINYINT,\
+            auto_opt VARCHAR(20),\
+            auto_del_tmp TINYINT\
+            )')
+            db[1].execute("INSERT IGNORE into in_settings VALUE (0,0,\"H\",1)")
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_in_settings (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+
+        self.close_db(db)
+    def select_all_in_settings(self):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT auto_jbk,auto_bayes,auto_del_tmp,auto_opt \
+        FROM in_settings \
+        ")
+        ret = []
+        dls = []
+        if dbexe > 0:
+            dls = db[1].fetchall()
+        self.close_db(db)
+        for dl in dls:
+            r = list(dl)
+            r[0]=str(r[0])
+            r[1]=str(r[1])
+            r[2]=str(r[2])
+            r[3]=r[3]
+            ret.append(r)
+        return ret
+    def add_in_timeline_log(self , chtxt="", title="", btime="", etime="", opt="", exp="", longexp="", category=""):
+        db = self.connect_db()
+        db[1].execute('\
+        INSERT IGNORE into in_timeline_log \
+        (chtxt,title,btime,etime,opt,exp,longexp,category) \
+        values (%s,%s,%s,%s,%s,%s,%s,%s)', \
+                      ( chtxt, title, btime, etime, opt,exp,longexp,category))
+        ##db.commit()
+        self.close_db(db)
+    def del_in_timeline_log(self, title="", chtxt="", btime=""):
+        """
+
+        """
+        db = self.connect_db()
+        db[1].execute("\
+        DELETE FROM in_timeline_log \
+        WHERE title = %s AND chtxt = %s AND btime = %s", \
+                      (title, chtxt, btime))
+        #db.commit()
+        self.close_db(db)
+    def new_in_timeline_log(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('\
+            CREATE TABLE in_timeline_log \
+            (\
+            id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,\
+            chtxt VARCHAR(20),\
+            title VARCHAR(100),\
+            btime DATETIME,\
+            etime DATETIME,\
+            opt VARCHAR(20),\
+            exp VARCHAR(200),\
+            longexp TEXT,\
+            category VARCHAR(100),\
+            UNIQUE uni (chtxt,title,btime,category)\
+            )')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_in_timeline_log (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+
+        self.close_db(db)
+    def select_chtxt_by_title_timeline_log(self,title):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT chtxt \
+        FROM in_timeline_log \
+        WHERE title LIKE \"%"+title+"%\"\
+        GROUP by chtxt\
+        ORDER by sum(1) DESC limit 1")
+        retdb=db[1].fetchall()
+        ret=""
+        if ret!=None:
+            if len(retdb)>0:
+                ret=retdb[0][0]
+        self.close_db(db)
+        return ret
+    def add_timeline(self, type="", chtxt="", title="", btime="", etime="", deltatime="", deltaday="", opt="" ,counter=-1):
+        db = self.connect_db()
+        db[1].execute('\
+        INSERT IGNORE into timeline \
+        (type,chtxt,title,btime,etime,deltatime,deltaday,opt,counter) \
+        values (%s,%s,%s,%s,%s,%s,%s,%s,%s)', \
+                      (type, chtxt, title, btime, etime, deltatime, deltaday, opt ,counter))
+        ##db.commit()
+        self.close_db(db)
+    def update_epg_timeline(self,type,chtxt,title,btime,epgbtime,epgetime,epgtitle,epgexp,epgcategory):
+        db = self.connect_db()
+        db[1].execute('\
+        UPDATE timeline \
+        SET epgbtime=%s,epgetime=%s,epgtitle=%s,epgexp=%s,epgcategory=%s \
+        WHERE type=%s AND chtxt=%s AND title=%s AND btime=%s ', \
+                      (epgbtime,epgetime,epgtitle,epgexp,epgcategory,type, chtxt, title, btime))
+        ##db.commit()
+        self.close_db(db)
+    def update_status_change_timeline(self,type,chtxt,title,btime,epgchange):
+        db = self.connect_db()
+        db[1].execute('\
+        UPDATE timeline \
+        SET epgchange =%s \
+        WHERE type=%s AND chtxt=%s AND title=%s AND btime=%s ', \
+                      (epgchange , type, chtxt, title, btime))
+        ##db.commit()
+        self.close_db(db)
+    def update_status_dup_timeline(self,type,chtxt,title,btime,epgduplicate):
+        db = self.connect_db()
+        db[1].execute('\
+        UPDATE timeline \
+        SET epgduplicate =%s \
+        WHERE type=%s AND chtxt=%s AND title=%s AND btime=%s ', \
+                      (epgduplicate , type, chtxt, title, btime))
+        ##db.commit()
+        self.close_db(db)
+    def del_timeline(self, type="", title="", chtxt="", btime=""):
+        """
+
+        """
+        db = self.connect_db()
+        db[1].execute("\
+        DELETE FROM timeline \
+        WHERE type = %s AND title = %s AND chtxt = %s AND btime = %s", \
+                      (type, title, chtxt, btime))
+        #db.commit()
+        self.close_db(db)
+    def select_all_timeline(self):
+        db = self.connect_db()
+        recdata = []
+        dbr = db[1].execute("\
+        SELECT type, chtxt, title, btime, etime, deltatime ,deltaday ,opt ,epgbtime ,epgetime ,epgtitle ,epgduplicate ,epgchange ,counter\
+        FROM timeline")
+        dbl = db[1].fetchall()
+        self.close_db(db)
+        if dbr > 0:
+            recdata = self.getdic_timeline(dbl)
+        return recdata
+    def select_bytime_timeline(self, dminutes):
+        db = self.connect_db()
+        recdatum = []
+        #dbr=db[1].execute("SELECT type, chtxt, title, btime, etime, deltatime ,deltaday ,opt FROM rectime WHERE btime < DATE_SUB(now(),INTERVAL "+dminutes+" MINUTE ) AND btime > DATE_ADD(now(),INTERVAL "+dminutes+" MINUTE )")
+        dbr = db[1].execute("SELECT \
+        type, chtxt, title, btime, etime, deltatime ,deltaday ,opt ,epgbtime ,epgetime ,epgtitle ,epgduplicate ,epgchange ,counter\
+        FROM timeline \
+        WHERE btime BETWEEN DATE_SUB(now(),INTERVAL " + dminutes + " MINUTE ) AND \
+        DATE_ADD(now(),INTERVAL " + dminutes + " MINUTE )")
+        dbl = db[1].fetchall()
+        self.close_db(db)
+        #recdblist.printutf8(dbl)
+        if dbr > 0:
+            recdatum = self.getdic_timeline(dbl)
+        return recdatum
+    def select_by_name_time_timeline(self,title,btime,btime2):
+        db = self.connect_db()
+        recdatum = []
+        #dbr=db[1].execute("SELECT type, chtxt, title, btime, etime, deltatime ,deltaday ,opt FROM rectime WHERE btime < DATE_SUB(now(),INTERVAL "+dminutes+" MINUTE ) AND btime > DATE_ADD(now(),INTERVAL "+dminutes+" MINUTE )")
+        dbr = db[1].execute("SELECT \
+        type, chtxt, title, btime, etime, deltatime ,deltaday ,opt ,epgbtime ,epgetime ,epgtitle ,epgduplicate ,epgchange ,counter\
+        FROM timeline \
+        WHERE btime > %s AND \
+        btime < %s AND title = %s",(btime,btime2,title))
+        dbl = db[1].fetchall()
+        self.close_db(db)
+        #recdblist.printutf8(dbl)
+        if dbr > 0:
+            recdatum = self.getdic_timeline(dbl)
+        return recdatum
+    def select_bytime_all_timeline(self,btime,etime):
+        db = self.connect_db()
+        recdatum = []
+        #dbr=db[1].execute("SELECT type, chtxt, title, btime, etime, deltatime ,deltaday ,opt FROM rectime WHERE btime < DATE_SUB(now(),INTERVAL "+dminutes+" MINUTE ) AND btime > DATE_ADD(now(),INTERVAL "+dminutes+" MINUTE )")
+        dbr = db[1].execute("SELECT \
+        type, chtxt, title, btime, etime, deltatime ,deltaday ,opt ,epgbtime ,epgetime ,epgtitle ,epgduplicate ,epgchange ,counter\
+        FROM timeline \
+        WHERE btime >= %s AND \
+        etime <= %s",(btime,etime))
+        dbl = db[1].fetchall()
+        self.close_db(db)
+        #recdblist.printutf8(dbl)
+        if dbr > 0:
+            recdatum = self.getdic_timeline(dbl)
+        return recdatum
+    def select_byepgtime_all_timeline(self,epgbtime,epgetime):
+        db = self.connect_db()
+        recdatum = []
+        #dbr=db[1].execute("SELECT type, chtxt, title, btime, etime, deltatime ,deltaday ,opt FROM rectime WHERE btime < DATE_SUB(now(),INTERVAL "+dminutes+" MINUTE ) AND btime > DATE_ADD(now(),INTERVAL "+dminutes+" MINUTE )")
+        dbr = db[1].execute("SELECT \
+        type, chtxt, title, btime, etime, deltatime ,deltaday ,opt ,epgbtime ,epgetime ,epgtitle ,epgduplicate ,epgchange ,counter\
+        FROM timeline \
+        WHERE epgbtime >= %s AND \
+        epgetime <= %s",(epgbtime,epgetime))
+        dbl = db[1].fetchall()
+        self.close_db(db)
+        #recdblist.printutf8(dbl)
+        if dbr > 0:
+            recdatum=self.getdic_timeline(dbl)
+        return recdatum
+    def select_byepgtime_over_timeline(self,epgbtime,epgetime):
+        db = self.connect_db()
+        recdatum = []
+        #dbr=db[1].execute("SELECT type, chtxt, title, btime, etime, deltatime ,deltaday ,opt FROM rectime WHERE btime < DATE_SUB(now(),INTERVAL "+dminutes+" MINUTE ) AND btime > DATE_ADD(now(),INTERVAL "+dminutes+" MINUTE )")
+        dbr = db[1].execute("SELECT \
+        type, chtxt, title, btime, etime, deltatime ,deltaday ,opt ,epgbtime ,epgetime ,epgtitle ,epgduplicate ,epgchange ,counter\
+        FROM timeline \
+        WHERE (NOT(( timeline.epgetime <= %s )OR( timeline.epgbtime >= %s )))"\
+        ,(epgbtime,epgetime))
+        dbl = db[1].fetchall()
+        self.close_db(db)
+        #recdblist.printutf8(dbl)
+        if dbr > 0:
+            recdatum=self.getdic_timeline(dbl)
+        return recdatum
+    def count_schedule_timeline(self, btime, etime):
+        """
+        count rectasknum
+        return [te num,bs/cs num]
+        """
+        db = self.connect_db()
+        dbexe = "SELECT type,epg_ch.bctype,timeline.chtxt,title FROM timeline INNER JOIN epg_ch ON timeline.chtxt=epg_ch.chtxt"
+        dbexe = dbexe + " WHERE ((NOT(( timeline.etime <= %s )OR( timeline.btime >= %s ))) OR ((timeline.btime = %s) AND (timeline.etime = %s) ) )"
+        Srec = 0
+        Trec = 0
+        db[1].execute(dbexe, (btime, etime,btime,etime))
+        dbl=db[1].fetchall()
+        for typet, bctypet, chtxtt, titlet in dbl:
+            if (typet == recdblist.REC_RESERVE) or (typet == recdblist.REC_FINAL_RESERVE) or (typet == recdblist.REC_KEYWORD) or (typet == recdblist.REC_KEYWORD_EVERY_SOME_DAYS):
+                if bctypet.find("cs") > -1:
+                    Srec = Srec + 1
+                elif bctypet.find("bs") > -1:
+                    Srec = Srec + 1
+                elif bctypet.find("te") > -1:
+                    Trec = Trec + 1
+        self.close_db(db)
+        return [Trec, Srec]
+    def search_schedule_timeline(self,btime,etime):
+        """
+        count rectasknum
+        return [(type,bctype,chtxt,title,btime,etime)]
+        """
+        db = self.connect_db()
+        dbexe = "SELECT type,epg_ch.bctype,timeline.chtxt,title,timeline.btime,timeline.etime FROM timeline INNER JOIN epg_ch ON timeline.chtxt=epg_ch.chtxt"
+        dbexe = dbexe + " WHERE ((NOT(( timeline.etime <= %s )OR( timeline.btime >= %s ))) OR ((timeline.btime = %s) AND (timeline.etime = %s) ) )"
+        ret=[]
+        db[1].execute(dbexe, (btime, etime,btime,etime))
+        dbl=db[1].fetchall()
+        for typet, bctypet, chtxtt, titlet , btimet, etimet in dbl:
+            if (typet == recdblist.REC_RESERVE) or (typet == recdblist.REC_FINAL_RESERVE) or (typet == recdblist.REC_KEYWORD) or (typet == recdblist.REC_KEYWORD_EVERY_SOME_DAYS):
+                ret.append([typet,bctypet,chtxtt,titlet,btimet,etimet])
+        self.close_db(db)
+        return ret
+    def count_epgschedule_timeline(self, epgbtime, epgetime):
+        """
+        count rectasknum
+        return [te num,bs/cs num]
+        """
+        db = self.connect_db()
+        dbexe = "SELECT type,epg_ch.bctype,timeline.chtxt,title FROM timeline INNER JOIN epg_ch ON timeline.chtxt=epg_ch.chtxt"
+        dbexe = dbexe + " WHERE (NOT(( timeline.epgetime <= %s )OR( timeline.epgbtime >= %s )))"
+        Srec = 0
+        Trec = 0
+        db[1].execute(dbexe, (epgbtime, epgetime))
+        dbl=db[1].fetchall()
+        for typet, bctypet, chtxtt, titlet in dbl:
+            if (typet == recdblist.REC_RESERVE) or (typet == recdblist.REC_FINAL_RESERVE) or (typet == recdblist.REC_KEYWORD) or (typet == recdblist.REC_KEYWORD_EVERY_SOME_DAYS):
+                if bctypet.find("cs") > -1:
+                    Srec = Srec + 1
+                elif bctypet.find("bs") > -1:
+                    Srec = Srec + 1
+                elif bctypet.find("te") > -1:
+                    Trec = Trec + 1
+        self.close_db(db)
+        return [Trec, Srec]
+    def search_epgschedule_timeline(self,epgbtime,epgetime):
+        """
+        count rectasknum
+        return [(type,bctype,chtxt,title,btime,etime)]
+        """
+        db = self.connect_db()
+        dbexe = "SELECT type,epg_ch.bctype,timeline.chtxt,title,timeline.btime,timeline.etime FROM timeline INNER JOIN epg_ch ON timeline.chtxt=epg_ch.chtxt"
+        dbexe = dbexe + " WHERE ((NOT(( timeline.epgetime <= %s )OR( timeline.epgbtime >= %s ))) OR ((timeline.epgbtime = %s) AND (timeline.epgetime = %s) ) )"
+        ret=[]
+        db[1].execute(dbexe, (epgbtime, epgetime,epgbtime,epgetime))
+        dbl=db[1].fetchall()
+        for typet, bctypet, chtxtt, titlet , btimet, etimet in dbl:
+            if (typet == recdblist.REC_RESERVE) or (typet == recdblist.REC_FINAL_RESERVE) or (typet == recdblist.REC_KEYWORD) or (typet == recdblist.REC_KEYWORD_EVERY_SOME_DAYS):
+                ret.append([typet,bctypet,chtxtt,titlet,btimet,etimet])
+        self.close_db(db)
+        return ret
+    def select_bytime_bychtxt_all_timeline(self,btime,etime,chtxt):
+        db = self.connect_db()
+        recdatum = []
+        #dbr=db[1].execute("SELECT type, chtxt, title, btime, etime, deltatime ,deltaday ,opt FROM rectime WHERE btime < DATE_SUB(now(),INTERVAL "+dminutes+" MINUTE ) AND btime > DATE_ADD(now(),INTERVAL "+dminutes+" MINUTE )")
+        dbr = db[1].execute("SELECT \
+        type, chtxt, title, btime, etime, deltatime ,deltaday ,opt ,epgbtime ,epgetime ,epgtitle ,epgduplicate ,epgchange ,counter\
+        FROM timeline \
+        WHERE btime > %s AND \
+        etime < %s\
+        AND chtxt=%s ",(btime,etime,chtxt))
+        dbl = db[1].fetchall()
+        self.close_db(db)
+        #recdblist.printutf8(dbl)
+        if dbr > 0:
+            recdatum = self.getdic_timeline(dbl)
+        return recdatum
+    def getdic_timeline(self,timelinelists):
+        recdatum=[]
+        for typet, chtxt, title, btime, etime, deltatime, deltaday, opt ,epgbtimet , epgetimet ,epgtitlet ,epgduplicatet ,epgchanget ,countert in timelinelists:
+            ret = {}
+            ret['type'] = typet
+            ret['chtxt'] = chtxt
+            ret['title'] = title
+            btime = btime.strftime("%Y-%m-%d %H:%M:%S")
+            etime = etime.strftime("%Y-%m-%d %H:%M:%S")
+            ret['btime'] = btime
+            ret['etime'] = etime
+            ret['opt'] = opt
+            try:
+                ret['epgbtime'] = epgbtimet.strftime("%Y-%m-%d %H:%M:%S")
+                ret['epgetime'] = epgetimet.strftime("%Y-%m-%d %H:%M:%S")
+            except:
+                ret['epgbtime'] = "2010-01-01 00:00:00"
+                ret['epgetime'] = "2010-01-01 00:00:00"
+            ret['epgtitle'] = epgtitlet
+            ret['epgduplicate'] = epgduplicatet
+            ret['epgchange'] = epgchanget
+            if deltatime == None or deltatime == "":
+                deltatime = "3"
+            if deltaday == None or deltaday == "":
+                deltaday = "7"
+            if typet == recdblist.REC_KEYWORD:
+                ret['deltatime'] = deltatime
+            elif typet == recdblist.REC_KEYWORD_EVERY_SOME_DAYS:
+                ret['deltatime'] = deltatime
+                ret['deltaday'] = deltaday
+            try:
+                ret['counter'] = int(countert)
+            except:
+                ret['counter']=-1
+            recdatum.append(ret)
+        return recdatum
+    def delete_old_timeline(self, dhour):
+        db = self.connect_db()
+        db[1].execute("\
+        DELETE FROM timeline \
+        WHERE \
+        btime < DATE_SUB(now(),INTERVAL " + dhour + " HOUR )")
+        #db.commit()
+        self.close_db(db)
+    def new_in_auto_jbk_key(self):
+        db = self.connect_db()
+        try:
+            db[1].execute("\
+            CREATE TABLE in_auto_jbk_key \
+            (\
+            id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,\
+            keyword VARCHAR(200),\
+            auto TINYINT DEFAULT 0,\
+            opt VARCHAR(20),\
+            UNIQUE unijbk (keyword)\
+            )")
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_in_auto_jbk_key (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        self.close_db(db)
+    def add_in_auto_jbk_key(self,key):
+        db = self.connect_db()
+        db[1].execute('\
+        INSERT IGNORE into in_auto_jbk_key \
+        (keyword) \
+        values (%s)', \
+                      (key,))
+        ##db.commit()
+        self.close_db(db)
+    def select_all_in_auto_jbk_key(self):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT keyword,auto,opt \
+        FROM in_auto_jbk_key \
+vim         ")
+        ret = []
+        if dbexe > 0:
+            ret = db[1].fetchall()
+        self.close_db(db)
+        return ret
+    def drop_in_status(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('drop table in_status')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and (inst[0]==1050 or inst[0]==1051))):
+                recdblist.addCommonlogEX("Error", "drop_in_status (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        self.close_db(db)
+    def new_in_status(self):
+        db = self.connect_db()
+        try:
+            db[1].execute("\
+            CREATE TABLE in_status \
+            (\
+            ts2avi TINYINT DEFAULT 0,\
+            terec TINYINT DEFAULT 0,\
+            bscsrec TINYINT DEFAULT 0,\
+            b252ts TINYINT DEFAULT 0,\
+            installed TINYINT DEFAULT 0,\
+            version TINYINT\
+            )")
+            db[1].execute("INSERT IGNORE into in_status VALUE (0,0,0,0,0,0)")
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_in_status (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        self.close_db(db)
+    def select_all_in_status(self):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT ts2avi,terec,bscsrec,b252ts \
+        FROM in_status \
+        ")
+        ret = []
+        dls = []
+        if dbexe > 0:
+            dls = db[1].fetchall()
+        self.close_db(db)
+        for dl in dls:
+            r = list(dl)
+            r[0]=str(r[0])
+            r[1]=str(r[1])
+            r[2]=str(r[2])
+            r[3]=str(r[3])
+            ret.append(r)
+        return ret
+    def select_version_in_status(self):
+        db = self.connect_db()
+        version=0
+        try:
+            dbexe = db[1].execute("\
+            SELECT version \
+            FROM in_status \
+            ")
+            if dbexe > 0:
+                dls = db[1].fetchall()
+            self.close_db(db)
+            for dl in dls:
+                r = list(dl)
+                version=int(str(r[0]))
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "select_version_in_status (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        return version
+    def change_version_in_status(self,version):
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE in_status SET version=%s",str(version))
+        self.close_db(db)
+    def change_ts2avi_in_status(self,i):
+        """
+        statuをiだけ増減する
+        iはint
+        """
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE in_status SET ts2avi=ts2avi+%s",i)
+        self.close_db(db)
+    def change_terec_in_status(self,i):
+        """
+        statuをiだけ増減する
+        iはint
+        """
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE in_status SET terec=terec+%s",i)
+        self.close_db(db)
+    def change_bscsrec_in_status(self,i):
+        """
+        statuをiだけ増減する
+        iはint
+        """
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE in_status SET bscsrec=bscsrec+%s",i)
+        self.close_db(db)
+    def change_b252ts_in_status(self,i):
+        """
+        statuをiだけ増減する
+        iはint
+        """
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE in_status SET b252ts=b252ts+%s",i)
+        self.close_db(db)
+    def select_installed_in_status(self):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT ts2avi,terec,bscsrec,b252ts,installed \
+        FROM in_status \
+        ")
+        ret = 0
+        dls = []
+        if dbexe > 0:
+            dls = db[1].fetchall()
+        self.close_db(db)
+        for dl in dls:
+            r = list(dl)
+            ret=r[4]
+        return ret
+    def change_chscaned_in_status(self):
+        """
+        installedを設定する
+        """
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE in_status SET installed=2")
+        self.close_db(db)
+    def change_installed_in_status(self,num=1):
+        """
+        installedを設定する
+        """
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE in_status SET installed=%s",(num,))
+        self.close_db(db)
+    def new_epg_timeline(self, bctype):
+        db = self.connect_db()
+        try:
+            db[1].execute("\
+            DELETE FROM epg_timeline \
+            WHERE bctype = %s", \
+                          (bctype,))
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and (inst[0]==1007 or inst[0]==1146))or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_epg_timeline delete (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        try:
+            db[1].execute("\
+            CREATE TABLE epg_timeline \
+            (\
+            bctype VARCHAR(20),\
+            channel VARCHAR(100) NOT NULL,\
+            start VARCHAR(30),\
+            stop  VARCHAR(30),\
+            title VARCHAR(100),\
+            exp VARCHAR(200),\
+            longexp TEXT,\
+            category VARCHAR(100),\
+            UNIQUE unitv(bctype,channel,start,stop,title)\
+            )")
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_epg_timeline (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        #db.commit()
+        self.close_db(db)
+    def add_epg_timeline(self, bctype, channel, start, stop, title, desc,longdesc, category):
+        db = self.connect_db()
+        db[1].execute('\
+        INSERT IGNORE INTO epg_timeline \
+        VALUES (%s,%s,%s,%s,%s,%s,%s,%s)', \
+                      (bctype, channel, start, stop, title, desc,longdesc,category))
+        #db.commit()
+        self.close_db(db)
+    def add_multi_epg_timeline(self, tvlists):
+        """
+        tvlists is (bctype,channel,start,stop,title,desc,longdesc,category) lists.
+        """
+        db = self.connect_db()
+        db[1].executemany('\
+        INSERT IGNORE INTO epg_timeline \
+        (bctype,channel,start,stop,title,exp,longexp,category) \
+        values(%s,%s,%s,%s,%s,%s,%s,%s)', \
+                          tvlists)
+        self.close_db(db)
+    def select_by_time_ngram_epg_timeline(self, btime, etime, chtxt):
+        db = self.connect_db()
+        dbexe = "\
+        SELECT \
+        channel,title,start,stop,exp,longexp,category \
+        FROM epg_timeline \
+        WHERE start >= %s \
+        AND \
+        start <= %s \
+        AND \
+        channel LIKE %s"
+        dbcmd = db[1].execute(dbexe, (btime, etime, chtxt))
+        retall = []
+        if dbcmd > 0:
+            retall = db[1].fetchall()
+        self.close_db(db)
+        return retall
+    def select_by_time_keyword_auto_suggest_epg_timeline(self,keyword,btime,etime):
+        db = self.connect_db()
+        dbexe = "\
+        SELECT \
+        epg_ch.chtxt,title,start,stop,exp,longexp,category \
+        FROM epg_timeline \
+        INNER JOIN epg_ch \
+        WHERE epg_ch.chtxt=epg_timeline.channel \
+        AND \
+        epg_ch.visible=1 \
+        AND \
+        start >= %s \
+        AND \
+        stop <= %s \
+        AND \
+        ( \
+        ( title LIKE \'%%"+keyword+"%%\' ) \
+        OR \
+        ( exp LIKE \'%%"+keyword+"%%\' ) \
+        OR \
+        ( longexp LIKE \'%%"+keyword+"%%\' ) \
+        )"
+        dbcmd = db[1].execute(dbexe,(btime, etime))
+        retall = []
+        if dbcmd > 0:
+            retall = db[1].fetchall()
+        self.close_db(db)
+        return retall
+    def new_in_auto_bayes_key(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('CREATE TABLE in_auto_bayes_key \
+            (\
+            keychar VARCHAR(10),\
+            chtxt VARCHAR(20),\
+            ratio_rec DECIMAL(32,14),\
+            ratio_all DECIMAL(32,14),\
+            UNIQUE unibayeskey(keychar,chtxt)\
+            )')
+            db[1].execute('CREATE INDEX keycharindex ON in_auto_bayes_key(keychar)')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_in_auto_bayes_key (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        self.close_db(db)
+
+    def add_in_auto_bayes_key(self,key,chtxt,ratio_rec,ratio_all):
+        db = self.connect_db()
+        ratio_rec=str(ratio_rec)
+        ratio_all=str(ratio_all)
+        db[1].execute('\
+        INSERT IGNORE INTO in_auto_bayes_key \
+        (keychar,chtxt,ratio_rec,ratio_all) \
+        values (%s,%s,%s,%s)',\
+        (key,chtxt,ratio_rec,ratio_all))
+        self.close_db(db)
+    def add_num_in_auto_bayes_key(self,chtxt,add_rec_num,add_all_num):
+        db = self.connect_db()
+        add_rec_num=str(add_rec_num)
+        add_all_num=str(add_all_num)
+        db[1].execute("\
+        UPDATE in_auto_bayes_key SET ratio_rec=CONVERT(ratio_rec+%s,DECIMAL(32,14)),ratio_all=CONVERT(ratio_all+%s,DECIMAL(32,14)) WHERE keychar=\"NUM\" AND chtxt=%s",\
+        (add_rec_num,add_all_num,chtxt))
+        self.close_db(db)
+    def change_in_auto_bayes_key(self,key,chtxt,new_ratio_rec,new_ratio_all):
+        """
+        """
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE in_auto_bayes_key SET ratio_rec=%s,ratio_all=%s WHERE keychar=%s AND chtxt=%s",(str(new_ratio_rec),str(new_ratio_all),key,chtxt)\
+        )
+        self.close_db(db)
+    def change_ratio_all_reduce_in_auto_bayes_key(self,chtxt,beforenum,newnum):
+        beforenum=str(beforenum)
+        newnum=str(newnum)
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE in_auto_bayes_key SET ratio_all=CONVERT(ratio_all*%s/(%s+%s),DECIMAL(32,14)) WHERE chtxt=%s AND NOT (keychar=\"NUM\")",(beforenum,newnum,beforenum,chtxt)\
+        )
+        self.close_db(db)
+    def change_ratio_all_in_auto_bayes_key(self,key,chtxt,beforenum,addnum):
+        db = self.connect_db()
+        beforenumf=beforenum
+        beforenum=str(beforenum)
+        db[1].execute("INSERT INTO in_auto_bayes_key (keychar,chtxt,ratio_rec,ratio_all) \
+        VALUES (%s,%s,%s,%s)\
+        ON DUPLICATE KEY UPDATE \
+        ratio_all=CONVERT((ratio_all*%s+%s)/%s,DECIMAL(32,14))",(key,chtxt,"0",str(Decimal(addnum)/beforenumf),beforenum,chtxt,key))
+        self.close_db(db)
+    def change_multi_ratio_all_in_auto_bayes_key(self,chtxt,beforenum,list):
+        """
+        list={key:addnum}のリスト
+        """
+        beforenumf=beforenum
+        beforenum=str(beforenum)
+        db = self.connect_db()
+        for i,j in list.items():
+            retl=(i,chtxt,"0",str(Decimal(j)/beforenumf),beforenum,str(j),beforenum)
+            try:
+                db[1].execute("INSERT INTO in_auto_bayes_key (keychar,chtxt,ratio_rec,ratio_all) \
+                VALUES (%s,%s,%s,%s)\
+                ON DUPLICATE KEY UPDATE \
+                ratio_all=CONVERT((ratio_all*%s+%s)/%s,DECIMAL(32,14))",retl)
+            except Exception, inst:
+                if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                    recdblist.addCommonlogEX("Error", "change_multi_ratio_all_in_auto_bayes_key (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        self.close_db(db)
+    def change_ratio_rec_reduce_in_auto_bayes_key(self,chtxt,beforenum,newnum):
+        beforenum=str(beforenum)
+        newnum=str(newnum)
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE in_auto_bayes_key SET ratio_rec=CONVERT(ratio_rec*%s/(%s+%s),DECIMAL(32,14)) WHERE chtxt=%s AND NOT (keychar=\"NUM\")",(beforenum,newnum,beforenum,chtxt)\
+        )
+        self.close_db(db)
+    def change_ratio_rec_in_auto_bayes_key(self,key,chtxt,beforenum,addnum):
+        db = self.connect_db()
+        beforenumf=beforenum
+        beforenum=str(beforenum)
+        db[1].execute("INSERT INTO in_auto_bayes_key (keychar,chtxt,ratio_rec,ratio_all) \
+        VALUES (%s,%s,%s,%s)\
+        ON DUPLICATE KEY UPDATE \
+        ratio_rec=CONVERT((ratio_rec*%s+%s)/%s,DECIMAL(32,14))",(key,chtxt,str(Decimal(addnum)/beforenumf),"0",beforenum,chtxt,key))
+        self.close_db(db)
+    def change_multi_ratio_rec_in_auto_bayes_key(self,chtxt,beforenum,list):#self,key,chtxt,beforenum,addnum):
+        beforenumf=beforenum
+        beforenum=str(beforenum)
+        db = self.connect_db()
+        for i,j in list.items():
+            retl=(i,chtxt,str(Decimal(j)/beforenumf),"0",beforenum,str(j),beforenum)
+            try:
+                db[1].execute("INSERT INTO in_auto_bayes_key (keychar,chtxt,ratio_rec,ratio_all) \
+                VALUES (%s,%s,%s,%s)\
+                ON DUPLICATE KEY UPDATE \
+                ratio_rec=CONVERT((ratio_rec*%s+%s)/%s,DECIMAL(32,14))",retl)
+            except Exception, inst:
+                if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                    recdblist.addCommonlogEX("Error", "change_multi_ratio_rec_in_auto_bayes_key (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        self.close_db(db)
+    def select_by_key_in_auto_bayes_key(self,key,chtxt):
+        db = self.connect_db()
+        dbexe = db[1].execute("\
+        SELECT keychar,chtxt,ratio_rec,ratio_all \
+        FROM in_auto_bayes_key \
+        WHERE keychar = %s AND chtxt = %s", \
+                              (key,chtxt))
+        dls = []
+        if dbexe > 0:
+            dls = db[1].fetchall()
+        self.close_db(db)
+        if len(dls)>0:
+            return dls[0]
+        else:
+            return dls
+    def new_auto_timeline_keyword(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('\
+            CREATE TABLE auto_timeline_keyword \
+            (\
+            id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,\
+            chtxt VARCHAR(40),\
+            title VARCHAR(100),\
+            btime DATETIME,\
+            etime DATETIME,\
+            UNIQUE uni (chtxt,title,btime,etime)\
+            )')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_auto_timeline_keyword (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+    def add_auto_timeline_keyword(self,chtxt="", title="", btime="", etime=""):
+        db = self.connect_db()
+        db[1].execute('\
+        INSERT IGNORE into auto_timeline_keyword \
+        (chtxt,title,btime,etime) \
+        values (%s,%s,%s,%s)', \
+                       (chtxt, title, btime, etime))
+        ##db.commit()
+        self.close_db(db)
+    def delete_old_auto_timeline_keyword(self, dhour):
+        db = self.connect_db()
+        db[1].execute("\
+        DELETE FROM auto_timeline_keyword \
+        WHERE \
+        btime < DATE_SUB(now(),INTERVAL " + dhour + " HOUR )")
+        self.close_db(db)
+    def new_auto_timeline_bayes(self):
+        db = self.connect_db()
+        try:
+            db[1].execute('\
+            CREATE TABLE auto_timeline_bayes \
+            (\
+            id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,\
+            chtxt VARCHAR(40),\
+            title VARCHAR(100),\
+            btime DATETIME,\
+            etime DATETIME,\
+            point INT,\
+            UNIQUE uni (chtxt,title,btime,etime)\
+            )')
+        except Exception, inst:
+            if not ((type(inst)==MySQLdb.ProgrammingError and inst[0]==1007)or(type(inst)==MySQLdb.OperationalError and inst[0]==1050)):
+                recdblist.addCommonlogEX("Error", "new_auto_timeline_bayes (dbMySQL.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+    def add_auto_timeline_bayes(self,chtxt="", title="", btime="", etime="",point=""):
+        db = self.connect_db()
+        db[1].execute('\
+        INSERT IGNORE into auto_timeline_bayes \
+        (chtxt,title,btime,etime,point) \
+        values (%s,%s,%s,%s,%s)', \
+                      (chtxt, title, btime, etime,point))
+        self.close_db(db)
+    def delete_old_auto_timeline_bayes(self, dhour):
+        db = self.connect_db()
+        db[1].execute("\
+        DELETE FROM auto_timeline_bayes \
+        WHERE \
+        btime < DATE_SUB(now(),INTERVAL " + dhour + " HOUR )")
+        self.close_db(db)
+    def update_db_to93(self):
+        db = self.connect_db()
+        self.drop_in_settings()
+        self.new_in_settings()
+        db[1].execute("\
+        ALTER TABLE timeline ADD epgtitle VARCHAR(100),\
+        ADD epgbtime DATETIME,\
+        ADD epgetime DATETIME,\
+        ADD epgduplicate TINYINT DEFAULT 0,\
+        ADD epgchange TINYINT DEFAULT 0")
+        db[1].execute("\
+        ALTER TABLE in_status ADD version TINYINT")
+        self.close_db(db)
+        self.change_version_in_status("93")
+    def update_db_93to94(self):
+        db = self.connect_db()
+        self.drop_in_settings()
+        self.new_in_settings()
+        db[1].execute("\
+        ALTER TABLE timeline ADD counter TINYINT DEFAULT -1")
+        self.close_db(db)
+        self.change_version_in_status("94")
+    def update_db_94to95(self):
+        db = self.connect_db()
+        self.drop_in_settings()
+        self.new_in_settings()
+        db[1].execute("\
+        ALTER TABLE timeline ADD epgexp VARCHAR(200)")
+        self.close_db(db)
+        self.change_version_in_status("95")
+    def update_db_95to96(self):
+        db = self.connect_db()
+        self.drop_in_settings()
+        self.new_in_settings()
+        self.close_db(db)
+        self.change_version_in_status("96")
+    def update_db_96to98(self):
+        db = self.connect_db()
+        self.drop_in_settings()
+        self.new_in_settings()
+        self.close_db(db)
+        self.change_version_in_status("98")
+    def update_db_98to100(self):
+        ###ここで前のepg_chをバックアップしてchtxtの変換をする必要がある。
+        self.drop_in_settings()
+        self.new_in_settings()
+        db = self.connect_db()
+        db[1].execute("\
+        UPDATE timeline INNER JOIN epg_ch ON timeline.chtxt=epg_ch.chtxt SET timeline.chtxt=CONCAT(CONCAT(epg_ch.ch,'_'),epg_ch.csch) WHERE NOT (substring(epg_ch.bctype,1,2) = 'bs' OR substring(epg_ch.bctype,1,2) = 'cs')")
+        db[1].execute("\
+        UPDATE timeline INNER JOIN epg_ch ON timeline.chtxt=epg_ch.chtxt SET timeline.chtxt=CONCAT('BS_',epg_ch.ch) WHERE substring(epg_ch.bctype,1,2) = 'bs'")
+        db[1].execute("\
+        UPDATE timeline INNER JOIN epg_ch ON timeline.chtxt=epg_ch.chtxt SET timeline.chtxt=CONCAT('CS_',epg_ch.csch) WHERE substring(epg_ch.bctype,1,2) = 'cs'")
+        try:
+            db[1].execute("\
+            ALTER TABLE epg_ch DROP ontv")
+        except:
+            ""
+        db[1].execute("\
+        ALTER TABLE epg_ch ADD logo0 BLOB,\
+        ADD logo1 BLOB,\
+        ADD logo2 BLOB,\
+        ADD logo3 BLOB,\
+        ADD logo4 BLOB,\
+        ADD logo5 BLOB\
+        ")
+        db[1].execute("\
+        ALTER TABLE in_auto_jbk_key ADD auto TINYINT DEFAULT 0")
+        db[1].execute("\
+        ALTER TABLE in_auto_jbk_key ADD opt VARCHAR(20) DEFAULT \"\"")
+        self.close_db(db)
+        self.change_installed_in_status(1)#チャンネルスキャンをさせる
+        self.change_version_in_status("100")
+    def update_db_100to101(self):
+        self.drop_in_settings()
+        self.new_in_settings()
+        self.new_epg_ch()
+        db = self.connect_db()
+        try:
+            db[1].execute("\
+            ALTER TABLE timeline ADD epgcategory VARCHAR(100)\
+            ")
+        except:
+            ""
+        self.close_db(db)
+        self.change_installed_in_status(1)
+        self.change_version_in_status("101")
+        #self.change_installed_in_status()#チャンネルスキャンをさせる
+        
diff --git a/dist/trunk/rec10/epgdb.py b/dist/trunk/rec10/epgdb.py
new file mode 100755 (executable)
index 0000000..f0bfaf6
--- /dev/null
@@ -0,0 +1,277 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import datetime\r
+import os\r
+import shutil\r
+import time\r
+import os.path\r
+import traceback\r
+\r
+import chdb\r
+import n_gram\r
+import rec10d\r
+import ts2epg\r
+import xml2db_dom\r
+import configreader\r
+import recdblist\r
+path = str(os.path.dirname(os.path.abspath(__file__))) + "/"\r
+tmppath = configreader.getConfPath("tmp")+"/"\r
+if tmppath=="/":\r
+    tmppath=path\r
+if not os.path.exists(tmppath):\r
+    os.mkdir(tmppath)\r
+def update(chtxt):\r
+    recdblist.printutf8(chtxt)\r
+    tnow = datetime.datetime.now()\r
+    try:\r
+        lastup = datetime.datetime.strptime(chdb.searchCHFromChtxt(chtxt)[0]['update'], "%Y-%m-%d %H:%M:%S")\r
+    except:\r
+        lastup = datetime.datetime.strptime("2009-04-01 00:00:00", "%Y-%m-%d %H:%M:%S")\r
+    dt = tnow-lastup\r
+    dt = dt.days * 24 * 60 + dt.seconds\r
+    if dt > 2 * 60 * 60:\r
+        ts2epg.writeEpgXML(os.path.join(tmppath, chtxt + "epgdata.xml"), chdb.searchCHFromChtxt(chtxt)['ch'])\r
+        xml2db_dom.xml2db_dom(os.path.join(tmppath, chtxt + "epgdata.xml"), chdb.searchCHFromChtxt(chtxt)['bctype'])\r
+def updatebc(bctype):\r
+    bctypel = chdb.searchCHFromBctype(bctype)\r
+    #print bctype\r
+    try:\r
+        ts2epg.writeEpgXML(tmppath + bctype + "epgdata.xml", chdb.searchCHFromBctype(bctype)['ch'])\r
+        xml2db_dom.xml2db_dom(tmppath + bctype + "epgdata.xml", bctype)\r
+        shutil.copyfile(tmppath + bctype + "epgdata.xml", tmppath + bctype + "epgdata.bak.xml")\r
+        time.sleep(5)\r
+        rec10d.rec10db.update_by_bctype_epg_ch(bctype)\r
+    except Exception, inst:\r
+        recdblist.addCommonlogEX("Error","updatebc(epgdb.py)", str(type(inst)), str(inst)+"\n"+traceback.format_exc(),log_level=200)\r
+        xml2db_dom.xml2db_dom(tmppath + bctype + "epgdata.bak.xml", bctype)\r
+        rec10d.rec10db.update_status_by_bctype_epg_ch(bctype, "2")\r
+def updateLogo_bc(bctype):\r
+    bctypel = chdb.searchCHFromBctype(bctype)\r
+    #print bctype\r
+    try:\r
+        ts2epg.writeLogoEpgXML(tmppath + bctype + "logo.xml", chdb.searchCHFromBctype(bctype)['ch'])\r
+        xml2db_dom.xml2db_dom_logo(tmppath + bctype + "logo.xml", bctype)\r
+        shutil.copyfile(tmppath + bctype + "logo.xml", tmppath + bctype + "logo.bak.xml")\r
+        time.sleep(5)\r
+        rec10d.rec10db.update_logostatus_by_bctype_epg_ch(bctype,"1")\r
+    except Exception, inst:\r
+        recdblist.addCommonlogEX("Error","updatebc(epgdb.py)", str(type(inst)), str(inst)+"\n"+traceback.format_exc(),log_level=200)\r
+        xml2db_dom.xml2db_dom(tmppath + bctype + "logo.bak.xml", bctype)\r
+        rec10d.rec10db.update_logostatus_by_bctype_epg_ch(bctype,"2")\r
+def searchTime(titletxt, timet, deltatime, chtxt):\r
+    time = datetime.datetime.strptime(timet, "%Y-%m-%d %H:%M:%S")\r
+    ret = []\r
+    deltatime = int(deltatime)\r
+    beforetime = time.strftime("%Y%m%d%H%M%S")\r
+    beforetime = time - datetime.timedelta(hours=deltatime)\r
+    aftertime = time + datetime.timedelta(hours=deltatime)\r
+    beforetime = beforetime.strftime("%Y%m%d%H%M%S")\r
+    aftertime = aftertime.strftime("%Y%m%d%H%M%S")\r
+    one = ["", "", "", "","","",""]\r
+    tempt = 0\r
+    chtxtt=chtxt.replace("_0","_%")\r
+    d = rec10d.rec10db.select_by_time_ngram_epg_timeline(beforetime, aftertime, chtxtt)\r
+    for chtxtt, title, start, stop ,exp,longexp,category in d:\r
+        #recdblist.printutf8(chtxtt+":"+title+":"+start+":"+stop)\r
+        p = n_gram.bigram(titletxt, title)\r
+        btime = start\r
+        btime = btime[0:4] + "-" + btime[4:6] + "-" + btime[6:8] + " " + btime[8:10] + ":" + btime[10:12] + ":00"\r
+        etime = stop\r
+        etime = etime[0:4] + "-" + etime[4:6] + "-" + etime[6:8] + " " + etime[8:10] + ":" + etime[10:12] + ":00"\r
+        bt = datetime.datetime.strptime(btime, "%Y-%m-%d %H:%M:%S")\r
+        dt = bt-time\r
+        dt = abs(dt)\r
+        dt = 24 * 60 * 60 * dt.days + dt.seconds + 1\r
+        p = p * 90\r
+        dt = 1000-1000 * dt / (7 * 24 * 60 * 60)\r
+        if p > 0:\r
+            p = p + dt\r
+        if p > tempt:\r
+            one = [chtxtt, title, btime, etime,exp,longexp,category]\r
+            tempt = p\r
+        if p > 0:\r
+            #recdblist.printutf8(title + ":" + str(p) + u"点")\r
+            ""\r
+    ret = one\r
+    #print ret\r
+    return ret\r
+def searchTimeAuto(keytxt, timet, deltatime):\r
+    time = datetime.datetime.strptime(timet, "%Y-%m-%d %H:%M:%S")\r
+    ret = []\r
+    deltatime = int(deltatime)\r
+    beforetime = time.strftime("%Y%m%d%H%M%S")\r
+    aftertime = time + datetime.timedelta(hours=deltatime)\r
+    aftertime = aftertime.strftime("%Y%m%d%H%M%S")\r
+    d = rec10d.rec10db.select_by_time_keyword_auto_suggest_epg_timeline(keytxt,beforetime, aftertime)\r
+    for chtxtt, title, start, stop ,exp,longexp,category in d:\r
+        btime = start\r
+        btime = btime[0:4] + "-" + btime[4:6] + "-" + btime[6:8] + " " + btime[8:10] + ":" + btime[10:12] + ":00"\r
+        etime = stop\r
+        etime = etime[0:4] + "-" + etime[4:6] + "-" + etime[6:8] + " " + etime[8:10] + ":" + etime[10:12] + ":00"\r
+        ret.append([chtxtt, title, btime, etime,exp,longexp,category])\r
+    return ret\r
+def countSchedule(btime,etime):\r
+    """\r
+    return rec num (int return[0]:TE /int return[1]:BS/CS)\r
+    """\r
+    def cmpare(x, y):\r
+        xt = x\r
+        yt = y\r
+        if xt > yt:\r
+            return -1\r
+        elif xt == yt:\r
+            return 0\r
+        else:\r
+            return 1\r
+    dls = rec10d.rec10db.select_bytime_all_timeline(btime, etime)\r
+    times = []\r
+    btd = datetime.datetime.strptime(btime, "%Y-%m-%d %H:%M:%S")\r
+    etd = datetime.datetime.strptime(etime, "%Y-%m-%d %H:%M:%S")\r
+    for dl in dls:\r
+        dd1 = datetime.datetime.strptime(dl['btime'], "%Y-%m-%d %H:%M:%S")\r
+        dd2 = datetime.datetime.strptime(dl['etime'], "%Y-%m-%d %H:%M:%S")\r
+        if dd1 < btd:\r
+            dd1 = btd\r
+        if dd2 > etd:\r
+            dd2 = etd\r
+        times.append(dd1)\r
+        times.append(dd2)\r
+    times = list(set(times))\r
+    times.sort(cmpare)\r
+    times.reverse()\r
+    retcount = [0, 0]\r
+    for i in xrange(0, len(times)-2, 1):\r
+        bt1 = times[i]\r
+        et1 = times[i + 1]\r
+        btime1 = bt1.strftime("%Y-%m-%d %H:%M:%S")\r
+        etime1 = et1.strftime("%Y-%m-%d %H:%M:%S")\r
+        ret1 = rec10d.rec10db.count_schedule_timeline(btime1, etime1)\r
+        if retcount[0] < ret1[0]:\r
+            retcount[0] = ret1[0]\r
+        if retcount[1] < ret1[1]:\r
+            retcount[1] = ret1[1]\r
+    return retcount\r
+\r
+def searchSchedule(btime,etime):\r
+    """\r
+    return rec num (int return[0]:TE /int return[1]:BS/CS)\r
+    """\r
+    def cmpare(x, y):\r
+        xt = x\r
+        yt = y\r
+        if xt > yt:\r
+            return -1\r
+        elif xt == yt:\r
+            return 0\r
+        else:\r
+            return 1\r
+    dls = rec10d.rec10db.select_bytime_all_timeline(btime, etime)\r
+    times = []\r
+    btd = datetime.datetime.strptime(btime, "%Y-%m-%d %H:%M:%S")\r
+    etd = datetime.datetime.strptime(etime, "%Y-%m-%d %H:%M:%S")\r
+    for dl in dls:\r
+        dd1 = datetime.datetime.strptime(dl['btime'], "%Y-%m-%d %H:%M:%S")\r
+        dd2 = datetime.datetime.strptime(dl['etime'], "%Y-%m-%d %H:%M:%S")\r
+        if dd1 < btd:\r
+            dd1 = btd\r
+        if dd2 > etd:\r
+            dd2 = etd\r
+        times.append(dd1)\r
+        times.append(dd2)\r
+    times = list(set(times))\r
+    times.sort(cmpare)\r
+    times.reverse()\r
+    ret=[]\r
+    for i in xrange(0, len(times)-2, 1):\r
+        bt1 = times[i]\r
+        et1 = times[i + 1]\r
+        btime1 = bt1.strftime("%Y-%m-%d %H:%M:%S")\r
+        etime1 = et1.strftime("%Y-%m-%d %H:%M:%S")\r
+        ret1 = rec10d.rec10db.search_schedule_timeline(btime1, etime1)\r
+        ret.append(ret1)\r
+    ret = list(set(ret))\r
+    return ret\r
+\r
+def countEpgSchedule(epgbtime,epgetime):\r
+    """\r
+    return rec num (int return[0]:TE /int return[1]:BS/CS)\r
+    """\r
+    def cmpare(x, y):\r
+        xt = x\r
+        yt = y\r
+        if xt > yt:\r
+            return -1\r
+        elif xt == yt:\r
+            return 0\r
+        else:\r
+            return 1\r
+    dls = rec10d.rec10db.select_byepgtime_over_timeline(epgbtime, epgetime)\r
+    #print dls\r
+    times = []\r
+    btd = datetime.datetime.strptime(epgbtime, "%Y-%m-%d %H:%M:%S")\r
+    etd = datetime.datetime.strptime(epgetime, "%Y-%m-%d %H:%M:%S")\r
+    for dl in dls:\r
+        dd1 = datetime.datetime.strptime(dl['epgbtime'], "%Y-%m-%d %H:%M:%S")\r
+        dd2 = datetime.datetime.strptime(dl['epgetime'], "%Y-%m-%d %H:%M:%S")\r
+        if dd1 < btd:\r
+            dd1 = btd\r
+        if dd2 > etd:\r
+            dd2 = etd\r
+        times.append(dd1)\r
+        times.append(dd2)\r
+    times = list(set(times))\r
+    times.sort(cmpare)\r
+    times.reverse()\r
+    retcount = [0, 0]\r
+    for i in xrange(0, len(times)-1, 1):\r
+        bt1 = times[i]\r
+        et1 = times[i + 1]\r
+        epgbtime1 = bt1.strftime("%Y-%m-%d %H:%M:%S")\r
+        epgetime1 = et1.strftime("%Y-%m-%d %H:%M:%S")\r
+        ret1 = rec10d.rec10db.count_epgschedule_timeline(epgbtime1, epgetime1)\r
+        if retcount[0] < ret1[0]:\r
+            retcount[0] = ret1[0]\r
+        if retcount[1] < ret1[1]:\r
+            retcount[1] = ret1[1]\r
+    return retcount\r
+def searchEpgSchedule(epgbtime,epgetime):\r
+    """\r
+    return rec num (int return[0]:TE /int return[1]:BS/CS)\r
+    """\r
+    def cmpare(x, y):\r
+        xt = x\r
+        yt = y\r
+        if xt > yt:\r
+            return -1\r
+        elif xt == yt:\r
+            return 0\r
+        else:\r
+            return 1\r
+    dls = rec10d.rec10db.select_byepgtime_all_timeline(epgbtime, epgetime)\r
+    times = []\r
+    btd = datetime.datetime.strptime(epgbtime, "%Y-%m-%d %H:%M:%S")\r
+    etd = datetime.datetime.strptime(epgetime, "%Y-%m-%d %H:%M:%S")\r
+    for dl in dls:\r
+        dd1 = datetime.datetime.strptime(dl['epgbtime'], "%Y-%m-%d %H:%M:%S")\r
+        dd2 = datetime.datetime.strptime(dl['epgetime'], "%Y-%m-%d %H:%M:%S")\r
+        if dd1 < btd:\r
+            dd1 = btd\r
+        if dd2 > etd:\r
+            dd2 = etd\r
+        times.append(dd1)\r
+        times.append(dd2)\r
+    times = list(set(times))\r
+    times.sort(cmpare)\r
+    times.reverse()\r
+    ret=[]\r
+    for i in xrange(0, len(times)-2, 1):\r
+        bt1 = times[i]\r
+        et1 = times[i + 1]\r
+        epgbtime1 = bt1.strftime("%Y-%m-%d %H:%M:%S")\r
+        epgetime1 = et1.strftime("%Y-%m-%d %H:%M:%S")\r
+        ret1 = rec10d.rec10db.search_epgschedule_timeline(epgbtime1, epgetime1)\r
+        ret.append(ret1)\r
+    ret = list(set(ret))\r
+    return ret\r
diff --git a/dist/trunk/rec10/epgrefresh.py b/dist/trunk/rec10/epgrefresh.py
new file mode 100755 (executable)
index 0000000..523bdfc
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+import os
+import sys
+import time
+
+import chdb
+import epgdb
+import recdblist
+
+update = chdb.update()
+if len(update) > 0:
+    #recdblist.printutf8(u"番組表を更新")
+    #print update
+    pid = os.fork()
+    if pid > 0:#親プロセスの場合
+        ""
+    else:#子プロセスの場合 アップデートを行って終了
+        for bctype in update:
+            time.sleep(1)
+            epgdb.updatebc(bctype)
+        sys.exit(0)
\ No newline at end of file
diff --git a/dist/trunk/rec10/guess.py b/dist/trunk/rec10/guess.py
new file mode 100755 (executable)
index 0000000..cad73e1
--- /dev/null
@@ -0,0 +1,240 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+
+import os
+import os.path
+import re
+import time
+import os
+import datetime
+import n_gram
+import recdblist
+import zenhan
+import auto_move
+
+def detSeriesNum(execpath):
+    files=os.listdir(execpath)
+    ss={}
+    for file in files:
+        ftitle=os.path.splitext(file)
+        fname=ftitle[0]
+        fname=zenhan.toHankaku(unicode(fname,"utf-8"))
+        nt=detNameType(fname, execpath)
+        st=nt['title']
+        if not ss.has_key(st):
+            ss[st]={}
+        ss[st][nt['num']]=ftitle
+        print ss
+    return ss
+def detDeltaNum(title,movepath):
+    """
+        #番組の話数を推測する。
+    """
+    files=os.listdir(movepath)
+    ff=[]
+    maxnum=0
+    for file in files:
+        recdblist.printutf8(unicode(file,'utf-8'),verbose_level=800)
+        file=os.path.join(movepath,file)
+        if os.path.isfile(file):
+            name=os.path.splitext(os.path.split(file)[1])
+            name=name[0]
+            name=zenhan.toHankaku(unicode(name,'utf-8'))
+            p1=detNameType(name,movepath)
+            #recdblist.printutf8(p1['title']+" "+str(p1['num']))
+            time1=time.localtime(os.path.getmtime(file))
+            time1=datetime.datetime.fromtimestamp(os.path.getmtime(file))
+            if p1['num']!=-1:
+                ff.append([p1['num'],p1['title'],time1])
+                if maxnum<p1['num']+1:
+                    maxnum=p1['num']+1
+    return detMultiDeltaDays(ff)
+def detMultiDeltaDays(num_with_title_with_dates):
+    maxnum=0
+    for ft in num_with_title_with_dates:
+        if maxnum<ft[0]+1:
+            maxnum=ft[0]+1
+    ff=num_with_title_with_dates
+    f3=[None]*maxnum
+    fret={}
+    for i in range(0, maxnum, 1):
+        f3[i]=[]
+    for f2 in ff:
+        f3[f2[0]].append(f2)
+    for i in range(maxnum):
+        for j in range(i+1,maxnum,1):
+            for ft3 in f3[i]:
+                for ft4 in f3[j]:
+                    for gdd in detSingleDeltaDay(i, ft3[2], j, ft4[2]):
+                        #print gdd
+                        if fret.get(gdd[0])!=None:
+                            #print fret
+                            fret[gdd[0]]=fret[gdd[0]]+gdd[1]
+                        else:
+                            fret[gdd[0]]=gdd[1]
+    #print fret
+    maxk=0
+    maxp=0
+    for i in range(maxnum):
+        if fret.get(i)!=None:
+            if maxp<fret[i]:
+                maxk=i
+                maxp=fret[i]
+    #print maxk
+    #print maxp
+    return maxk
+def detSingleDeltaDay(num1,date1,num2,date2):
+    dd=date1-date2
+    if date1<date2:
+        dd=date2-date1
+    dn=dd.days
+    d=num2-num1
+    if d<0:
+        d=-1*d
+    dp=dd+datetime.timedelta(hours=6)
+    dp=dp.days
+    dm=dd-datetime.timedelta(hours=6)
+    dm=dm.days
+    ret=[]
+    if dn%d*2>d:
+        dn=dn+d
+    if dm%d*2>d:
+        dm=dm+d
+    if dp%d*2>d:
+        dp=dp+d
+    #recdblist.printutf8(str(d)+":"+str(dn))
+    if dp!=dn:
+        ret.append([dn/d,60])
+        ret.append([dp/d,40])
+    elif dm!=dn:
+        ret.append([dn/d,60])
+        ret.append([dm/d,40])
+    else:
+        ret.append([dn/d,100])
+    return ret
+def detNameType(title,path):
+    """
+    type A ---title#<number>
+    type B ---title#<number>subtitle
+    type C ---title subtitle
+    type D ---title(without number)
+    type Aj ---title第<number>話
+    path --search reflexively
+    """
+    new=0
+    if re.search(u"[新]",title) or re.search(u" 新",title):
+        title=title.replace(u"[新]","")
+        title=title.replace(u" 新","")
+        new=1
+    recdblist.printutf8(title,verbose_level=800)
+    title=auto_move.getTitle(title)##titleから日時を除く
+    title=title.replace(u"無料≫","")
+    #rA=re.compile(".+(?P<title>)#\d(?P<num>)\s[0,10]\z")
+    rA=re.compile("(.+)#(\d*)\s*\Z")
+    tA=rA.match(title)
+    rB=re.compile("(.+)#(\d*)\s*(\D*)")
+    tB=rB.match(title)
+    rAj=re.compile("(.+)第(\d*)話\s*\Z")
+    tAj=rAj.match(title)
+    ret={'title':"",'type':"",'num':0,'subtitle':"",'folder':""}
+    if tA:
+        #recdblist.printutf8("typeA")
+        #recdblist.printutf8("title="+tA.group(1))
+        #recdblist.printutf8("num="+tA.group(2))
+        ret['type']="A"
+        ret['title']=tA.group(1).replace(" ","")
+        ret['num']=int(tA.group(2))
+        ret['folder']=searchFolder(tA.group(1),unicode(path,'utf-8'))
+    if tAj:
+        #recdblist.printutf8("typeA")
+        #recdblist.printutf8("title="+tAj.group(1))
+        #recdblist.printutf8("num="+tAj.group(2))
+        ret['type']="Aj"
+        ret['title']=tAj.group(1).replace(" ","")
+        ret['num']=int(tAj.group(2))
+        ret['folder']=searchFolder(tAj.group(1),unicode(path,'utf-8'))
+    elif tB:
+        #recdblist.printutf8("typeB")
+        #recdblist.printutf8("title="+tB.group(1))
+        #recdblist.printutf8("num="+tB.group(2))
+        #recdblist.printutf8("subtitle="+tB.group(3))
+        ret['type']="B"
+        ret['title']=tB.group(1).replace(" ","")
+        ret['num']=int(tB.group(2))
+        ret['folder']=searchFolder(tB.group(1),unicode(path,'utf-8'))
+        ret['subtitle']=tB.group(3)
+    else:#type C or type D
+        #fold=searchFolder(title, path)
+        ts=title.split(" ")
+        tt=""
+        rt=["",0,""]
+        for t in ts:
+            tt=tt+" "+t
+            ft1=searchFolder(tt,unicode(path,'utf-8'))
+            #recdblist.printutf8(tt)
+            #print ft1
+            if ft1!="":
+                #recdblist.printutf8(rt)
+                #recdblist.printutf8(ft1[0]+" : "+str(ft1[1]))
+                if ft1[1]>rt[1]:
+                    rt[0]=tt
+                    rt[1]=ft1[1]
+                    rt[2]=ft1[0]
+                    #recdblist.printutf8(rt)
+        #recdblist.printutf8("title="+rt[0][1:]+"/")
+        #recdblist.printutf8("subtitle = "+title.replace(rt[0][1:],"")[1:])
+        ret['title']=rt[0][1:].replace(" ","")
+        ret['num']=-1
+        ret['folder']=rt[2]
+        ret['subtitle']=title.replace(rt[0][1:],"")[1:]
+        if ret['subtitle'].replace(" ","")=="":
+            ret['type']="D"
+        else:
+            ret['type']="C"
+    if new==1:
+        ret['num']=1
+    return ret
+def searchFolder(title,path,threshold=500):
+    """
+    titleからフォルダーを探す
+    """
+    folderpath=os.listdir(path)
+    lfpath=[]
+    ngram=[]
+    for ft in folderpath:
+        fullpath=os.path.join(path, ft)
+        if os.path.isdir(fullpath):
+            lfpath.append(fullpath)
+            ftt=os.listdir(fullpath)
+            if len(ftt)>0:
+                for ft2 in ftt:
+                    folderpath.append(os.path.join(fullpath, ft2))
+        else:
+            lfpath.append(fullpath)
+    for dirp in lfpath:
+        cmpp=""
+        appp=""
+        if os.path.isdir(dirp):
+            cmpp=os.path.dirname(dirp)
+            appp=dirp
+        else:
+            cmpp=os.path.basename(dirp)
+            appp=os.path.dirname(dirp)
+        ntitle=auto_move.getTitle(title)
+        ncmpp=auto_move.getTitle(cmpp)
+        p=n_gram.trigram(ntitle,ncmpp)
+        if p>0:
+            ngram.append((p,appp))
+    ngram=list(set(ngram))
+    ngram.sort()
+    ngram.reverse()
+    if len(ngram)>0:
+        #recdblist.printutf8(title + ngram[0][1] + " : "+str(ngram[0][0]))
+        if ngram[0][0]>threshold:
+            return ngram[0][1]
+        else:
+            return ""
+    else:
+        return ""
\ No newline at end of file
diff --git a/dist/trunk/rec10/install.py b/dist/trunk/rec10/install.py
new file mode 100755 (executable)
index 0000000..c2c9135
--- /dev/null
@@ -0,0 +1,276 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import time\r
+import os.path\r
+import ConfigParser\r
+import sys\r
+import commands\r
+import configwriter\r
+import shutil\r
+import traceback\r
+\r
+import recdblist\r
+def printutf8(str):\r
+    print str.encode('utf-8')\r
+def install():\r
+    version = recdblist.version\r
+    recdblist.printutf8(u"rec10の環境インストールを開始します。",verbose_level=100)\r
+    time.sleep(1)\r
+    recdblist.printutf8(u"環境インストール処理中・・・",verbose_level=100)\r
+    path = str(os.path.dirname(os.path.abspath(__file__)))\r
+    confp = ConfigParser.SafeConfigParser()\r
+    Conf = 'rec10.conf'\r
+    confpath=""\r
+    if os.path.exists(os.path.join(path,Conf)):\r
+        confpath=os.path.join(path,Conf)\r
+    elif os.path.exists(os.path.join("/etc","rec10.conf")):\r
+        confpath=os.path.join("/etc","rec10.conf")\r
+    elif os.path.exists(os.path.join("/etc/rec10","rec10.conf")):\r
+        confpath=os.path.join("/etc/rec10","rec10.conf")\r
+    if confpath!="":\r
+        confp.read(confpath)\r
+    else:\r
+        recdblist.printutf8(u"rec10.confが見つかりません。",verbose_level=100)\r
+        recdblist.printutf8(u"このinstall.pyと同じフォルダに置くか、/etc/rec10.confもしくは/etc/rec10/rec10.confにおいてください。",verbose_level=100)\r
+        sys.exit(1)\r
+    recdblist.printutf8(u"設定ファイルの読み込みを確認//設定ファイルのパスは"+confpath,verbose_level=100)\r
+    if confp.get('path',"recpath")=="/path of /recording":\r
+        recdblist.printutf8(u"録画先のフォルダを設定してください(recpath=)",verbose_level=100)\r
+        sys.exit(1)\r
+    recdblist.printutf8(u"DB処理に入ります",verbose_level=100)\r
+    if os.path.exists(os.path.join(path,"rec10d.py")):\r
+        try:\r
+            update_db_all()\r
+        except Exception, inst:\r
+            recdblist.printutf8(u"DB処理中にエラーが出ました。configファイルのDB設定を見直してください。",verbose_level=100)\r
+            recdblist.printutf8(str(type(inst)),verbose_level=100)\r
+            recdblist.printutf8(str(inst)+"\n"+traceback.format_exc(),verbose_level=100)\r
+    import rec10d\r
+    rec10d.rec10db.change_installed_in_status()\r
+    recdblist.printutf8(u"チャンネル設定に入ります",verbose_level=100)\r
+    import scan_ch\r
+    rec10d.rec10db.new_epg_ch()\r
+    recdblist.printutf8(u"チャンネルスキャンの開始",verbose_level=100)\r
+    scan_ch.searchCh()\r
+    rec10d.rec10db.change_installed_in_status(100)\r
+    recdblist.printutf8(u"おめでとうございます 初期設定は完了しました。",verbose_level=100)\r
+    recdblist.printutf8(u"rec10を実行するユーザーのcrontabに"+os.path.join(path,"rec10")+u"を追加してください(5分周期が目安)",verbose_level=100)\r
+    \r
+def getLocalPath(cmd,exit=1):\r
+    printutf8(cmd+u"の場所を確認中")\r
+    txt=commands.getoutput(u"which "+cmd)\r
+    if len(txt.split(" "))>3:\r
+        if exit==1:\r
+            printutf8(cmd+u"の場所を確認できませんでした。終了します")\r
+            sys.exit(1)\r
+        else:\r
+            return ""\r
+    else:\r
+        printutf8(cmd+u" : "+txt)\r
+        if len(txt.splitlines()):\r
+            txt=txt.splitlines()[0]\r
+        return txt.strip()\r
+def move():\r
+    useB=0\r
+    path = str(os.path.dirname(os.path.abspath(__file__)))\r
+    printutf8(u"rec10 ver "+recdblist.version_str+" installer.")\r
+    printutf8(u"rec10のインストールを開始します。")\r
+    maxn=13\r
+    configwriter.setTempConfPath(u"wine", getLocalPath(u"wine"))\r
+    configwriter.setTempConfPath(u"recpt1", getLocalPath(u"recpt1",exit=0))\r
+    #configwriter.setpath(u"x264", getLocalPath(u"x264"))\r
+    configwriter.setTempConfPath(u"mp4box", getLocalPath(u"MP4Box",exit=0))\r
+    configwriter.setTempConfPath(u"mencoder", getLocalPath(u"mencoder"))\r
+    configwriter.setTempConfPath(u"ffmpeg", getLocalPath(u"ffmpeg"))\r
+    configwriter.setTempConfPath(u"mkvmerge", getLocalPath(u"mkvmerge",exit=0))\r
+    configwriter.setTempConfPath(u"lame", getLocalPath(u"lame",exit=0))\r
+    configwriter.setTempConfPath(u"b25", getLocalPath(u"b25"))\r
+    configwriter.setTempConfPath(u"tee", getLocalPath(u"tee"))\r
+    configwriter.setTempConfPath(u"java", getLocalPath(u"java"))\r
+\r
+    try:\r
+        configwriter.setTempConfPath(u"lame", getLocalPath(u"lame"))\r
+    except:\r
+        printutf8(u"lameが見つかりません(NeroAacEncを導入する場合は問題ありません)")\r
+    printutf8(u"必須環境の設定が完了しました")\r
+    printutf8(u"個人設定に入ります")\r
+    if os.path.exists("/etc/rec10.conf"):\r
+        printutf8(u"以前の設定ファイルが見つかりました。")\r
+        printutf8(u"インポートしますか?")\r
+        useB=raw_input("[Y/n]:")\r
+        if useB=="N" or useB == "n":\r
+            useB=0\r
+        else:\r
+            useB=1\r
+            printutf8(u"設定ファイルのインポートを行います。")\r
+    printutf8(u"rec10の録画ファイルが置かれる場所を入力してください(1/"+str(maxn)+")")\r
+    printutf8(u"100GB程度は確保されている必要があります")\r
+    recpath=getConf(useB,"/etc/rec10.conf","path","recpath","path : ")\r
+    configwriter.setTempConfPath(u"recpath",recpath)\r
+    printutf8(u"DBの設定に入ります。")\r
+    printutf8(u"rec10が使用するMySQLのユーザーを設定してください。(2/"+str(maxn)+")")\r
+    mysql_user=getConf(useB,"/etc/rec10.conf","db","mysql_user","mysql_user : ")\r
+    configwriter.setTempConfDB("mysql_user", mysql_user)\r
+    printutf8(u"パスワードを設定してください(3/"+str(maxn)+")")\r
+    mysql_passwd=getConf(useB,"/etc/rec10.conf","db","mysql_passwd","mysql_passwd : ")\r
+    configwriter.setTempConfDB("mysql_passwd", mysql_passwd)\r
+    printutf8(u"同時録画可能数の設定に入ります")\r
+    printutf8(u"TE(地デジ)録画可能数(PT*だと2 白Friioだと1)(4/"+str(maxn)+")")\r
+    te_max=str(int(getConf(useB,"/etc/rec10.conf","env","te_max","te_max : ")))\r
+    configwriter.setTempConfEnv("te_max", te_max)\r
+    printutf8(u"BS/CS110録画可能数(PT*だと2 黒Friioだと1)(5/"+str(maxn)+")")\r
+    bscs_max=str(int(getConf(useB,"/etc/rec10.conf","env","bscs_max","bscs_max : ")))\r
+    configwriter.setTempConfEnv("bscs_max", bscs_max)\r
+    printutf8(u"同時エンコード最大数を設定してください(6/"+str(maxn)+")")\r
+    printutf8(u"CPUのコア数が目安です")\r
+    enc_max=raw_input("[2]:")\r
+    if enc_max=="":\r
+        enc_max="2"\r
+    else:\r
+        enc_max=str(int(enc_max))\r
+    configwriter.setTempConfEnv("enc_max", enc_max)\r
+    printutf8(u"二カ国語放送/5.1ch放送の音声変換の設定です。\nNeroAACエンコーダーを使用しますか?(NeroAACEncを別途入手してtstoolsに入れてください。))")\r
+    printutf8(u"入手先:http://www.nero.com/jpn/technologies-aac-codec.html\n (7/"+str(maxn)+")")\r
+    audioenc=raw_input("[y/N]:  ")\r
+    if audioenc=="y" or audioenc=="Y":\r
+        configwriter.setTempConfPath("useNeroAAC", "1")\r
+        aacpath=getLocalPath(u"neroAacEnc",exit=0)\r
+        if len(aacpath)<2:\r
+            printutf8(u"NeroAACEncのパスを指定してください")\r
+            aacpath=getConf(useB,"/etc/rec10.conf","path","NeroAAC","[/usr/local/bin/neroAacEnc] : ")\r
+        if aacpath.replace(" ","")=="":\r
+            aacpath="/usr/local/bin/neroAacEnc"\r
+        configwriter.setTempConfPath("NeroAAC",aacpath)\r
+    else:\r
+        configwriter.setTempConfPath("useNeroAAC", "0")\r
+        aacpath="/usr/local/bin/neroAacEnc"\r
+        configwriter.setTempConfPath("NeroAAC",aacpath)\r
+        printutf8(u"lameを使用します。")\r
+    printutf8(u"x264のパスを指定してください(7/"+str(maxn)+")")\r
+    x264path=getConf(useB,"/etc/rec10.conf","path","x264","x264 path : ")\r
+    if x264path.replace(" ","")=="" or not os.path.isfile(x264path):\r
+        x264path=getLocalPath(u"x264")\r
+    configwriter.setTempConfPath("x264",x264path)\r
+    printutf8(u"保存する画質を教えてください(8/"+str(maxn)+")")\r
+    printutf8(u"x264のcrfの値です。標準だと30分で800MBほどになります")\r
+    crf=getConf(useB,"/etc/rec10.conf","env","crf","[24] : ")\r
+    if crf.replace(" ","")=="":\r
+        crf="24"\r
+    configwriter.setTempConfEnv("crf", crf)\r
+    printutf8(u"アニメーションを保存する画質を教えてください(9/"+str(maxn)+")")\r
+    printutf8(u"x264のcrfの値です。標準だと30分で800MBほどになります")\r
+    a_crf=getConf(useB,"/etc/rec10.conf","env","animation_crf","[20] : ")\r
+    if a_crf.replace(" ","")=="":\r
+        a_crf="20"\r
+    configwriter.setTempConfEnv("animation_crf", a_crf)\r
+    printutf8(u"x264の圧縮率を設定してください(10/"+str(maxn)+")")\r
+    printutf8(u"x264のpresetの値です。標準だとmedium、小さければ小さいほど高圧縮になります")\r
+    preset=getConf(useB,"/etc/rec10.conf","env","x264_preset","[4] : ")\r
+    if preset.replace(" ","")=="":\r
+        preset="4"\r
+    configwriter.setTempConfEnv("x264_preset", preset)\r
+    printutf8(u"保存するコンテナの設定(11/"+str(maxn)+")")\r
+    printutf8(u"MP4を標準にしますか(もしくはMKVが使えます)")\r
+    useMP4=raw_input("[Y/n]:")\r
+    if useMP4=="N" or useMP4 == "n" :\r
+        useMP4="0"\r
+    else:\r
+        useMP4="1"\r
+    configwriter.setTempConfEnv("make_mp4", useMP4)\r
+    printutf8(u"TSファイルの自動削除(12/"+str(maxn)+")")\r
+    printutf8(u"中間体のtsファイルを削除しますか")\r
+    printutf8(u"(削除するとやり直しができないため残しておくことを推奨します。)")\r
+    removeTS=raw_input("[y/N]:")\r
+    if removeTS=="Y" or removeTS == "y" :\r
+        removeTS="1"\r
+    else:\r
+        removeTS="0"\r
+    configwriter.setTempConfEnv("remove_ts", removeTS)\r
+    printutf8(u"自機識別オプション(13/"+str(maxn)+")")\r
+    printutf8(u"本rec10の識別名を入力してください")\r
+    printutf8(u"複数台のrec10を運用する場合に効果的です。空白でもかまいません。")\r
+    printutf8(u"例 kobe01")\r
+    iff=getConf(useB,"/etc/rec10.conf","env","iff","[] : ")\r
+    configwriter.setTempConfEnv("iff", iff)\r
+    confp = ConfigParser.SafeConfigParser()\r
+    confp.read("/etc/rec10.conf")\r
+    if useB:\r
+        configwriter.setTempConfPath("recorded",confp.get("path","recorded"))\r
+        configwriter.setTempConfPath("move_destpath",confp.get("path","move_destpath"))\r
+        configwriter.setTempConfPath("tmp",confp.get("path","tmp"))\r
+        try:\r
+            configwriter.setTempConfEnv("x264_addline",confp.get("env","x264_addline"))\r
+        except:\r
+            configwriter.setTempConfEnv("x264_addline","")\r
+        if confp.get("path","b25_remote")=="":\r
+            configwriter.setTempConfPath("b25_remote", "0")\r
+        elif confp.get("path","b25_remote")=="1":\r
+            configwriter.setTempConfPath("b25_remote", confp.get("path","b25_remote"))\r
+            configwriter.setTempConfPath("b25", confp.get("path","b25"))\r
+            configwriter.setTempConfPath("b25_env", confp.get("path","b25_env"))\r
+        else:\r
+            configwriter.setTempConfPath("b25_remote", confp.get("path","b25_remote"))\r
+\r
+    configwriter.writeTempConf()\r
+    printutf8(u"初期設定が終了しました。")\r
+    printutf8(u"makeを実行した後にrootにてmake installを実行するとインストールされます。")\r
+def getConf(useBeforeConf,Confpath,dbsection,key,defaultstr):\r
+    tstr=defaultstr\r
+    if os.path.exists(Confpath) and useBeforeConf==1:\r
+        try:\r
+            confp = ConfigParser.SafeConfigParser()\r
+            confp.read("/etc/rec10.conf")\r
+            tstr=u"["+confp.get(dbsection,key)+u"]:"\r
+        except:\r
+            tstr=defaultstr\r
+    tmpconf=raw_input(tstr)\r
+    if tmpconf.replace(" ","")=="" and os.path.exists(Confpath) and useBeforeConf==1 :\r
+        confp = ConfigParser.SafeConfigParser()\r
+        confp.read("/etc/rec10.conf")\r
+        try:\r
+            tmpconf=confp.get(dbsection,key)\r
+        except:\r
+            tmpconf=""\r
+    return tmpconf\r
+def update_db_all():\r
+    import rec10d\r
+    tversion=0\r
+    if rec10d.rec10db.select_installed_in_status()==1:\r
+        if rec10d.rec10db.select_version_in_status()==0:\r
+            tversion=0\r
+            recdblist.printutf8(u"既存のDBが見つかりました。0.9.1と仮定してアップデート処理を行います。",verbose_level=100)\r
+            update_db(0)\r
+            time.sleep(1)\r
+        else:\r
+            recdblist.printutf8(u"既存のDBが見つかりました。アップデート処理を行います。",verbose_level=100)\r
+        tversion=int(rec10d.rec10db.select_version_in_status())\r
+        while (recdblist.version>tversion):\r
+            update_db(tversion)\r
+            tversion=int(rec10d.rec10db.select_version_in_status())\r
+    else:\r
+        rec10d.rec10db.drop_in_status()\r
+        rec10d.rec10db.drop_in_settings()\r
+        time.sleep(2)\r
+        rec10d.rec10db.new_in_status()\r
+        rec10d.rec10db.new_in_settings()\r
+        rec10d.rec10db.change_version_in_status(recdblist.version)\r
+def update_db(version):\r
+    import rec10d\r
+    if version==0:\r
+        rec10d.rec10db.update_db_to93()\r
+    elif version==93:\r
+        rec10d.rec10db.update_db_93to94()\r
+    elif version==94:\r
+        rec10d.rec10db.update_db_94to95()\r
+    elif version==95:\r
+        rec10d.rec10db.update_db_95to96()\r
+    elif version==96:\r
+        rec10d.rec10db.update_db_96to98()\r
+    elif version==98:\r
+        rec10d.rec10db.update_db_98to100()\r
+    elif version==100:\r
+        rec10d.rec10db.update_db_100to101()\r
+if __name__ == "__main__":\r
+    move()\r
diff --git a/dist/trunk/rec10/install.sh b/dist/trunk/rec10/install.sh
new file mode 100755 (executable)
index 0000000..3d61e16
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash
+SELF_DIR=`dirname $0`
+cd ${SELF_DIR}
+if type -P python2.6 > /dev/null
+then export LANG="ja_JP.UTF-8" && python2.6 ./install.py
+elif type -P python26 > /dev/null
+then export LANG="ja_JP.UTF-8" && python26 ./install.py
+elif type -P python2.7 > /dev/null
+then export LANG="ja_JP.UTF-8" && python2.7 ./install.py
+elif type -P python27 > /dev/null
+then export LANG="ja_JP.UTF-8" && python27 ./install.py
+elif type -P python2.5 > /dev/null
+then export LANG="ja_JP.UTF-8" && python2.5 ./install.py
+elif type -P python25 > /dev/null
+then export LANG="ja_JP.UTF-8" && python25 ./install.py
+fi
+
+mv Makefile.base Makefile
diff --git a/dist/trunk/rec10/license-ja.txt b/dist/trunk/rec10/license-ja.txt
new file mode 100755 (executable)
index 0000000..b489776
--- /dev/null
@@ -0,0 +1,462 @@
+GNU 劣等一般公衆利用許諾書 (GNU Lesser General Public License)¶
+
+バージョン3、2007年6月29日
+日本語訳、2007年9月5日
+
+Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+
+(訳: 本ライセンス文書を、一字一句忠実に複製、頒布することは許可する。しかし変更は認めない。)
+
+This is an unofficial translation of the GNU Lesser General Public License into Japanese. It was not published by the Free Software Foundation, and does not legally state the distribution terms for software that uses the GNU LGPL--only the original English text of the GNU LGPL does that. However, we hope that this translation will help Japanese speakers understand the GNU LGPL better.
+
+(訳: 以下はGNU Lesser General Public Licenseの非公式な日本語訳です。これはフリーソフトウェア財団 (Free Software Foundation)によって正式に発表されたものではなく、GNU LGPLが適用されたソフトウェアの頒布条件を法的に有効な形で述べたものではありません。頒布条件としては、GNU LGPLの英語版テキストで指定されているもののみが有効です。しかしながら、私たちはこの翻訳が、日本語を使用する人々にとってGNU LGPLをより良く理解する助けとなることを望んでいます。)
+
+翻訳は八田真行 <mhatta@gnu.org>が行った。原文はhttp://www.gnu.org/licenses/lgpl-3.0.html である。誤訳の指摘や訳の改善案を歓迎する。なお、日本語訳の利用条件は原文に準ずる。
+
+このバージョンのGNU 劣等一般利用許諾書では、GNU 一般公衆利用許諾書(GNU General Public License)バージョン3が規定する利用条件を取り込んだ上で、以下に列挙する追加的許可で補足するものとする。
+0. 追加された定義¶
+
+本文中で使われている通り、「本許諾書」はGNU 劣等一般公衆利用許諾書バージョン3を指す。「GNU GPL」は、GNU 一般公衆利用許諾書バージョン3を指す。
+
+『ライブラリ』(The Library)とは、本許諾書の下で管理された『保護された作品』のうち、以下で定義する『アプリケーション』や『結合された作品』以外のものを指す。
+
+『アプリケーション』(Application)とは、『ライブラリ』が提供するインターフェースを利用するが、『ライブラリ』を基にはしていない作品すべてのことである。『ライブラリ』によって定義されたクラスの下位クラスを定義するのは、『ライブラリ』が提供するインターフェースの利用の一形態と見なされる。
+
+『結合された作品』(Combined Work)とは、『アプリケーション』と『ライブラリ』を結合ないしリンクすることによって作成された作品のことである。また、それによって『結合された作品』が作られた特定のバージョンの『ライブラリ』は、『リンクされたバージョン』(Linked Version)と呼ばれる。
+
+『結合された作品』に対する『最小限の対応するソース』 (Minimal Corresponding Source)とは、『結合された作品』に対する(訳注: GPLv3における)『対応するソース』のことを意味する。ただし、『結合された作品』に含まれる部分のうち、それのみを分離して考えた場合、『アプリケーション』を基にしているが、『リンクされたバージョン』は基にしていない部分のソースコードのすべては除外される。
+
+『結合された作品』に『対応するアプリケーションコード』 (Corresponding Application Code)とは、『アプリケーション』のオブジェクトコードかソースコードを意味する。『対応するアプリケーションコード』には、『アプリケーション』から『結合された作品』を再生成するために必要なデータやユーティリティ・プログラムすべてが含まれるが、『結合された作品』の『システムライブラリ』は除く。
+1. GNU GPL第3項への例外¶
+
+あなたは本許諾書の第3項および第4項に従い、『保護された作品』を伝達することができる。その際、GNU GPL第3項の第2段落に束縛される必要はない。
+2. 改変されたバージョンの伝達¶
+
+『ライブラリ』のコピーを改変し、かつあなたの改変点において、ある機能が (その機能が呼び出される際に引数として渡されるものを除いて)その機能を利用する『アプリケーション』から提供される関数やデータを参照する場合、以下のどちらかに従えば、あなたは改変されたバージョンのコピーを伝達することができる:
+
+    * a) 本許諾書に従って伝達する。ただし、『アプリケーション』が関数やデータを提供しない場合でも、その機能が依然として動作し、機能の目的のうち意味あるものとして残った部分はすべて実行するよう誠実な配慮を尽くさなければならない。あるいは、
+    * b) GNU GPLに従って伝達する。この場合、本ライセンス文書によってそのコピーに適用可能な追加的許可は一切認められない。 
+
+3. ライブラリのヘッダファイルに由来するコードや各種データを取り込んだオブジェクトコード¶
+
+オブジェクトコード形式の『アプリケーション』は、『ライブラリ』の一部であるヘッダファイルに含まれるコードや各種データを取り込むことができる。あなたは、そのようなオブジェクトコードを、あなたが選択したいかなる条項の下でも複製、伝達して構わない。ただし、取り込まれたコード等が数値的パラメータや、データ構造のレイアウトやアクセサー、小さなマクロ、インライン関数やテンプレート(長さにして10行以下)ではない場合、あなたは以下の両方を行わなければならない。
+
+    * a) オブジェクトコードのコピーそれぞれにおいて、『ライブラリ』がその中で利用されており、『ライブラリ』とその利用は本許諾書によって保護されている旨を目立つように告知する。
+    * b) オブジェクトコードに、GNU GPLと本許諾書のコピーを添付する。 
+
+4. 結合された作品¶
+
+あなたは、『結合された作品』に含まれる『ライブラリ』部分の改変を事実上禁止したり、そのような改変をデバッグするためのリバースエンジニアリングを禁止したりしない限り、『結合された作品』をあなたが選択したいかなる条件の下でも複製、伝達して構わない。ただしその場合、以下をすべて行う必要がある:
+
+    * a) 『ライブラリ』が『結合された作品』中で利用されており、また『ライブラリ』とその利用は本許諾書によって保護されるということを、『結合された作品』のコピーそれぞれにおいて目立つように告知する。
+    * b) 『結合された作品』に、GNU GPLと本ライセンス文書のコピーを添付する。
+    * c) 実行中に『コピーライト』告知を表示する『結合された作品』の場合、そういった告知文中に 『ライブラリ』の著作権告知と、ユーザに対してGNU GPLと本ライセンス文書のコピーがどこにあるかを示す参照先情報を含める。
+    * d) 以下のどれか一つを行う:
+          o 0) 本許諾書の条項に従い、『最小限の対応するソース』を伝達する。また、『対応するアプリケーションコード』を、『対応するソース』の伝達に関して GNU GPL第6項が指定しているのと同様のやり方で、ユーザが『アプリケーション』を『ライブラリ』の改変されたバージョンと再結合または再リンクして改変された『結合された作品』を作成するのに適した形式、かつそういった再結合や再リンクを許可する条項の下で伝達する。
+          o 1) 『ライブラリ』をリンクするのに適した共有ライブラリメカニズムを利用する。適したメカニズムとは、(a)実行時すでにユーザのコンピュータシステムに存在する『ライブラリ』のコピーを利用し、(b) 『リンクされたバージョン』とインターフェースに互換性がある『ライブラリ』の改変されたバージョンと共に適切に機能するものである。 
+    * e) 『インストール用情報』を提供する。ただしこれはGNU GPL第6項に従いそのような情報を提供することが義務付けられている場合に限られ、またそのような情報が、『リンクされたバージョン』の改変されたバージョンと『アプリケーション』を再結合ないし再リンクすることによって作成された『結合された作品』の改変されたバージョンをインストール、実行するのに必要とされる限りにおいてのみである(あなたが小項4dの0を選択する場合、『インストール用情報』は『最小限の対応するソース』と『対応するアプリケーションコード』と共に供しなければならない。あなたが小項4dの1を選択する場合、あなたは『インストール用情報』をGNU GPL第6項が『対応するソース』の伝達に関して指定するのと同様のやり方で提供しなければならない)。 
+
+5. 結合されたライブラリ¶
+
+あなたは、『ライブラリ』を基にした作品であるライブラリ機能を、『アプリケーション』ではなく、かつ本許諾書で保護されていない他のライブラリ機能と一緒に、単一のライブラリ内で並置し、そのような結合されたライブラリをあなたが選んだ条項に従って伝達することができる。ただしその場合、以下の両方を行わなければならない。
+
+    * a) 結合されたライブラリに、他のいかなるライブラリ機能とも結合されておらず、本許諾書の条項に従って伝達される、元のままの『ライブラリ』を基にした作品のコピーを添付する。
+    * b) その一部が『ライブラリ』を元にした作品である結合されたライブラリに、対応する結合されていない形式の同じ作品がどこで見つかるかを説明した目立つ告知を載せる。 
+
+6. GNU 劣等一般公衆利用許諾書の改訂されたバージョン¶
+
+フリーソフトウェア財団は、改訂された、あるいは新しいバージョンのGNU 劣等一般公衆利用許諾書を折りに触れて発行することができる。そのような新バージョンは、その精神においては現在のバージョンと似たものになるだろうが、細部については新たに生じた問題や懸念を解決すべく異なるものになるだろう。
+
+それぞれのバージョンには、見分けがつくようなバージョン番号が振られている。あなたが受領した『ライブラリ』において、ある特定のバージョン番号が振られたGNU 劣等一般公衆利用許諾書「かそれ以降のバージョンのいずれか (or any later version)」が適用されると指定されていた場合、あなたは指定された番号のバージョンか、それ以降にフリーソフトウェア財団によって発行されたバージョンのいずれかのバージョンのどちらの利用条件に従うかを選ぶことができる。あなたが受領した『ライブラリ』が特定のバージョン番号の GNU 劣等一般公衆利用許諾書を指定していなかった場合には、あなたはフリーソフトウェア財団がそれまでに発行したGNU 劣等一般公衆利用許諾書のバージョンの中からどれを選択しても構わない。
+
+(訳注: 日本語訳のバージョンは日付で管理している。冒頭を見よ。)
+
+あなたが受領した『ライブラリ』において、GNU 劣等一般公衆利用許諾書の将来のバージョンのうちどれが適用されうるかは代理人が決定できる、と指定されていた場合、その代理人が、あるバージョンを受諾すると述べた公的な声明は、あなたに対し、その『ライブラリ』に関してそのバージョンのGNU LGPLを選ぶことを永続的かつ正式に許可するのと等しい。
+
+
+
+
+
+
+利用条件 (TERMS AND CONDITIONS)¶
+0. 定義¶
+
+「本許諾書」(The License)とは、GNU 一般公衆利用許諾書のバージョン3を指す。
+
+「『コピーライト』」(Copyright)とは、いわゆる著作権のみならず、半導体マスクのようなその他の作品に適用される、著作権に類似した法的権利をも意味する。
+
+(訳注: この規定により、本許諾書は著作権法で保護されたいわゆる「著作物」よりも広い範囲をカバーすることになる。よってこの訳のライセンス本文中においては、work(s)に「著作物」ではなく「作品」という訳語を宛てることにした。)
+
+「『プログラム』」(The Program)とは、本許諾書の下でライセンスされた、『コピーライト』が主張可能な作品すべてを意味する。個々のライセンシーは「あなた」として表現される。ライセンシーは個人でも組織でも構わない。
+
+ある作品の「改変」(modify)とは、その作品の全体ないし一部を、『コピーライト』の許可を必要とするようなやり方で複製ないし翻案することを意味する。ただし、完全に同一なコピーを作成する場合は除く。改変の結果出来た作品は、以前の作品の「改変されたバージョン」(modified version)、または、以前の作品を「基にした」(based on)作品と呼ばれる。
+
+「『保護された作品』」(covered work)とは、改変されていない『プログラム』か、『プログラム』を基にした作品のいずれかを指す。
+
+ある作品の「普及」(propagate)とは、コンピュータ上で実行すること、または私的なコピーを改変することを除き、適用可能な『コピーライト』法規の下で許可無く行うと、権利侵害として、直接的、あるいは間接的にあなたが責任を問われる何らかの行為を意味する。普及には、複製、頒布 (改変の有無を問わない)、公衆への利用可能化が含まれ、またいくつかの国々では他の活動も含まれる可能性がある。
+
+ある作品の「伝達」(convey)とは、第三者がコピーを作成ないし受領するのを可能とする普及行為すべてを意味する。ただし、コンピュータネットワーク越しにユーザとやりとりするだけで、コピーの転送は伴わない場合は、伝達ではない。
+
+対話的なユーザインターフェースが「『適切な法的告知』」(Appropriate Legal Notices)を表示するという場合、そのインターフェースは (1)適切な『コピーライト』告知を表示し、(2)ユーザに対して、その作品には何の保証もない(別途保証が提供されている場合は除く)ということ、ライセンシーはその作品を本許諾書の下で伝達できるということ、そして本許諾書のコピーを見るにはどうしたらよいかということを便利かつ顕著に視認できるような機能を含むものとする。もしインターフェースが、メニューのようなユーザコマンドやオプションの一覧を表示するならば、その一覧中には上記の基準を満たすようなアイテムが目立つように含まれていなければならない。
+1. ソースコード¶
+
+ある作品の「ソースコード」(source code)とは、その作品に改変を加えるに当たって好ましいと考えられる形式のことである。「オブジェクトコード」 (object code)とは、作品がとりうるソースコード以外の形式すべてを意味する。
+
+「標準インターフェース」(Standard Interface)とは、標準化団体として認知された組織によって定義された公式な標準か、ある特定のプログラミング言語向けに指定されたインターフェースの場合には、その言語を利用する開発者の間で広く使われているインターフェースのことを指す。
+
+実行可能な作品の「『システムライブラリ』」(System Libraries)とは、 (a)「主要コンポーネント」(Major Component) の頒布物に通常含まれるが、その主要コンポーネントの一部ではなく、かつ(b)作品をその「主要コンポーネント」といっしょに利用することを可能にする、あるいは公衆にとってソースコード形式で利用可能な実装がひとつは存在する標準インターフェースを提供するためにのみ機能するものすべてを意味する。ただし、全体としての作品そのものは除く。ここでいう「主要コンポーネント」とは、実行可能な作品がその上で実行されるある特定のオペレーティングシステム (そういったものが必要ならば)の主要で不可欠な一部分(カーネルやウィンドウシステムなど)、あるいはその作品を作成するのに使われるコンパイラ、実行するのに使われるオブジェクトコードインタプリタなどを意味する。
+
+オブジェクトコード形式の作品に「『対応するソース』」(Corresponding Source)とは、その作品を生成、インストール、(実行可能な作品に関しては)オブジェクトコードを実行、または作品を改変する上で必要とされるソースコードのすべてを意味する。この場合、そうした活動をコントロールするためのスクリプトは『対応するソース』に含まれるが、その作品にとっての『システムライブラリ』や、先ほど列挙した活動を行う上で改変されることなく利用されるものの作品の一部ではない、汎用のツールや一般的に利用可能なフリープログラムは除外される。例えば『対応するソース』には、その作品のソースファイルと連携するインターフェース定義ファイルに加え、共有ライブラリや動的にリンクされた下位プログラムと作品のその他の部分との間での親密なデータのやりとりやコントロールフローなどのために、その作品が設計上明確に必要とする、そうした共有ライブラリや下位プログラムのソースコードなどが含まれる。
+
+『対応するソース』には、ユーザが『対応するソース』の他の部分から自動的に再生成できるものを含む必要はない。
+
+ソースコード形式の作品にとっての『対応するソース』とは、その作品そのものである。
+2. 基本的な許可¶
+
+本許諾書の下で認められるすべての権利は、『プログラム』に主張される『コピーライト』の条項に基づき授与されるものであり、ここで述べられた条件が満たされている限り覆すことはできない。本許諾書は、改変されていない『プログラム』をあなたが無制限に実行することを許可し、明示的に確約する。『保護された作品』を実行することから得られた出力結果は、その出力内容が『保護された作品』を構成する場合のみ本許諾書で保護される。本許諾書は、あなたが有するフェアユースまたはその同等物の権利を、『コピーライト』法規によって提供される通りに承認する。
+
+その他の状況においてあなたのライセンスが有効である限り、『保護された作品』の、伝達を伴わない作成、実行、および普及は無条件に行うことができる。他者にあなた専用の改変を行わせる、あるいは他者にあなたがそういった作品を実行するための機能を提供させるということが唯一の目的であれば、『保護された作品』を他者に伝達することができる。ただしその場合、あなたが『コピーライト』を支配していない部分すべての伝達に関しては、本許諾書の条項に従わなければならない。従って、あなたのために『保護された作品』を作成または実行する者は、専らあなたのためだけに、あなたの監督と支配の下で、あなたとの関係の範囲外ではあなたが『コピーライト』を有する一部分のいかなるコピーをも作成することを禁止するという条件の下で行わなければならないということになる。
+
+上記以外のあらゆる状況下においては、伝達は以下で述べる条件の下でのみ許可される。再許諾は認められない。下記第10項により、再許諾は必要ないからである。
+3. ユーザの法的権利を、技術的保護手段の回避を禁ずる法律から守る¶
+
+『保護された作品』は、 1996年12月20日に採択されたWIPO著作権条約第11項の下での義務を満たす適用可能な法のいずれか、あるいはそれに類似の法が、回避の禁止または制限の対象として規定する、「効果的な技術的手段」 (effective technological measure)の一部として見なされてはならない。
+
+(訳注: WIPO著作権条約については、http://www.cric.or.jp/db/article/wch.html 等を参照せよ。)
+
+あなたが『保護された作品』を伝達する場合、『保護された作品』に関して本許諾書の下で権利を行使することにより、技術的手段の回避に影響が出る範囲において、そのような手段の回避を禁じるいかなる法的権力をも放棄することになる。また、あなたはその作品のユーザに対して、技術的手段の回避を禁じるためにあなたや第三者の法的権利を強制するための手段として、その作品の動作や改変を制限するいかなる意図も否認することになる。
+4. 一字一句忠実なコピーの伝達¶
+
+あなたは、自分が受領した『プログラム』のソースコードと一字一句同じコピーであれば、いかなる媒体でも伝達することができる。ただしその場合、あなたはそれぞれのコピーにおいて、目立つように、かつ適切な形で、ふさわしい『コピーライト』告知を掲載しなければならない。すなわち、本許諾書と、下記第7項に従い追加された非許可的条項のすべてがそのコードに適用される旨の告知を掲載し、あらゆる保証が存在しない旨の告知をすべてそのまま保全し、かつ『プログラム』の受領者すべてに、『プログラム』といっしょにこの許諾書のコピーを与えなければならない。
+
+あなたは、自分が伝達するコピーのそれぞれに関していかなる価格を付けても良いし、無料で伝達しても構わない。また、報酬を取ってサポートや保証保護 (warranty protection)を提供しても良い。
+5. 改変されたバージョンのソースの伝達¶
+
+あなたは、『プログラム』を基にした作品、あるいはそうした作品を『プログラム』から作成するための改変点を、上記第4項の規定に従ってソースコード形式で伝達することができる。ただしその場合、あなたは以下に示す条件のすべてを満たさなければならない:
+
+    * a) 作品には、あなたが作品を改変したということと、改変に関連した日時を記述した告知を目立つように載せなければならない。
+    * b) 作品には、それが本許諾書と、下記第7項に従って追加された条件すべての下で公開されていることを記述した告知を目立つように載せなければな らない。この条件は、上記第4項における「告知をすべてそのまま保全」するための条項を改変する。
+    * c) 作品の全部分を、総体として、コピーを所有するに至った人全員に、本許諾書の下でライセンスしなければならない。そこで、本許諾書は、本許諾書第7項に基づく適用可能な追加的条項のすべてとともに、作品全体に、すなわちその全部分に、それらがどのようにパッケージされているかに関わらず適用されることになる。本許諾書は、これ以外のやり方には作品をライセンスする許可を与えないが、あなたが本許諾書以外で別途許可を得ていた場合には、それによって得られた許可まで無効とするものではない。
+    * d) 改変された作品が対話的なユーザインターフェースを有する場合、それらのインターフェースは『適切な法的告知』を表示しなければならない。ただし、『プログラム』に元々『適切な法的告知』を表示しない対話的なインターフェースがある場合、あなたの作品で表示するようにする必要はない。 
+
+一巻の記憶装置の中か頒布媒体上で、『保護された作品』と、本来『保護された作品』の拡張ではなく、『保護された作品』とより大規模なプログラムを形成するような形で結合されているわけでもないその他の分離かつ独立した作品とをまとめた編集物は、編集作業とそれに由来する『コピーライト』が、個々の作品が許可する範囲を越えて編集物のユーザの作品へのアクセスや法的権利を制限するのに使われない限り、「集積物」(aggregate)と呼ばれる。単に『保護された作品』を集積物に含めるだけでは、その集積物の他の部分にまで本許諾書が適用されるということにはならない。
+6. ソース以外の形式における伝達¶
+
+あなたは、オブジェクトコード形式の『保護された著作物』を、上記第4項および第5項の規定に従って伝達することができる。ただしその場合、あなたは機械読み取り可能な『対応するソース』も本許諾書の条件に従って、以下のいずれかの方法で伝達しなければならない。
+
+    * a) オブジェクトコードを物理的製品(物理的頒布媒体を含む)で、あるいはそれに組み込んで伝達する。その際、『対応するソース』を、ソフトウェア のやりとりで一般的に使われる耐久性のある物理的媒体に固定していっしょに頒布する。
+    * b) オブジェクトコードを物理的製品(物理的頒布媒体を含む)で、あるいはそれに組み込んで伝達する。その際、最低でも3年間、あるいはあなたがその製品モデルに補修用部品やカスタマーサポートを提供する限り有効な、書面 による申し出を添付する。その申し出には、(1) オブジェクトコードを所有する者すべてに対して、その製品に含まれるソフトウェアのうち本許諾書で保護されるものすべてに『対応するソース』のコピーを、ソフトウェアのやりとりで一般的に使われる耐久性のある物理的媒体で頒布する旨を記載する。その際、物理的にこのソースの伝達を行うのにかかる正当なコスト以上の価格を要求してはならない。あるいは、(2) 『対応するソース』を無料でネットワークサーバから複製するためのアクセスを提供する旨を記載する。
+    * c) オブジェクトコードの個々のコピーを、対応するソースを提供するという書面による申し出のコピーといっしょに伝達する。この選択肢は特別な場合、かつ非商業的な場合のみに、そしてあなたがオブジェクトコードを上記小項 6bに合致した申し出といっしょに受領した場合にのみに認められる。
+    * d) オブジェクトコードを、指定の場所から複製するためのアクセスを提供することによって伝達し、『対応するソース』に対しても同じ場所を通じて同じ方法で複製するための同等のアクセスを提供する。伝達は無料でも手数料を課しても構わないが、『対応するソース』に対して追加的な課金を行ってはならない。受領者に対して、『対応するソース』をオブジェクトコードといっしょに複製することを義務づける必要はない。オブジェクトコードの複製元がネットワークサーバの場合、対応するソースは同等の複製機能をサポートする異なったサーバ(あなたか第三者が運営)上にあっても良い。その場合、オブジェクトコードの傍らに、『対応するソース』はどこで見つけられるかを明確に指示しておかなければならない。どのサーバが『対応するソース』をホストするかに関わらず、あなたは『対応するソース』がこれらの条 項を満たすために必要なかぎり利用可能であることを保証する責任がある。
+    * e) オブジェクトコードをピア・ツー・ピア伝送を使って伝達する。ただしこの場合、あなたは上記小項6dに従い、その作品のオブジェクトコードと 『対応するソース』がどこで一般公衆に無料で提供されるのかということを他のピアに知らせておかなければならない。 
+
+オブジェクトコードの分離した一部であり、そのソースコードが『対応するソース』から『システムライブラリ』として除外されているものは、オブジェクトコード作品を伝達する場合に含める必要はない。
+
+「ユーザ製品」(User Product)とは、(1)「コンシューマ製品」(consumer product)、すなわち、個人、子供、あるいは家庭用に通常使用される有形個人資産すべてか、あるいは(2)居住所における導入を目的に設計ないし販売されるものすべてを指す。ある物品がコンシューマ製品であるかを決定する際疑義がある場合には、極力範囲を広げる方向で決定されるべきである。ここで、ある特定のユーザによって受領されたある特定の製品にとっての「通常使用」 (nomally used)とは、その種の製品において典型的な、あるいは一般的な利用のことであり、その特定のユーザが置かれた状況や、その特定のユーザがその製品を実際にどう使っているか、どう使うことを予期しているか、あるいは予期されているかとは関係ない。その製品に相当な商業的、産業的または非コンシューマ的な利用法があったとしても、そうした利用がその製品の唯一重要な利用形態を代表するものでない限り、その製品はコンシューマ製品である。
+
+ユーザ製品の「『インストール用情報』」(Installation Information)とは、ユーザ製品内の『保護された作品』に関して、『対応するソース』の改変されたバージョンから得られる『保護された作品』の改変されたバージョンを、インストール、実行するために必要な手法、手順、認証キーやその他の情報すべてを意味する。この情報は、改変されたオブジェクトコードの継続的な動作が、改変が為されたということによってのみ拒否されたり妨害されることが決してないことを保証するのに十分なものでなければならない。
+
+本節の下において、作品をユーザ製品の内で、またはユーザ製品と共に、あるいは特にユーザ製品での利用を念頭においてオブジェクトコードで伝達し、またその伝達がユーザ製品の受領者への所有と利用の権利の永遠ないし有期の移転の一部として起こる場合(移転がどのように行われるかは問わない)、この条項の下で『対応するソース』は『インストール用情報』と共に提供されなければならない。しかしこの条件は、あなたと第三者のいずれもが改変されたオブジェクトコードをユーザ製品にインストールする能力を有していない際には適用されない(例えば、作品がROMにインストールされている場合)。
+
+『インストール用情報』を提供する条件には、受領者によって改変ないしインストールされた作品、あるいはそうした作品が改変ないしインストールされたユーザ製品に対し、サービスや保証、アップデートを提供しつづけるという条件は含まれない。改変自体がネットワークの運用に実質的かつ有害な影響をもたらし、ネットワークを介したコミュニケーションのプロトコルや規則に違反する場合には、ネットワークアクセスを拒否しても構わない。
+
+伝達される『対応するソース』や提供される『インストール用情報』が本節を満たすためには、それらが公に文書化された形式で(かつ公衆に対してソースコード形式で利用可能な実装とともに)提供されなければならない。この場合、これらの圧縮展開や読み込み、複製に特別なパスワードやキーを必要としてならない。
+7. 追加的条項¶
+
+「追加的許可」(Additional permissions)とは、本許諾書が課す条件に一つかそれ以上の例外を設けることにより、本許諾書の条項を補足する条項のことである。『プログラム』全体に適用可能な追加的許可は、適用可能な法の下でそれらが有効である限り、あたかもそれらが本許諾書に含まれているかのように扱われなければならない。追加的許可が『プログラム』の一部にのみ適用される場合、その部分に関してはそういった追加的許可の下で別途利用可能だが、『プログラム』全体としては追加的許可に関わりなく本許諾書によってのみ管理される。
+
+あなたが『保護された作品』のコピーを伝達する場合、あなたは追加的許可をそのコピー、あるいはその一部から削除することを選択できる (追加的許可は、あなたが作品をある種の形で改変する際には、そうした許可自身の削除を要求するような形で書かれてもよい)。あなたは、あなたによって『保護された作品』に追加され、あなたが適切な『コピーライト』許可を有するか、与えることができる限り、その一部分に追加的許可を設定することができる。
+
+本許諾書の他の条件に関わらず、あなたが『保護された作品』に追加した一部分について(その部分の『コピーライト』保有者らによって正式に許可されていれば)、本許諾書の条項を、以下に示す条項で補足することができる:
+
+    * a) 本許諾書第15項および第16項の条項とは異なった形で保証の否認や責任の限定を主張する。あるいは、
+    * b) 追加した一部分において、明示的で妥当な法的告知や作者特定の保全、またはそれを含む作品において『適切な法的告知』の表示を要求する。あるいは、
+    * c) 追加した一部分の出自を不当に表示することを禁じるか、あるいはそのような一部分の改変されたバージョンはオリジナルのバージョンとは異なっ ているということを適切な方法で印づけることを要求する。あるいは、
+    * d) その一部分のライセンサーや作者の名前を、宣伝目的で利用することを制限する。あるいは、
+    * e) 商品名や商標、サービスマークの利用に関して、商標法に従い権利を授与することを拒否する。あるいは、
+    * f) その一部分(あるいはその改変されたバージョン)を伝達する者に、受領 者への責任に関して契約上の引き受けがあり、そうした責任が直接的にそういったライセンサーや作者にまで課せられる場合、その一部分のライセンサーや作者の免責を要求する。 
+
+他の非許可的な追加的条項は下記第10項が意味するところの「さらなる権利制限」(further restrictions)とみなされる。あなたが受領した『プログラム』、あるいはその一部に、それが本許諾書とともにさらなる権利制限である条項によっても管理されていると述べた告知が含まれている場合には、あなたはそういった条項を削除して構わない。あるライセンス文書にさらなる権利制限がふくまれているが、しかし本許諾書の下での再許諾や伝達を許可しているならば、あなたはそのライセンス文書の条項によって管理されている一部分を『保護された作品』に追加することができる。ただしその場合、さらなる権利制限はそのような再許諾や伝達では無効としなければならない。
+
+あなたが本節に従って『保護された著作物』に条項を追加した場合、あなたは関係するソースファイル中に、それらのファイルに適用される追加的条項に関する声明、あるいは適用可能な条項を見つけることができる場所を示す告知を掲載しなければならない。
+
+追加的条項は、それが許可的であろうと非許可的であろうと、別途書面化されたライセンスという形式で述べられてもよいし、本許諾書への例外として述べられてもよい。上記の要件はどちらの場合でも適用される。
+8. 終了¶
+
+あなたは『保護された作品』を、本許諾書の下で明示的に提供されている場合を除いて、普及、または改変してはならない。それ以外に『保護された作品』を普及、または改変しようとする試みはすべて無効であり、本許諾書の下であなたに認められた権利(下記第11項の第3段落に従い授与されたパテントライセンスすべてを含む)を自動的に終了させることになる。
+
+しかしながら、あなたが本許諾書への違反をすべて中止するならば、あなたがある特定の『コピーライト』保有者から得たライセンスは、(a)その『コピーライト』保有者が明白かつ決定的にあなたへのライセンスを終了させるか、あるいはさせないまでは暫定的に、(b)その『コピーライト』保有者が、あなたに対し違反について、何らかの正当な手段によりライセンス停止後60日以内に通知することができなかった場合には永続的に、回復される。
+
+加えて、あなたがある特定の『コピーライト』保有者から得たライセンスは、その『コピーライト』保有者があなたに対して違反を何らかの正当な手段で通知し、それより前にその『コピーライト』保有者から、(当該作品に限らずその『コピーライト』保有者の作品のいずれかに関して)本許諾書に関する違反の通知を受領したことがなく、さらにあなたがその通知を受領してから30日以内に違反を正した場合、永続的に回復される。
+
+本節に従いあなたの権利が終了した場合でも、本許諾書に従ってあなたからコピーや権利を受領した当事者が得た許諾は終了しない。あなたの権利が終了され、永続的に回復されなかった場合には、あなたは同じライセンス対象に関し下記第10項に従って新たにライセンスを受領する資格を失うものとする。
+9. コピーの所有に必要とされない受諾¶
+
+あなたは、『プログラム』のコピーを受領あるいは実行するために本許諾書を受諾する必要はない。コピーを受領するためにピア・ツー・ピア伝送を使った結果としてのみ発生する『保護された作品』の付随的な普及も、同様に受諾を必要としない。しかしながら、他の場合においては、本許諾書以外にあなたに対して『保護された作品』の普及や改変をする許可を認めるものはない。これらの行為は、本許諾書を受諾しない限り『コピーライト』を侵害することになる。そこで、『保護された作品』を改変あるいは普及することにより、あなたはそうした行為を行うために本許諾書を受諾したということを示したことになる。
+10. 下流の受領者への自動的許諾¶
+
+あなたが『保護された作品』を伝達するたびに、受領者は自動的にオリジナルのライセンサーから、本許諾書に従いその作品を実行、改変、普及するライセンスを得る。なお、あなたには第三者が本許諾書に従うことを強制する責任はない。
+
+「主体取引」(entity transaction)とは、ある組織そのもの、ないしその組織の実質的に全ての資産の支配権が移転するか、あるいは組織の細分化や合併が行われるような取引を指す。もし主体取引の結果として『保護された作品』の普及が起こった場合、作品のコピーを受領したそれぞれの取引当事者は、利害関係のある当事者の先任者から、その先任者が前段落に従って有する、あるいは与えることができる、その作品に関するライセンスもまたすべて受領する。加えて個々の取引当事者は、利害関係のある先任者から、その先任者が有しているか、適正な努力によって得ることが可能な限りにおいて、その作品の『対応するソース』の所有権も得る権利を有する。
+
+あなたは本許諾書の下で授与された、あるいは確約された権利の行使に対して、本許諾書が規定する以上のさらなる権利制限を課してはならない。たとえば、あなたはライセンス料、ロイヤルティや他の料金を、本許諾書の下で認められている権利の行使に関して課してはならない。また、あなたは『プログラム』やその一部の作成、利用、販売、販売の申し出、取り込みによって何らかのパテントクレームが侵害されたとして、訴訟(訴訟における反対請求ないし反訴を含む)を開始してはならない。
+11. 特許¶
+
+「貢献者」(contributor)とは、本許諾書の下で『プログラム』、あるいは『プログラム』が基にした作品を利用することを正式に許可した『コピーライト』保有者のことを指す。従って、そのようにしてライセンスされた作品は、貢献者による「貢献者バージョン」(contributor version)と呼ばれる。
+
+ある貢献者の「必須パテントクレーム」(essential patent claims)とは、すでに取得しているか、あるいは今後取得する見込みがあるため、その貢献者が現在所有ないし支配していると言える特許のうち、貢献者バージョンに対して、本許諾書で許可されているような作成や利用、販売といった何らかの形の行為を行うことによって侵害される可能性があるパテントクレームのすべてを意味する。ただし、貢献者バージョンをさらに改変した結果としてのみ侵害されるようなクレームは含まれない。この定義において、「支配」には本許諾書が課す条件と整合的なやり方で特許の再許諾を認める権利も含まれる。
+
+個々の貢献者はあなたに対して、その貢献者の必須パテントクレームに関し、あなたがその貢献者バージョンの内容を作成、利用、販売、販売の申し出、取り込み、その他実行、改変、普及するために必要な、非排他的で全世界的に有効、かつロイヤルティフリーのパテントライセンスを授与する。
+
+以下の3段落において「『パテントライセンス』」とは、ある特許を実施しないという明示的な協定やコミットメントのすべてを指す(例えば、ある特許の実施に対する明示的な許可や、特許侵害訴訟を提起しないという誓約など)。そのような『パテントライセンス』をある当事者に「授与」するとは、その当事者と特許を実施しないという協定やコミットメントを結ぶことを意味する。
+
+もしあなたが、『保護された作品』の伝達を、それがある『パテントライセンス』に依存しており、よってその作品の『対応するソース』は、すべての人にとって、公衆が利用可能なネットワークサーバや他の容易にアクセス可能な手段を通じ、無料かつ本許諾書に従って複製可能ではないということを知りながら行うならば、あなたは (1)『対応するソース』も同様に利用可能にするか、 (2)この特定の作品に関して『パテントライセンス』から得られる便益を自ら剥奪するか、あるいは(3)下流の受領者に対しても、本許諾書の条項と整合的な形で、『パテントライセンス』が拡大されるように計らうかのいずれかを行わなければならない。ここで「『パテントライセンス』に依存するのを知りながら」というのは、あなたが『保護された作品』をある国で伝達すること、あるいはあなたの受領者が『保護された著作物』をある国で利用することが、『パテントライセンス』を授与されない限り、その国において、あなたにとってそれが有効だと信じるだけの理由がある一つかそれ以上の同定可能な特許を侵害するということを実際に知っているということである。
+
+ある一対一の取引や協定に基づき、あるいは関連して、あなたが『保護された作品』の伝達、または伝達によって引き起こされる普及を行い、その際『保護された作品』を受領した一部の当事者に対して、『保護された作品』の特定のコピーの利用、普及、改変、または伝達を正式に許可するような『パテントライセンス』を授与するならば、あなたが授与した『パテントライセンス』は『保護された作品』やそれを基にした作品のすべての受領者にまで自動的に拡大されることになる。
+
+ある『パテントライセンス』が「差別的」(discriminatory)であるとは、本許諾書の下で明確に認められた一つかそれ以上の権利を、『パテントライセンス』がカバーする範囲内に含まなかったり、そうした権利の行使を禁じたり、あるいは権利を行使しないことを条件として課すようなものである場合を指す。あなたを一方の当事者とし、ソフトウェアの頒布を生業とする第三者との間で、あなたは第三者に対し、作品を伝達する活動の程度に基づいて支払いを行う一方、第三者は、あなたから『保護された作品』を受領したすべての当事者に対して「差別的」な『パテントライセンス』を、(a)あなたが伝達した『保護された作品』のコピー(またはそうしたコピーから作成されたコピー)に対して、または(b)『保護された作品』を含む特定製品や編集物を、主要な、あるいは関連した対象として授与する、というような協定を結んでいる場合、あなたは『保護された作品』を伝達してはならない。ただし、あなたがそのような協定を締結したり、『パテントライセンス』を授与されたのが2007年3月28日より以前である場合は本節の例外とする。
+
+本許諾書に含まれる一切の記述は、適用可能な特許法の下であなたが利用可能な暗黙のライセンス、その他侵害への防御手段を排除したり制限したりするように解釈されてはならない。
+12. 他者の自由を明け渡してはならない¶
+
+何らかの条件(裁判所の指令や協定など)があなたに課せられ、それが本許諾書の条件と矛盾したとしても、あなたが本許諾書の条件を免れることにはならない。あなたが、『保護された作品』を、本許諾書が課す義務と他の関連した義務の両方を同時に満たすような形で伝達できないのであれば、結果としてあなたがそれを伝達することは全く不可能ということになる。例えばあなたが、自分が『プログラム』を伝達した人々がさらに伝達を行う場合には、彼らからロイヤルティを徴収する、というような義務を負う条項に同意していた場合、あなたがそういった条項と本許諾書の両方を満たすには、『プログラム』の伝達を完全に止めてしまうしかないだろう。
+13. GNU Affero 一般公衆利用許諾書との利用¶
+
+本許諾書に含まれる他の条件に関わらず、あなたには、『保護された作品』を GNU Affero 一般公衆利用許諾書バージョン3の下で許諾された作品とリンクまたは結合して単一の結合物とし、その結果物を伝達する許可が与えられる。本許諾書の条項は『保護された作品』である部分に関してはそのまま適用されるが、結合物それ自体としては、GNU Affero 一般公衆利用許諾書の第13項が規定する、ネットワークを介したやりとりに関する特殊な条件も適用されることになる。
+
+(訳注: 訳出時点では、GNU Affero GPLは改定作業が依然続いており、確定バージョンはリリースされていない。 http://gplv3.fsf.org/agplv3-dd2-guide.htmlを参照せよ。)
+14. 本許諾書の改訂されたバージョン¶
+
+フリーソフトウェア財団は、改訂された、あるいは新しいバージョンの GNU 一般公衆利用許諾書を折りに触れて発行することができる。そのような新バージョンは、その精神においては現在のバージョンと似たものになるだろうが、細部については新たな問題や懸念を解決すべく異なるものになるだろう。
+
+それぞれのバージョンには、見分けがつくようなバージョン番号が振られている。『プログラム』に、ある特定のバージョン番号が振られた GNU 一般公衆利用許諾書「かそれ以降のバージョンのいずれか(or any later version)」が適用されると指定されていた場合、あなたは指定された番号のバージョンか、それ以降にフリーソフトウェア財団によって発行されたいずれかのバージョンのどちらの利用条件に従うかを選ぶことができる。『プログラム』が本許諾書のバージョン番号を指定していなかった場合には、あなたはフリーソフトウェア財団がそれまでに発行したバージョンの中からどれを選択しても構わない。
+
+(訳注: 日本語訳のバージョンは日付で管理している。冒頭を見よ。)
+
+『プログラム』において、GNU 一般公衆利用許諾書の将来のバージョンのうちどれが適用されうるかは代理人が決定できる、と指定されていた場合、その代理人が、あるバージョンを受諾すると述べた公的な声明は、あなたに対し、その『プログラム』に関してそのバージョンのGNU GPLを選ぶことを永続的かつ正式に許可するのと等しい。
+
+本許諾書の今後のバージョンでは、あなたに追加的な、または従来とは異なった形での許可を与えるかもしれない。しかしながら、作者や『コピーライト』保有者に対し、あなたが以降のバージョンに従うことを選んだ結果として、追加的な義務が課せられることはない。
+15. 保証の否認¶
+
+『プログラム』には、適用可能な法で許可されている範囲において何の保証もない。書面で述べられていない限り、『コピーライト』保有者やその他の当事者は『プログラム』を「あるがまま(as is)」で、明示的、暗示的を問わず、いかなる種類の保証もなく提供する。この保証には、商用可能性や特定目的への適合性の暗黙的保証が含まれるが、これらに限定されない。『プログラム』の質や性能に関するリスクはすべてあなたに帰属する。『プログラム』に問題があると判明した場合、あなたは必要なすべての対応、補修、修正にかかる費用を負うものとする。
+16. 責任の限定¶
+
+適用可能な法において義務づけられるか、書面による同意がない限り、『コピーライト』保有者あるいはその他『プログラム』を上記で許可された通りに改変あるいは伝達する当事者は、たとえそうした保有者や他の当事者が損害が発生する可能性について事前に通知されていたとしても、あなたに対して損害賠償責任を有することはない。ここでいう損害には、『プログラム』の利用あるいは利用できないことから発生した一般的、特殊的、偶然的、必然的な損害のすべてが含まれる(データの消失やデータの不正確な解釈、あなたや第三者によって被った、あるいは『プログラム』が他のプログラムといっしょにうまく動作しなかったために引き起こされた損害などが含まれるが、これらに限定されない)。
+17. 第15項と第16項の解釈について¶
+
+上記のような保証の否認や責任の限定が、特定国内においてそういった条項が指定する通りの法的効力を持ち得ない場合、再審裁判所は、『プログラム』に関連したすべての民事責任の絶対的棄権に最も近く肉薄する国内法を適用すべきである。ただし、報酬の見返りとして責任の保証や引き受けが『プログラム』のコピーに付随する場合は除く。 
+
+
+
+
+GNU 一般公衆利用許諾書 (GNU General Public License)¶
+
+バージョン3、2007年6月29日
+日本語訳、2007年9月5日
+
+Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+
+(訳: 本ライセンス文書を、一字一句忠実に複製、頒布することは許可する。しかし変更は認めない。)
+
+This is an unofficial translation of the GNU General Public License into Japanese. It was not published by the Free Software Foundation, and does not legally state the distribution terms for software that uses the GNU GPL--only the original English text of the GNU GPL does that. However, we hope that this translation will help Japanese speakers understand the GNU GPL better.
+
+(訳: 以下はGNU General Public Licenseの非公式な日本語訳です。これはフリーソフトウェア財団 (Free Software Foundation)によって正式に発表されたものではなく、GNU GPLが適用されたソフトウェアの頒布条件を法的に有効な形で述べたものではありません。頒布条件としては、GNU GPLの英語版テキストで指定されているもののみが有効です。しかしながら、私たちはこの翻訳が、日本語を使用する人々にとってGNU GPLをより良く理解する助けとなることを望んでいます。)
+
+翻訳は八田真行 <mhatta@gnu.org>が行った。原文はhttp://www.gnu.org/licenses/gpl-3.0.html である。誤訳の指摘や訳の改善案を歓迎する。なお、日本語訳の利用条件は原文に準ずる。
+はじめに¶
+
+GNU 一般公衆利用許諾書は、ソフトウェアやその他の種類の著作物のための、フリーかつコピーレフトを主張するライセンスです。
+
+ソフトウェアやその他の実用的著作物向けのライセンスの大半は、あなたから著作物を共有したり変更したりする自由を奪い去るよう設計されています。それらとは対照的に、GNU 一般公衆利用許諾書は、あなたに対してあるプログラムの全てのバージョンを共有、変更する自由を保証すること、すなわち、そのソフトウェアがそのユーザすべてにとってフリーでありつづけることを保証することを目的としています。私たちフリーソフトウェア財団(Free Software Foundation)は、GNU 一般公衆利用許諾書を私たちのソフトウェアの大半に適用しています。その作者が私たちと同様の方法で公開するならば、他のいかなる著作物にも適用することが可能です。もちろん、あなたのプログラムにも適用することができます。
+
+私たちがフリーソフトウェアについて語るとき、私たちは自由について言及しているのであって、価格は問題にしていません。私たちが用意した一般公衆利用許諾書の数々は、フリーソフトウェアのコピーを頒布する(そして希望によっては頒布に際して手数料を要求する)自由をあなたに保証すべく設計されています。すなわち、ソースコードを受領するか、望めばそれを手に入れられるということ、ソフトウェアを変更し、その一部を新たなフリープログラムで利用することができるということ、そしてこうしたことが可能であることをあなたが知っているということが保証されるのです。
+
+(訳注: GNU GPL以外の一般公衆利用許諾書として、GNU AGPLとGNU LGPLが用意されている。)
+
+あなたの権利を守るため、私たちは誰か他人が上記のようなあなたの権利を否定したり、権利を放棄するように求めることを防ぐ必要があります。そこで、あなたがソフトウェアのコピーを頒布したり改変したりする場合、あなたにはある種の責任が発生します。それは、他人の自由を尊重するという責任です。
+
+たとえば、本許諾書が適用されたプログラムのコピーをあなたが頒布する場合、それが無料であろうと手数料を取る場合であろうと、あなたは受領者たちに、あなた自身が受け取ったのと同じ自由を渡さなければなりません。あなたは、彼らもまた、ソースコードを受領するか後に得られることを保証しなければなりません。そしてあなたは、彼らに本許諾書の条項を示し、彼らの権利について彼らに知らしめなければなりません。
+
+GNU GPLを利用する開発者は、あなたの権利を2段階の手順を踏んで守ります。その手順とは、(1) ソフトウェアに著作権を主張し、(2) あなたに本許諾書を提示して、ソフトウェアを複製、頒布、または改変する法的な許可を与える、というものです。
+
+開発者や作者を守るため、GPLでは、このフリーソフトウェアには何の保証もないということを明確に説明しています。ユーザと開発者両方の便宜のため、 GPLでは改変されたバージョンには変更された旨を印づけるよう要求しており、改変されたバージョンの問題が、誤って以前のバージョンの作者に帰せられることがないようにしています。
+
+一部の機器は、それらに収録されたソフトウェアを改変した上で再びインストールしたり、実行したりするために必要なアクセスを、製造者には拒否しないにもかわらずユーザに対しては拒否するよう設計されています。これは、ユーザが自らの有するソフトウェアを変更する自由を守るというGPLの目的とは、根本的に相容れません。このような技術の濫用は、往々にして個人使用向けの製品の分野で見られるものですが、まさにこのような分野こそ、こうした慣行が最も容認しがたいものとなるのです。そこで私たちは、このバージョンのGPLを、そうした製品においてこの種の慣行を禁止するように設計しました。もし同種の問題が他の領域にまで相当程度広がってきた場合には、私たちはユーザの自由を守るためのに必要とされるだけ、GPLの将来のバージョンにおいてこの規定をそうした領域にも拡大すべく準備を整えています。
+
+最後に、すべてのプログラムはソフトウェア特許によって絶え間なく脅かされています。およそ国家は、特許が汎用コンピュータにおけるソフトウェアの開発と利用を制限することを認めるべきではありません。しかし、そういったことを認めてしまっている地域においては、私たちは、特許がフリーなプログラムに適用され、実質的にプログラムがプロプライエタリにされてしまうという特別な脅威を避けたいと思います。こうした事態を防ぐために、GPLでは、プログラムを非フリーとするために特許を使うことはできないということを保証します。
+
+(訳注: 本許諾書で「プロプライエタリ (proprietary)」とは、ソフトウェアの利用や再頒布、改変が禁止されているか、許可を得ることが必要とされているか、あるいは厳しい制限が課せられていて自由にそうすることが事実上できなくなっている状態のことを指す。詳しくはhttp://www.gnu.org/philosophy/categories.ja.html#ProprietarySoftware をを参照せよ。)
+
+複製、頒布、改変に関する正確な利用条件は以下で述べていきます。
+利用条件 (TERMS AND CONDITIONS)¶
+0. 定義¶
+
+「本許諾書」(The License)とは、GNU 一般公衆利用許諾書のバージョン3を指す。
+
+「『コピーライト』」(Copyright)とは、いわゆる著作権のみならず、半導体マスクのようなその他の作品に適用される、著作権に類似した法的権利をも意味する。
+
+(訳注: この規定により、本許諾書は著作権法で保護されたいわゆる「著作物」よりも広い範囲をカバーすることになる。よってこの訳のライセンス本文中においては、work(s)に「著作物」ではなく「作品」という訳語を宛てることにした。)
+
+「『プログラム』」(The Program)とは、本許諾書の下でライセンスされた、『コピーライト』が主張可能な作品すべてを意味する。個々のライセンシーは「あなた」として表現される。ライセンシーは個人でも組織でも構わない。
+
+ある作品の「改変」(modify)とは、その作品の全体ないし一部を、『コピーライト』の許可を必要とするようなやり方で複製ないし翻案することを意味する。ただし、完全に同一なコピーを作成する場合は除く。改変の結果出来た作品は、以前の作品の「改変されたバージョン」(modified version)、または、以前の作品を「基にした」(based on)作品と呼ばれる。
+
+「『保護された作品』」(covered work)とは、改変されていない『プログラム』か、『プログラム』を基にした作品のいずれかを指す。
+
+ある作品の「普及」(propagate)とは、コンピュータ上で実行すること、または私的なコピーを改変することを除き、適用可能な『コピーライト』法規の下で許可無く行うと、権利侵害として、直接的、あるいは間接的にあなたが責任を問われる何らかの行為を意味する。普及には、複製、頒布 (改変の有無を問わない)、公衆への利用可能化が含まれ、またいくつかの国々では他の活動も含まれる可能性がある。
+
+ある作品の「伝達」(convey)とは、第三者がコピーを作成ないし受領するのを可能とする普及行為すべてを意味する。ただし、コンピュータネットワーク越しにユーザとやりとりするだけで、コピーの転送は伴わない場合は、伝達ではない。
+
+対話的なユーザインターフェースが「『適切な法的告知』」(Appropriate Legal Notices)を表示するという場合、そのインターフェースは (1)適切な『コピーライト』告知を表示し、(2)ユーザに対して、その作品には何の保証もない(別途保証が提供されている場合は除く)ということ、ライセンシーはその作品を本許諾書の下で伝達できるということ、そして本許諾書のコピーを見るにはどうしたらよいかということを便利かつ顕著に視認できるような機能を含むものとする。もしインターフェースが、メニューのようなユーザコマンドやオプションの一覧を表示するならば、その一覧中には上記の基準を満たすようなアイテムが目立つように含まれていなければならない。
+1. ソースコード¶
+
+ある作品の「ソースコード」(source code)とは、その作品に改変を加えるに当たって好ましいと考えられる形式のことである。「オブジェクトコード」 (object code)とは、作品がとりうるソースコード以外の形式すべてを意味する。
+
+「標準インターフェース」(Standard Interface)とは、標準化団体として認知された組織によって定義された公式な標準か、ある特定のプログラミング言語向けに指定されたインターフェースの場合には、その言語を利用する開発者の間で広く使われているインターフェースのことを指す。
+
+実行可能な作品の「『システムライブラリ』」(System Libraries)とは、 (a)「主要コンポーネント」(Major Component) の頒布物に通常含まれるが、その主要コンポーネントの一部ではなく、かつ(b)作品をその「主要コンポーネント」といっしょに利用することを可能にする、あるいは公衆にとってソースコード形式で利用可能な実装がひとつは存在する標準インターフェースを提供するためにのみ機能するものすべてを意味する。ただし、全体としての作品そのものは除く。ここでいう「主要コンポーネント」とは、実行可能な作品がその上で実行されるある特定のオペレーティングシステム (そういったものが必要ならば)の主要で不可欠な一部分(カーネルやウィンドウシステムなど)、あるいはその作品を作成するのに使われるコンパイラ、実行するのに使われるオブジェクトコードインタプリタなどを意味する。
+
+オブジェクトコード形式の作品に「『対応するソース』」(Corresponding Source)とは、その作品を生成、インストール、(実行可能な作品に関しては)オブジェクトコードを実行、または作品を改変する上で必要とされるソースコードのすべてを意味する。この場合、そうした活動をコントロールするためのスクリプトは『対応するソース』に含まれるが、その作品にとっての『システムライブラリ』や、先ほど列挙した活動を行う上で改変されることなく利用されるものの作品の一部ではない、汎用のツールや一般的に利用可能なフリープログラムは除外される。例えば『対応するソース』には、その作品のソースファイルと連携するインターフェース定義ファイルに加え、共有ライブラリや動的にリンクされた下位プログラムと作品のその他の部分との間での親密なデータのやりとりやコントロールフローなどのために、その作品が設計上明確に必要とする、そうした共有ライブラリや下位プログラムのソースコードなどが含まれる。
+
+『対応するソース』には、ユーザが『対応するソース』の他の部分から自動的に再生成できるものを含む必要はない。
+
+ソースコード形式の作品にとっての『対応するソース』とは、その作品そのものである。
+2. 基本的な許可¶
+
+本許諾書の下で認められるすべての権利は、『プログラム』に主張される『コピーライト』の条項に基づき授与されるものであり、ここで述べられた条件が満たされている限り覆すことはできない。本許諾書は、改変されていない『プログラム』をあなたが無制限に実行することを許可し、明示的に確約する。『保護された作品』を実行することから得られた出力結果は、その出力内容が『保護された作品』を構成する場合のみ本許諾書で保護される。本許諾書は、あなたが有するフェアユースまたはその同等物の権利を、『コピーライト』法規によって提供される通りに承認する。
+
+その他の状況においてあなたのライセンスが有効である限り、『保護された作品』の、伝達を伴わない作成、実行、および普及は無条件に行うことができる。他者にあなた専用の改変を行わせる、あるいは他者にあなたがそういった作品を実行するための機能を提供させるということが唯一の目的であれば、『保護された作品』を他者に伝達することができる。ただしその場合、あなたが『コピーライト』を支配していない部分すべての伝達に関しては、本許諾書の条項に従わなければならない。従って、あなたのために『保護された作品』を作成または実行する者は、専らあなたのためだけに、あなたの監督と支配の下で、あなたとの関係の範囲外ではあなたが『コピーライト』を有する一部分のいかなるコピーをも作成することを禁止するという条件の下で行わなければならないということになる。
+
+上記以外のあらゆる状況下においては、伝達は以下で述べる条件の下でのみ許可される。再許諾は認められない。下記第10項により、再許諾は必要ないからである。
+3. ユーザの法的権利を、技術的保護手段の回避を禁ずる法律から守る¶
+
+『保護された作品』は、 1996年12月20日に採択されたWIPO著作権条約第11項の下での義務を満たす適用可能な法のいずれか、あるいはそれに類似の法が、回避の禁止または制限の対象として規定する、「効果的な技術的手段」 (effective technological measure)の一部として見なされてはならない。
+
+(訳注: WIPO著作権条約については、http://www.cric.or.jp/db/article/wch.html 等を参照せよ。)
+
+あなたが『保護された作品』を伝達する場合、『保護された作品』に関して本許諾書の下で権利を行使することにより、技術的手段の回避に影響が出る範囲において、そのような手段の回避を禁じるいかなる法的権力をも放棄することになる。また、あなたはその作品のユーザに対して、技術的手段の回避を禁じるためにあなたや第三者の法的権利を強制するための手段として、その作品の動作や改変を制限するいかなる意図も否認することになる。
+4. 一字一句忠実なコピーの伝達¶
+
+あなたは、自分が受領した『プログラム』のソースコードと一字一句同じコピーであれば、いかなる媒体でも伝達することができる。ただしその場合、あなたはそれぞれのコピーにおいて、目立つように、かつ適切な形で、ふさわしい『コピーライト』告知を掲載しなければならない。すなわち、本許諾書と、下記第7項に従い追加された非許可的条項のすべてがそのコードに適用される旨の告知を掲載し、あらゆる保証が存在しない旨の告知をすべてそのまま保全し、かつ『プログラム』の受領者すべてに、『プログラム』といっしょにこの許諾書のコピーを与えなければならない。
+
+あなたは、自分が伝達するコピーのそれぞれに関していかなる価格を付けても良いし、無料で伝達しても構わない。また、報酬を取ってサポートや保証保護 (warranty protection)を提供しても良い。
+5. 改変されたバージョンのソースの伝達¶
+
+あなたは、『プログラム』を基にした作品、あるいはそうした作品を『プログラム』から作成するための改変点を、上記第4項の規定に従ってソースコード形式で伝達することができる。ただしその場合、あなたは以下に示す条件のすべてを満たさなければならない:
+
+    * a) 作品には、あなたが作品を改変したということと、改変に関連した日時を記述した告知を目立つように載せなければならない。
+    * b) 作品には、それが本許諾書と、下記第7項に従って追加された条件すべての下で公開されていることを記述した告知を目立つように載せなければな らない。この条件は、上記第4項における「告知をすべてそのまま保全」するための条項を改変する。
+    * c) 作品の全部分を、総体として、コピーを所有するに至った人全員に、本許諾書の下でライセンスしなければならない。そこで、本許諾書は、本許諾書第7項に基づく適用可能な追加的条項のすべてとともに、作品全体に、すなわちその全部分に、それらがどのようにパッケージされているかに関わらず適用されることになる。本許諾書は、これ以外のやり方には作品をライセンスする許可を与えないが、あなたが本許諾書以外で別途許可を得ていた場合には、それによって得られた許可まで無効とするものではない。
+    * d) 改変された作品が対話的なユーザインターフェースを有する場合、それらのインターフェースは『適切な法的告知』を表示しなければならない。ただし、『プログラム』に元々『適切な法的告知』を表示しない対話的なインターフェースがある場合、あなたの作品で表示するようにする必要はない。 
+
+一巻の記憶装置の中か頒布媒体上で、『保護された作品』と、本来『保護された作品』の拡張ではなく、『保護された作品』とより大規模なプログラムを形成するような形で結合されているわけでもないその他の分離かつ独立した作品とをまとめた編集物は、編集作業とそれに由来する『コピーライト』が、個々の作品が許可する範囲を越えて編集物のユーザの作品へのアクセスや法的権利を制限するのに使われない限り、「集積物」(aggregate)と呼ばれる。単に『保護された作品』を集積物に含めるだけでは、その集積物の他の部分にまで本許諾書が適用されるということにはならない。
+6. ソース以外の形式における伝達¶
+
+あなたは、オブジェクトコード形式の『保護された著作物』を、上記第4項および第5項の規定に従って伝達することができる。ただしその場合、あなたは機械読み取り可能な『対応するソース』も本許諾書の条件に従って、以下のいずれかの方法で伝達しなければならない。
+
+    * a) オブジェクトコードを物理的製品(物理的頒布媒体を含む)で、あるいはそれに組み込んで伝達する。その際、『対応するソース』を、ソフトウェア のやりとりで一般的に使われる耐久性のある物理的媒体に固定していっしょに頒布する。
+    * b) オブジェクトコードを物理的製品(物理的頒布媒体を含む)で、あるいはそれに組み込んで伝達する。その際、最低でも3年間、あるいはあなたがその製品モデルに補修用部品やカスタマーサポートを提供する限り有効な、書面 による申し出を添付する。その申し出には、(1) オブジェクトコードを所有する者すべてに対して、その製品に含まれるソフトウェアのうち本許諾書で保護されるものすべてに『対応するソース』のコピーを、ソフトウェアのやりとりで一般的に使われる耐久性のある物理的媒体で頒布する旨を記載する。その際、物理的にこのソースの伝達を行うのにかかる正当なコスト以上の価格を要求してはならない。あるいは、(2) 『対応するソース』を無料でネットワークサーバから複製するためのアクセスを提供する旨を記載する。
+    * c) オブジェクトコードの個々のコピーを、対応するソースを提供するという書面による申し出のコピーといっしょに伝達する。この選択肢は特別な場合、かつ非商業的な場合のみに、そしてあなたがオブジェクトコードを上記小項 6bに合致した申し出といっしょに受領した場合にのみに認められる。
+    * d) オブジェクトコードを、指定の場所から複製するためのアクセスを提供することによって伝達し、『対応するソース』に対しても同じ場所を通じて同じ方法で複製するための同等のアクセスを提供する。伝達は無料でも手数料を課しても構わないが、『対応するソース』に対して追加的な課金を行ってはならない。受領者に対して、『対応するソース』をオブジェクトコードといっしょに複製することを義務づける必要はない。オブジェクトコードの複製元がネットワークサーバの場合、対応するソースは同等の複製機能をサポートする異なったサーバ(あなたか第三者が運営)上にあっても良い。その場合、オブジェクトコードの傍らに、『対応するソース』はどこで見つけられるかを明確に指示しておかなければならない。どのサーバが『対応するソース』をホストするかに関わらず、あなたは『対応するソース』がこれらの条 項を満たすために必要なかぎり利用可能であることを保証する責任がある。
+    * e) オブジェクトコードをピア・ツー・ピア伝送を使って伝達する。ただしこの場合、あなたは上記小項6dに従い、その作品のオブジェクトコードと 『対応するソース』がどこで一般公衆に無料で提供されるのかということを他のピアに知らせておかなければならない。 
+
+オブジェクトコードの分離した一部であり、そのソースコードが『対応するソース』から『システムライブラリ』として除外されているものは、オブジェクトコード作品を伝達する場合に含める必要はない。
+
+「ユーザ製品」(User Product)とは、(1)「コンシューマ製品」(consumer product)、すなわち、個人、子供、あるいは家庭用に通常使用される有形個人資産すべてか、あるいは(2)居住所における導入を目的に設計ないし販売されるものすべてを指す。ある物品がコンシューマ製品であるかを決定する際疑義がある場合には、極力範囲を広げる方向で決定されるべきである。ここで、ある特定のユーザによって受領されたある特定の製品にとっての「通常使用」 (nomally used)とは、その種の製品において典型的な、あるいは一般的な利用のことであり、その特定のユーザが置かれた状況や、その特定のユーザがその製品を実際にどう使っているか、どう使うことを予期しているか、あるいは予期されているかとは関係ない。その製品に相当な商業的、産業的または非コンシューマ的な利用法があったとしても、そうした利用がその製品の唯一重要な利用形態を代表するものでない限り、その製品はコンシューマ製品である。
+
+ユーザ製品の「『インストール用情報』」(Installation Information)とは、ユーザ製品内の『保護された作品』に関して、『対応するソース』の改変されたバージョンから得られる『保護された作品』の改変されたバージョンを、インストール、実行するために必要な手法、手順、認証キーやその他の情報すべてを意味する。この情報は、改変されたオブジェクトコードの継続的な動作が、改変が為されたということによってのみ拒否されたり妨害されることが決してないことを保証するのに十分なものでなければならない。
+
+本節の下において、作品をユーザ製品の内で、またはユーザ製品と共に、あるいは特にユーザ製品での利用を念頭においてオブジェクトコードで伝達し、またその伝達がユーザ製品の受領者への所有と利用の権利の永遠ないし有期の移転の一部として起こる場合(移転がどのように行われるかは問わない)、この条項の下で『対応するソース』は『インストール用情報』と共に提供されなければならない。しかしこの条件は、あなたと第三者のいずれもが改変されたオブジェクトコードをユーザ製品にインストールする能力を有していない際には適用されない(例えば、作品がROMにインストールされている場合)。
+
+『インストール用情報』を提供する条件には、受領者によって改変ないしインストールされた作品、あるいはそうした作品が改変ないしインストールされたユーザ製品に対し、サービスや保証、アップデートを提供しつづけるという条件は含まれない。改変自体がネットワークの運用に実質的かつ有害な影響をもたらし、ネットワークを介したコミュニケーションのプロトコルや規則に違反する場合には、ネットワークアクセスを拒否しても構わない。
+
+伝達される『対応するソース』や提供される『インストール用情報』が本節を満たすためには、それらが公に文書化された形式で(かつ公衆に対してソースコード形式で利用可能な実装とともに)提供されなければならない。この場合、これらの圧縮展開や読み込み、複製に特別なパスワードやキーを必要としてならない。
+7. 追加的条項¶
+
+「追加的許可」(Additional permissions)とは、本許諾書が課す条件に一つかそれ以上の例外を設けることにより、本許諾書の条項を補足する条項のことである。『プログラム』全体に適用可能な追加的許可は、適用可能な法の下でそれらが有効である限り、あたかもそれらが本許諾書に含まれているかのように扱われなければならない。追加的許可が『プログラム』の一部にのみ適用される場合、その部分に関してはそういった追加的許可の下で別途利用可能だが、『プログラム』全体としては追加的許可に関わりなく本許諾書によってのみ管理される。
+
+あなたが『保護された作品』のコピーを伝達する場合、あなたは追加的許可をそのコピー、あるいはその一部から削除することを選択できる (追加的許可は、あなたが作品をある種の形で改変する際には、そうした許可自身の削除を要求するような形で書かれてもよい)。あなたは、あなたによって『保護された作品』に追加され、あなたが適切な『コピーライト』許可を有するか、与えることができる限り、その一部分に追加的許可を設定することができる。
+
+本許諾書の他の条件に関わらず、あなたが『保護された作品』に追加した一部分について(その部分の『コピーライト』保有者らによって正式に許可されていれば)、本許諾書の条項を、以下に示す条項で補足することができる:
+
+    * a) 本許諾書第15項および第16項の条項とは異なった形で保証の否認や責任の限定を主張する。あるいは、
+    * b) 追加した一部分において、明示的で妥当な法的告知や作者特定の保全、またはそれを含む作品において『適切な法的告知』の表示を要求する。あるいは、
+    * c) 追加した一部分の出自を不当に表示することを禁じるか、あるいはそのような一部分の改変されたバージョンはオリジナルのバージョンとは異なっ ているということを適切な方法で印づけることを要求する。あるいは、
+    * d) その一部分のライセンサーや作者の名前を、宣伝目的で利用することを制限する。あるいは、
+    * e) 商品名や商標、サービスマークの利用に関して、商標法に従い権利を授与することを拒否する。あるいは、
+    * f) その一部分(あるいはその改変されたバージョン)を伝達する者に、受領 者への責任に関して契約上の引き受けがあり、そうした責任が直接的にそういったライセンサーや作者にまで課せられる場合、その一部分のライセンサーや作者の免責を要求する。 
+
+他の非許可的な追加的条項は下記第10項が意味するところの「さらなる権利制限」(further restrictions)とみなされる。あなたが受領した『プログラム』、あるいはその一部に、それが本許諾書とともにさらなる権利制限である条項によっても管理されていると述べた告知が含まれている場合には、あなたはそういった条項を削除して構わない。あるライセンス文書にさらなる権利制限がふくまれているが、しかし本許諾書の下での再許諾や伝達を許可しているならば、あなたはそのライセンス文書の条項によって管理されている一部分を『保護された作品』に追加することができる。ただしその場合、さらなる権利制限はそのような再許諾や伝達では無効としなければならない。
+
+あなたが本節に従って『保護された著作物』に条項を追加した場合、あなたは関係するソースファイル中に、それらのファイルに適用される追加的条項に関する声明、あるいは適用可能な条項を見つけることができる場所を示す告知を掲載しなければならない。
+
+追加的条項は、それが許可的であろうと非許可的であろうと、別途書面化されたライセンスという形式で述べられてもよいし、本許諾書への例外として述べられてもよい。上記の要件はどちらの場合でも適用される。
+8. 終了¶
+
+あなたは『保護された作品』を、本許諾書の下で明示的に提供されている場合を除いて、普及、または改変してはならない。それ以外に『保護された作品』を普及、または改変しようとする試みはすべて無効であり、本許諾書の下であなたに認められた権利(下記第11項の第3段落に従い授与されたパテントライセンスすべてを含む)を自動的に終了させることになる。
+
+しかしながら、あなたが本許諾書への違反をすべて中止するならば、あなたがある特定の『コピーライト』保有者から得たライセンスは、(a)その『コピーライト』保有者が明白かつ決定的にあなたへのライセンスを終了させるか、あるいはさせないまでは暫定的に、(b)その『コピーライト』保有者が、あなたに対し違反について、何らかの正当な手段によりライセンス停止後60日以内に通知することができなかった場合には永続的に、回復される。
+
+加えて、あなたがある特定の『コピーライト』保有者から得たライセンスは、その『コピーライト』保有者があなたに対して違反を何らかの正当な手段で通知し、それより前にその『コピーライト』保有者から、(当該作品に限らずその『コピーライト』保有者の作品のいずれかに関して)本許諾書に関する違反の通知を受領したことがなく、さらにあなたがその通知を受領してから30日以内に違反を正した場合、永続的に回復される。
+
+本節に従いあなたの権利が終了した場合でも、本許諾書に従ってあなたからコピーや権利を受領した当事者が得た許諾は終了しない。あなたの権利が終了され、永続的に回復されなかった場合には、あなたは同じライセンス対象に関し下記第10項に従って新たにライセンスを受領する資格を失うものとする。
+9. コピーの所有に必要とされない受諾¶
+
+あなたは、『プログラム』のコピーを受領あるいは実行するために本許諾書を受諾する必要はない。コピーを受領するためにピア・ツー・ピア伝送を使った結果としてのみ発生する『保護された作品』の付随的な普及も、同様に受諾を必要としない。しかしながら、他の場合においては、本許諾書以外にあなたに対して『保護された作品』の普及や改変をする許可を認めるものはない。これらの行為は、本許諾書を受諾しない限り『コピーライト』を侵害することになる。そこで、『保護された作品』を改変あるいは普及することにより、あなたはそうした行為を行うために本許諾書を受諾したということを示したことになる。
+10. 下流の受領者への自動的許諾¶
+
+あなたが『保護された作品』を伝達するたびに、受領者は自動的にオリジナルのライセンサーから、本許諾書に従いその作品を実行、改変、普及するライセンスを得る。なお、あなたには第三者が本許諾書に従うことを強制する責任はない。
+
+「主体取引」(entity transaction)とは、ある組織そのもの、ないしその組織の実質的に全ての資産の支配権が移転するか、あるいは組織の細分化や合併が行われるような取引を指す。もし主体取引の結果として『保護された作品』の普及が起こった場合、作品のコピーを受領したそれぞれの取引当事者は、利害関係のある当事者の先任者から、その先任者が前段落に従って有する、あるいは与えることができる、その作品に関するライセンスもまたすべて受領する。加えて個々の取引当事者は、利害関係のある先任者から、その先任者が有しているか、適正な努力によって得ることが可能な限りにおいて、その作品の『対応するソース』の所有権も得る権利を有する。
+
+あなたは本許諾書の下で授与された、あるいは確約された権利の行使に対して、本許諾書が規定する以上のさらなる権利制限を課してはならない。たとえば、あなたはライセンス料、ロイヤルティや他の料金を、本許諾書の下で認められている権利の行使に関して課してはならない。また、あなたは『プログラム』やその一部の作成、利用、販売、販売の申し出、取り込みによって何らかのパテントクレームが侵害されたとして、訴訟(訴訟における反対請求ないし反訴を含む)を開始してはならない。
+11. 特許¶
+
+「貢献者」(contributor)とは、本許諾書の下で『プログラム』、あるいは『プログラム』が基にした作品を利用することを正式に許可した『コピーライト』保有者のことを指す。従って、そのようにしてライセンスされた作品は、貢献者による「貢献者バージョン」(contributor version)と呼ばれる。
+
+ある貢献者の「必須パテントクレーム」(essential patent claims)とは、すでに取得しているか、あるいは今後取得する見込みがあるため、その貢献者が現在所有ないし支配していると言える特許のうち、貢献者バージョンに対して、本許諾書で許可されているような作成や利用、販売といった何らかの形の行為を行うことによって侵害される可能性があるパテントクレームのすべてを意味する。ただし、貢献者バージョンをさらに改変した結果としてのみ侵害されるようなクレームは含まれない。この定義において、「支配」には本許諾書が課す条件と整合的なやり方で特許の再許諾を認める権利も含まれる。
+
+個々の貢献者はあなたに対して、その貢献者の必須パテントクレームに関し、あなたがその貢献者バージョンの内容を作成、利用、販売、販売の申し出、取り込み、その他実行、改変、普及するために必要な、非排他的で全世界的に有効、かつロイヤルティフリーのパテントライセンスを授与する。
+
+以下の3段落において「『パテントライセンス』」とは、ある特許を実施しないという明示的な協定やコミットメントのすべてを指す(例えば、ある特許の実施に対する明示的な許可や、特許侵害訴訟を提起しないという誓約など)。そのような『パテントライセンス』をある当事者に「授与」するとは、その当事者と特許を実施しないという協定やコミットメントを結ぶことを意味する。
+
+もしあなたが、『保護された作品』の伝達を、それがある『パテントライセンス』に依存しており、よってその作品の『対応するソース』は、すべての人にとって、公衆が利用可能なネットワークサーバや他の容易にアクセス可能な手段を通じ、無料かつ本許諾書に従って複製可能ではないということを知りながら行うならば、あなたは (1)『対応するソース』も同様に利用可能にするか、 (2)この特定の作品に関して『パテントライセンス』から得られる便益を自ら剥奪するか、あるいは(3)下流の受領者に対しても、本許諾書の条項と整合的な形で、『パテントライセンス』が拡大されるように計らうかのいずれかを行わなければならない。ここで「『パテントライセンス』に依存するのを知りながら」というのは、あなたが『保護された作品』をある国で伝達すること、あるいはあなたの受領者が『保護された著作物』をある国で利用することが、『パテントライセンス』を授与されない限り、その国において、あなたにとってそれが有効だと信じるだけの理由がある一つかそれ以上の同定可能な特許を侵害するということを実際に知っているということである。
+
+ある一対一の取引や協定に基づき、あるいは関連して、あなたが『保護された作品』の伝達、または伝達によって引き起こされる普及を行い、その際『保護された作品』を受領した一部の当事者に対して、『保護された作品』の特定のコピーの利用、普及、改変、または伝達を正式に許可するような『パテントライセンス』を授与するならば、あなたが授与した『パテントライセンス』は『保護された作品』やそれを基にした作品のすべての受領者にまで自動的に拡大されることになる。
+
+ある『パテントライセンス』が「差別的」(discriminatory)であるとは、本許諾書の下で明確に認められた一つかそれ以上の権利を、『パテントライセンス』がカバーする範囲内に含まなかったり、そうした権利の行使を禁じたり、あるいは権利を行使しないことを条件として課すようなものである場合を指す。あなたを一方の当事者とし、ソフトウェアの頒布を生業とする第三者との間で、あなたは第三者に対し、作品を伝達する活動の程度に基づいて支払いを行う一方、第三者は、あなたから『保護された作品』を受領したすべての当事者に対して「差別的」な『パテントライセンス』を、(a)あなたが伝達した『保護された作品』のコピー(またはそうしたコピーから作成されたコピー)に対して、または(b)『保護された作品』を含む特定製品や編集物を、主要な、あるいは関連した対象として授与する、というような協定を結んでいる場合、あなたは『保護された作品』を伝達してはならない。ただし、あなたがそのような協定を締結したり、『パテントライセンス』を授与されたのが2007年3月28日より以前である場合は本節の例外とする。
+
+本許諾書に含まれる一切の記述は、適用可能な特許法の下であなたが利用可能な暗黙のライセンス、その他侵害への防御手段を排除したり制限したりするように解釈されてはならない。
+12. 他者の自由を明け渡してはならない¶
+
+何らかの条件(裁判所の指令や協定など)があなたに課せられ、それが本許諾書の条件と矛盾したとしても、あなたが本許諾書の条件を免れることにはならない。あなたが、『保護された作品』を、本許諾書が課す義務と他の関連した義務の両方を同時に満たすような形で伝達できないのであれば、結果としてあなたがそれを伝達することは全く不可能ということになる。例えばあなたが、自分が『プログラム』を伝達した人々がさらに伝達を行う場合には、彼らからロイヤルティを徴収する、というような義務を負う条項に同意していた場合、あなたがそういった条項と本許諾書の両方を満たすには、『プログラム』の伝達を完全に止めてしまうしかないだろう。
+13. GNU Affero 一般公衆利用許諾書との利用¶
+
+本許諾書に含まれる他の条件に関わらず、あなたには、『保護された作品』を GNU Affero 一般公衆利用許諾書バージョン3の下で許諾された作品とリンクまたは結合して単一の結合物とし、その結果物を伝達する許可が与えられる。本許諾書の条項は『保護された作品』である部分に関してはそのまま適用されるが、結合物それ自体としては、GNU Affero 一般公衆利用許諾書の第13項が規定する、ネットワークを介したやりとりに関する特殊な条件も適用されることになる。
+
+(訳注: 訳出時点では、GNU Affero GPLは改定作業が依然続いており、確定バージョンはリリースされていない。 http://gplv3.fsf.org/agplv3-dd2-guide.htmlを参照せよ。)
+14. 本許諾書の改訂されたバージョン¶
+
+フリーソフトウェア財団は、改訂された、あるいは新しいバージョンの GNU 一般公衆利用許諾書を折りに触れて発行することができる。そのような新バージョンは、その精神においては現在のバージョンと似たものになるだろうが、細部については新たな問題や懸念を解決すべく異なるものになるだろう。
+
+それぞれのバージョンには、見分けがつくようなバージョン番号が振られている。『プログラム』に、ある特定のバージョン番号が振られた GNU 一般公衆利用許諾書「かそれ以降のバージョンのいずれか(or any later version)」が適用されると指定されていた場合、あなたは指定された番号のバージョンか、それ以降にフリーソフトウェア財団によって発行されたいずれかのバージョンのどちらの利用条件に従うかを選ぶことができる。『プログラム』が本許諾書のバージョン番号を指定していなかった場合には、あなたはフリーソフトウェア財団がそれまでに発行したバージョンの中からどれを選択しても構わない。
+
+(訳注: 日本語訳のバージョンは日付で管理している。冒頭を見よ。)
+
+『プログラム』において、GNU 一般公衆利用許諾書の将来のバージョンのうちどれが適用されうるかは代理人が決定できる、と指定されていた場合、その代理人が、あるバージョンを受諾すると述べた公的な声明は、あなたに対し、その『プログラム』に関してそのバージョンのGNU GPLを選ぶことを永続的かつ正式に許可するのと等しい。
+
+本許諾書の今後のバージョンでは、あなたに追加的な、または従来とは異なった形での許可を与えるかもしれない。しかしながら、作者や『コピーライト』保有者に対し、あなたが以降のバージョンに従うことを選んだ結果として、追加的な義務が課せられることはない。
+15. 保証の否認¶
+
+『プログラム』には、適用可能な法で許可されている範囲において何の保証もない。書面で述べられていない限り、『コピーライト』保有者やその他の当事者は『プログラム』を「あるがまま(as is)」で、明示的、暗示的を問わず、いかなる種類の保証もなく提供する。この保証には、商用可能性や特定目的への適合性の暗黙的保証が含まれるが、これらに限定されない。『プログラム』の質や性能に関するリスクはすべてあなたに帰属する。『プログラム』に問題があると判明した場合、あなたは必要なすべての対応、補修、修正にかかる費用を負うものとする。
+16. 責任の限定¶
+
+適用可能な法において義務づけられるか、書面による同意がない限り、『コピーライト』保有者あるいはその他『プログラム』を上記で許可された通りに改変あるいは伝達する当事者は、たとえそうした保有者や他の当事者が損害が発生する可能性について事前に通知されていたとしても、あなたに対して損害賠償責任を有することはない。ここでいう損害には、『プログラム』の利用あるいは利用できないことから発生した一般的、特殊的、偶然的、必然的な損害のすべてが含まれる(データの消失やデータの不正確な解釈、あなたや第三者によって被った、あるいは『プログラム』が他のプログラムといっしょにうまく動作しなかったために引き起こされた損害などが含まれるが、これらに限定されない)。
+17. 第15項と第16項の解釈について¶
+
+上記のような保証の否認や責任の限定が、特定国内においてそういった条項が指定する通りの法的効力を持ち得ない場合、再審裁判所は、『プログラム』に関連したすべての民事責任の絶対的棄権に最も近く肉薄する国内法を適用すべきである。ただし、報酬の見返りとして責任の保証や引き受けが『プログラム』のコピーに付随する場合は除く。 
+
diff --git a/dist/trunk/rec10/license.txt b/dist/trunk/rec10/license.txt
new file mode 100755 (executable)
index 0000000..69e51ec
--- /dev/null
@@ -0,0 +1,254 @@
+GNU LESSER GENERAL PUBLIC LICENSE
+
+Version 3, 29 June 2007
+
+Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+
+This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.
+0. Additional Definitions.
+
+As used herein, “this License” refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL” refers to version 3 of the GNU General Public License.
+
+“The Library” refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.
+
+An “Application” is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.
+
+A “Combined Work” is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Version”.
+
+The “Minimal Corresponding Source” for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.
+
+The “Corresponding Application Code” for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.
+1. Exception to Section 3 of the GNU GPL.
+
+You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
+2. Conveying Modified Versions.
+
+If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:
+
+    * a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or
+    * b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.
+
+3. Object Code Incorporating Material from Library Header Files.
+
+The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
+
+    * a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.
+    * b) Accompany the object code with a copy of the GNU GPL and this license document.
+
+4. Combined Works.
+
+You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:
+
+    * a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.
+    * b) Accompany the Combined Work with a copy of the GNU GPL and this license document.
+    * c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.
+    * d) Do one of the following:
+          o 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
+          o 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.
+    * e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.)
+
+5. Combined Libraries.
+
+You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:
+
+    * a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.
+    * b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
+
+6. Revised Versions of the GNU Lesser General Public License.
+
+The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation.
+
+If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.
+
+
+GNU GENERAL PUBLIC LICENSE
+
+Version 3, 29 June 2007
+
+Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+Preamble
+
+The GNU General Public License is a free, copyleft license for software and other kinds of works.
+
+The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
+
+To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
+
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
+
+Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
+
+For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
+
+Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.
+
+Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
+
+The precise terms and conditions for copying, distribution and modification follow.
+TERMS AND CONDITIONS
+0. Definitions.
+
+“This License” refers to version 3 of the GNU General Public License.
+
+“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
+
+“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
+
+To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
+
+A “covered work” means either the unmodified Program or a work based on the Program.
+
+To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
+
+To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
+
+An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
+1. Source Code.
+
+The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
+
+A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
+
+The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
+
+The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
+
+The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
+
+The Corresponding Source for a work in source code form is that same work.
+2. Basic Permissions.
+
+All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
+
+You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
+
+Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
+3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
+
+When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
+4. Conveying Verbatim Copies.
+
+You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
+
+You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
+5. Conveying Modified Source Versions.
+
+You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
+
+    * a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
+    * b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
+    * c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
+    * d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
+
+A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
+6. Conveying Non-Source Forms.
+
+You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
+
+    * a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
+    * b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
+    * c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
+    * d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
+    * e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
+
+A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
+
+A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
+
+“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
+
+If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
+
+The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
+
+Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
+7. Additional Terms.
+
+“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
+
+When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
+
+Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
+
+    * a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
+    * b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
+    * c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
+    * d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
+    * e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
+    * f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
+
+All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
+
+If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
+
+Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
+8. Termination.
+
+You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
+
+However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
+
+Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
+9. Acceptance Not Required for Having Copies.
+
+You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
+10. Automatic Licensing of Downstream Recipients.
+
+Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
+
+An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
+
+You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
+11. Patents.
+
+A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.
+
+A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
+
+Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
+
+In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
+
+If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
+
+If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
+
+A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
+
+Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
+12. No Surrender of Others' Freedom.
+
+If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
+13. Use with the GNU Affero General Public License.
+
+Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
+14. Revised Versions of this License.
+
+The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
+
+If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
+
+Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
+15. Disclaimer of Warranty.
+
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+16. Limitation of Liability.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+17. Interpretation of Sections 15 and 16.
+
+If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
diff --git a/dist/trunk/rec10/n_gram.py b/dist/trunk/rec10/n_gram.py
new file mode 100755 (executable)
index 0000000..f24a097
--- /dev/null
@@ -0,0 +1,120 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+
+import zenhan
+def bigram(str1, str2):
+    str1 = zenhan.toHankaku(str1)
+    str2 = zenhan.toHankaku(str2)
+    str1 = str1.replace(" ", "")
+    str2 = str2.replace(" ", "")
+    """
+    bigramによる単語の近さを計算します。
+    """
+    gram = []
+    if len(str1) < 2:
+        gram.append(str1)
+    else:
+        tmp = str1[0]
+        for x in str1[1:]:
+            gram.append(tmp + x)
+            tmp = x
+    point = 0
+    for x in gram:
+        i = findGram(x, str2)
+        if i > 0:
+            i = 90 + 10 * i
+        else:
+            i = 0
+        point = point + i
+    return point
+def trigram(str1, str2):
+    """
+    trigramによる単語の近さを計算します。
+    単語文字列の長さも考慮にいれます。
+    """
+    str1 = zenhan.toHankaku(str1)
+    str2 = zenhan.toHankaku(str2)
+    str1 = str1.replace(" ", "")
+    str2 = str2.replace(" ", "")
+    gram = []
+    if len(str1) < 3:
+        gram.append(str1)
+    else:
+        tmp1 = str1[0]
+        tmp2 = str1[1]
+        for x in str1[2:]:
+            gram.append(tmp1 + tmp2 + x)
+            tmp1 = tmp2
+            tmp2 = x
+    point = 0
+    count = 0
+    for x in gram:
+        i = findGram(x, str2)
+        if i > 0:
+            i = 90 + 10 * i
+            count=count + 1
+        else:
+            i = 0
+        point = point + i
+    point = point + 20*count*count
+    point = point / len(str1) * 10
+    point = point / len(str2) * 10
+    return point
+def findGram(gram, s):
+    """
+    s中にあらわれるgramの数を調べる
+    """
+    st = s
+    i = 0
+    while st.find(gram) != -1:
+        i = i + 1
+        st = st[st.find(gram) + 1:]
+    return i
+def getNounQuadGram(s):
+    """
+    。
+    """
+    str1 = zenhan.toHankaku(s)
+    gram={}
+    if len(str1) > 4:
+        tmp1 = str1[0]
+        tmp2 = str1[1]
+        tmp3 = str1[2]
+        skipnum=0
+        for x in str1[3:]:
+            if skipnum>0:
+                skipnum=skipnum-1
+            else:
+                tmps=tmp1 + tmp2 + tmp3 + x
+                if tmps.find(" ")<0:
+                    if zenhan.checkCharacterType(tmp1)>0:
+                        if (zenhan.checkCharacterType(tmp1)==zenhan.checkCharacterType(tmp2)):
+                            if (zenhan.checkCharacterType(tmp2)==zenhan.checkCharacterType(tmp3)):
+                                if (zenhan.checkCharacterType(tmp3)==zenhan.checkCharacterType(x)):
+                                    gram[tmps]=gram.get(tmps,0)+1
+                                    skipnum=0
+                                else:
+                                    skipnum=3
+                            else:
+                                if (zenhan.checkCharacterType(tmp3)==zenhan.checkCharacterType(x)):
+                                    skipnum=2
+                                else:
+                                    skipnum=3
+                        else:
+                            if (zenhan.checkCharacterType(tmp2)==zenhan.checkCharacterType(tmp3)):
+                                if (zenhan.checkCharacterType(tmp3)==zenhan.checkCharacterType(x)):
+                                    skipnum=0
+                                else:
+                                    skipnum=3
+                            else:
+                                if (zenhan.checkCharacterType(tmp3)==zenhan.checkCharacterType(x)):
+                                    skipnum=2
+                                else:
+                                    skipnum=3
+            tmp1 = tmp2
+            tmp2 = tmp3
+            tmp3 = x
+    return gram
+""
\ No newline at end of file
diff --git a/dist/trunk/rec10/readme.txt b/dist/trunk/rec10/readme.txt
new file mode 100755 (executable)
index 0000000..f8dbd93
--- /dev/null
@@ -0,0 +1,211 @@
+###########################################
+#     Rec10 -Ts Recording system-         #
+#                          Ver.0.9.9.2    #
+# 2011/03/23         Yukikaze & long.inus #
+#  Copyright (C) 2009-2011 Yukikaze      #
+###########################################
+
+本ソフトはpythonおよびperlによって書かれた録画ツールです。
+ライセンスは LGPL v3に準拠します(license.txt参照)
+
+[必要コマンド]
+python(2.6,2.7にて動作確認)
+wine
+mencoder
+ffmpeg
+x264
+mp4box
+MySQL
+MySQLdb(MySQL-pythonなどの名前)
+mkvmerge(mkv使用時)
+java(jre1.6で動作を確認)
+
+[必要環境:Webインターフェース部分]
+perl
+一部のperlモジュール(rectool.pl,rec10webg2)
+
+[必要環境:外部ツール]
+jTsSplitter(included)
+BonTsDemux(included)
+epgdump(included)
+b25(not included)
+recpt1(recfriioでもいいはずです)(not included)
+MySQLdb
+
+事前準備:
+ネットの情報を参考にpt1ドライバーを無効化する
+pt1などのドライバーをインストールした上(chardev版)で、recpt1などのソフトを導入、
+b25をインストールしておいてください。
+*注意
+11年10月01日からのBS新チャンネル対応のためには、10/02現在ではrecpt1にパッチを当てる必要があります。
+rec10同梱版のepgrecはts解析によってチャンネルデータを得るように改変してあるので
+変更は不要です。
+
+1:install.shを実行
+2:表示にしたがって設定の変更(チャンネルなど)
+3:make
+4:su
+5:make install
+6:rec10を実行するユーザーで/usr/local/share/rec10を実行
+7:cronに書き加える
+8:rectool.plをインストール(Makefile.PLの実行 rectool.plの配置)
+
+付け足し
+
+7.cronの設定
+
+最後にrec10d.pyをcronで五分おきに実行するようにしてください
+crontab -e を実行するとcronを編集できるようになるので
+*/5 * * * * python /usr/local/bin/rec10
+のように書いてください(5扮ごとに実行)
+
+ログは/var/log/rec10に移動しました。
+
+8.rectoolのインストール
+Makefile.PLを実行します。
+実行した後にrectool.plをhttpの公開ディレクトリ(wwwフォルダなど)に置いてください。
+
+ちなみに
+エンコードの設定を変えたい場合はts2x264を参照してください
+
+
+チャンネルの設定を変えた場合はを編集した後に
+chdata.pyを実行してください(python chdata.py)
+その後番組表が更新されます
+
+バグだらけのコードですが、改善点などを指摘していただけるとうれしいです。
+yukikaze.jp@gmail.com
+
+
+動作確認のとれたディストリ
+
+11/03/10 SVN Centos 5.5 (yukikaze)
+11/03/10 0.9.9.1+a ArchLinux (yukikaze)
+11/02/20 0.9.9.1+a Debian 6.0
+11/02/XX 0.9.9 Ubuntu 10.10
+10/12/XX 0.9.8 Centos 5.5 (yukikaze)
+10/XX/XX 0.9.8 Fedora13 (long.inus)
+
+
+[History]
+11/XX/XX 0.9.10
+add Bluray compatible option("B")
+ステレオ音声時のBonTsDemux仕様オプション追加("b")
+lameの実行パスチェックを実装
+mencoderのコマンドラインを最新版対応へ
+ffmpegのオプション追加
+epggenreを追加
+keywordの重複チェックをより賢く
+logoのインポートに対応
+ArchLinuxサポートのための細かな変更
+新BSチャンネル対応
+lavf有効x264でのエラーに対応
+
+11/02/02 0.9.9
+BonTsDemuxを最新版へ(nogui化によりXvfbが不要)
+一部CSチャンネルの追加
+epg_chを変更(ontvの削除)
+チャンネルスキャン機能を実装
+キーワード予約の自動実行オプション追加(in_auto_jbkにauto,optの追加)
+番組初頭の解像度変更に対応
+キーワード予約自動実行オプションの重複チェック実装
+延長対応機能の修正
+移動後のオプション引き継ぎに対応
+
+10/10/09 0.9.8 release
+インターレース保持エンコードに対応
+色空間を修正
+放送大学のマルチチャンネルに仮対応
+verboseモードの実装
+ログレベルの実装
+画面サイズが取得できなかったときの処理を追加
+python2.5/2.7に対応
+音声の自動復帰を修正
+
+10/07/10 0.9.7 release
+ヒストリーチャンネルのタイトルを修正
+ffmpeg使用時にscale拡大をするように修正
+一時ファイル削除機能の修正
+sarの変更を実装
+最新版のCaption2Assに対応
+
+10/05/29 0.9.6 release
+バグ修正
+ログシステムの修正
+
+0.9.5(内部リリース)
+b25自動削除機能の改善
+自動仕分け機能のアップデート
+Caption2Assやaac取り出しがうまくいかないときの自動復帰処理の実装
+バグ修正
+
+10/04/02 0.9.4 release
+バグ修正
+インストーラーの大幅な改善
+ログシステムの変更
+エンコードの変更
+チャンネル変更に対応(CS)
+
+10/03/20 0.9.3 release(internal)
+lots of bug fixes.
+change DB.
+implement updating function(from 0.9.1 or 0.9.2)
+10/03/06 0.9.2 release(internal)
+few bug fix.(!!! amazing i think)
+implement new encoding system.
+use x264cli and mencoder throwgh fifo.
+implement final production changing system(you can choose mkv and mp4 now.)
+
+10/02/21 0.9.1 release
+Lots of bug fixes.
+change video filter.
+change encode option.
+implement installer.
+
+09/12/07 0.9.0 release
+change config path.(config.ini to rec10.conf)
+add Makefile
+change large number of var name.
+support b25_remote(thanks long.inus)
+support auto copy function.
+change video filter.
+change encode option.
+fix a lot of bugs.
+finish to support iEPG(iRec10EPG).
+
+09/10/27 0.8.0 relaase
+Lots of bug fixes.
+Use mkvmerge to mux avi to mkv.
+Many changes.
+
+09/08/22 0.6.0 release
+Lots of bug fixes.
+Implement db using MySQL.
+Change Ts splitting soft from Tssplitter to tssplitter_lite(included.)
+
+09/08/01 0.5.0 release
+バグフィックス
+検索録画のパターンマッチングアルゴリズムの変更(推測的な検索ができるようになった)
+rectool.plを同梱するようにした。
+周辺ソフトのうちライセンスの問題がないものを同梱するようにした。
+
+09/07/01 0.4.1 release
+lots of bug fixes
+add some cs-ch.
+release pl src.
+09/05/24 0.3.1 release
+fix
+チャンネルの増加
+エンコードオプションを実際に使えるようにした。
+1passモード実装
+niceコマンドをより広範囲に適用するようにした。
+09/05/08 0.1.1 release
+fix
+2passエンコードのログファイルがかぶるのを訂正
+一部チャンネル指定が間違っていたのを訂正
+その他多くのバグの訂正
+09/05/05 0.0.1b release
+fix
+replace tab to 4 spaces(it caused errors)
+add some cs-e2 channels
+09/05/04 0.0.1a release
diff --git a/dist/trunk/rec10/rec10.conf b/dist/trunk/rec10/rec10.conf
new file mode 100755 (executable)
index 0000000..482da6c
--- /dev/null
@@ -0,0 +1,70 @@
+[path]
+recpt1 = /usr/local/bin/recpt1
+wine = /usr/bin/wine
+x264 = /usr/bin/x264
+mencoder = /usr/bin/mencoder
+tee = /usr/bin/tee
+ffmpeg = /usr/bin/ffmpeg
+rec10 = /usr/local/share/rec10
+lame = /usr/bin/lame
+java = /usr/bin/java
+#recpathは録画先のフォルダを指定
+recpath = /path of /recording
+
+#録画終了後に動画を置いておくフォルダを指定するとrectool.plでリスト化できます。
+recorded = 
+
+#複数のrec10で役割を分担するときに用いる移動先
+move_destpath =
+ts_movepath =
+
+#一時キャッシュに使用するフォルダです。 指定しない場合rec10本体と同じフォルダが使われます。
+tmp = /tmp/rec10
+epgdump = /usr/local/bin/epgdump
+tssplitter = /usr/bin/java -jar /usr/local/share/rec10/tstools/jTsSplitter.jar
+jTsSplitter = /usr/local/share/rec10/tstools/jTsSplitter.jar
+bontsdemux = /usr/local/share/rec10/tstools/BonTsDemux.exe
+caption2ass = /usr/local/share/rec10/tstools/Caption2Ass.exe
+mp4box = /usr/bin/MP4Box
+mkvmerge = /usr/bin/mkvmerge
+mkvextract = /usr/bin/mkvextract
+gridserver_port=10910
+
+#b25関連の設定
+b25_remote=0
+#b25_remoteを使う場合は1にしてください。
+b25 = /usr/local/bin/b25
+#b25_remoteを使う場合、下記の"192.168.0.1"および"/~~~/b25-client.so"を書き換えてください。
+#b25_env = "export B25_SERVER_IP=192.168.0.1 && export LD_PRELOAD=/~~~/b25-client.so"
+
+useNeroAAC = 0
+NeroAAC = /usr/local/bin/neroAacEnc
+[db]
+db = MySQL
+mysql_dbname=rec10
+mysql_host=localhost
+mysql_user=nobody
+mysql_passwd=nobody
+mysql_port=3306
+[env]
+#同時エンコード最大数(自分のコア数が目安です。)
+enc_max=2
+#地上デジタル放送録画可能数(PT-xは2,friioは1)
+te_max=2
+#BS/CS放送録画可能数(PT-xは2,黒friioは1)
+bscs_max=2
+iff =
+bs = 0
+cs = 0
+make_mp4 = 1
+#エンコードの重さの設定 大きければ大きいほど(1-6)速度は遅くなるが同じ画質でもサイズが小さくなる。
+x264_preset=4
+crf=24
+animation_crf=18
+x264_thread = 0
+x264_addline = 
+remove_ts = 0
+
+[log]
+verbose_level = 400#デーモンとして使う場合は変更する必要はありません。
+log_level = 400#
\ No newline at end of file
diff --git a/dist/trunk/rec10/rec10d.py b/dist/trunk/rec10/rec10d.py
new file mode 100755 (executable)
index 0000000..b0ce3af
--- /dev/null
@@ -0,0 +1,34 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import os\r
+import os.path\r
+import warnings\r
+warnings.filterwarnings('ignore', "the sets module is deprecated")\r
+import configreader\r
+import dbMySQL\r
+import timerec\r
+path = str(os.path.dirname(os.path.abspath(__file__))) + "/"\r
+tmppath = configreader.getConfPath("tmp")+"/"\r
+if tmppath=="/":\r
+    tmppath=path\r
+if not os.path.exists(tmppath):\r
+    os.makedirs(tmppath)\r
+global rec10db\r
+def main():\r
+    timerec.task()\r
+db = configreader.getConfDB("db")\r
+if db == "MySQL":\r
+    dbn = configreader.getConfDB("mysql_dbname")\r
+    dbh = configreader.getConfDB("mysql_host")\r
+    dbu = configreader.getConfDB("mysql_user")\r
+    dbpwd = configreader.getConfDB("mysql_passwd")\r
+    dbport = int(configreader.getConfDB("mysql_port"))\r
+    rec10db = dbMySQL.DB_MySQL(dbname=dbn, host=dbh, user=dbu, passwd=dbpwd, port=dbport)\r
+    rec10db.new_in_status()\r
+else:\r
+    rec10db = dbSQLite.DB_SQLite(path + "ch.db")\r
+if __name__ == "__main__":\r
+    main()\r
+\r
diff --git a/dist/trunk/rec10/recdb.py b/dist/trunk/rec10/recdb.py
new file mode 100755 (executable)
index 0000000..b080755
--- /dev/null
@@ -0,0 +1,95 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import chdb\r
+import n_gram\r
+import rec10d\r
+import recdblist\r
+\r
+def reserveKeyword(keyword, chtxt, btime, etime, deltatime, opt):\r
+    rec10d.rec10db.add_timeline(type=recdblist.REC_KEYWORD, chtxt=chtxt, title=keyword, btime=btime, etime=etime, deltatime=deltatime, opt=opt)\r
+def reserveEverydayKeyword(keyword, chtxt, btime, etime, deltatime, opt, deltaday,count):\r
+    tcount=count\r
+    if tcount<0:\r
+        tcount=-1\r
+    rec10d.rec10db.add_timeline(type=recdblist.REC_KEYWORD_EVERY_SOME_DAYS, chtxt=chtxt, title=keyword, btime=btime, etime=etime, deltatime=deltatime, opt=opt, deltaday=deltaday,counter=tcount)\r
+def reserveReckey(type, title, chtxt, btime, etime, opt):\r
+    rec10d.rec10db.add_timeline(type=type, chtxt=chtxt, title=title, btime=btime, etime=etime, opt=opt)\r
+def deleteReckey(type, title, chtxt, btime):\r
+    rec10d.rec10db.del_timeline(type=type, title=title, chtxt=chtxt, btime=btime)\r
+def reserveAutoKeyword(chtxt,title,btime,etime):\r
+    rec10d.rec10db.add_auto_timeline_keyword(chtxt, title, btime, etime)\r
+def addAutoBayesKeyword(chtxt,title,btime,etime,point):\r
+    rec10d.rec10db.add_auto_timeline_bayes(chtxt, title, btime, etime,point)\r
+def getProgramsInTheseHours(dhour):\r
+    dhour = int(dhour)\r
+    dminutes = 60 * dhour\r
+    dminutes = str(dminutes)\r
+    return rec10d.rec10db.select_bytime_timeline(dminutes)\r
+def getProgramsInTheseMinutes(dminutes):\r
+    return rec10d.rec10db.select_bytime_timeline(dminutes)\r
+def countRecNow(dhour):\r
+    d = getProgramsInTheseHours(dhour)\r
+    ret = 0\r
+    for i in d:\r
+        t = i['type']\r
+        if t == "key" or t == "keyevery" or t == "rec" or t == "res":\r
+            ret = ret + 1\r
+    return ret\r
+def countRecNow_minutes(dminutes):\r
+    d = getProgramsInTheseMinutes(dminutes)\r
+    ret = 0\r
+    for i in d:\r
+        t = i['type']\r
+        if t == "key" or t == "keyevery" or t == "rec" or t == "res":\r
+            ret = ret + 1\r
+    return ret\r
+def countRecNow_minutes_BSCS(dminutes):\r
+    d = getProgramsInTheseMinutes(dminutes)\r
+    ret = 0\r
+    for i in d:\r
+        t = i['type']\r
+        if t == "key" or t == "keyevery" or t == "rec" or t == "res":\r
+            if len(chdb.searchCHFromChtxt(i['chtxt'])['ch']) > 2:\r
+                ret = ret + 1\r
+    return ret\r
+def countRecNow_minutes_TE(dminutes):\r
+    d = getProgramsInTheseMinutes(dminutes)\r
+    ret = 0\r
+    for i in d:\r
+        t = i['type']\r
+        if t == "key" or t == "keyevery" or t == "rec" or t == "res":\r
+            if len(chdb.searchCHFromChtxt(i['chtxt'])['ch']) < 3:\r
+                ret = ret + 1\r
+    return ret\r
+def deleteOldProgramBeforeTheseHours(dhour):\r
+    """\r
+    delete keys except recdblist.REC_MISS_ENCODE and recdblist.REC_KEYWORD_EVERY_SOME_DAYS before dhour hours from now.\r
+    """\r
+    rec10d.rec10db.delete_old_timeline(dhour)\r
+def delete_old_auto_keyword(dhour):\r
+    rec10d.rec10db.delete_old_auto_timeline_keyword(dhour)\r
+def delete_old_auto_bayes(dhour):\r
+    rec10d.rec10db.delete_old_auto_timeline_bayes(dhour)\r
+def getAll():\r
+    return rec10d.rec10db.select_all_timeline()\r
+def addRecLogProgram(title,chtxt,btime,etime,opt,exp,longexp,category):\r
+    rec10d.rec10db.add_in_timeline_log(chtxt,title,btime,etime,opt,exp,longexp,category)\r
+def getAllJbkKeyword():\r
+    return rec10d.rec10db.select_all_in_auto_jbk_key()\r
+def checkDuplicated(title,chtxt,epgbtime,epgetime):\r
+    tl=rec10d.rec10db.select_byepgtime_all_timeline(epgbtime,epgetime)\r
+    nel=rec10d.rec10db.select_bytime_all_timeline(epgbtime, epgetime)\r
+    dup=0\r
+    for t in tl:\r
+        if t["title"]==title and t["chtxt"]==chtxt:\r
+            dup=1\r
+        elif n_gram.trigram(t["title"],title)> 500 and t["chtxt"]==chtxt:\r
+            dup=1\r
+    for t in nel:\r
+        if t["title"]==title and t["chtxt"]==chtxt:\r
+            dup=1\r
+        elif n_gram.trigram(t["title"],title)> 500 and t["chtxt"]==chtxt:\r
+            dup=1\r
+    return dup\r
diff --git a/dist/trunk/rec10/recdblist.py b/dist/trunk/rec10/recdblist.py
new file mode 100755 (executable)
index 0000000..1b60dc9
--- /dev/null
@@ -0,0 +1,197 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+\r
+"""\r
+task names\r
+"""\r
+import datetime\r
+import os\r
+import os.path\r
+import traceback\r
+\r
+import configreader\r
+\r
+global REC_RESERVE\r
+global REC_FINAL_RESERVE\r
+global REC_ENCODE_GRID\r
+global REC_ENCODE_LOCAL\r
+global REC_ENCODE_QUE\r
+global REC_MISS_ENCODE\r
+global REC_KEYWORD\r
+global REC_KEYWORD_EVERY_SOME_DAYS\r
+global REC_FIN_LOCAL\r
+global REC_MISS_DECODE\r
+global REC_TS_DECODE_QUE\r
+global REC_TS_DECODING\r
+global REC_TS_RECORDING\r
+global REC_AVI_TO_MKV\r
+global REC_AVI_TO_MP4\r
+global REC_MKV_TO_MP4\r
+global REC_CHANGING_CANTAINER\r
+\r
+#ここから処理のちに移動\r
+\r
+global REC_MOVE_END\r
+\r
+#ここから自動で提起される処理。\r
+global REC_AUTO_SUGGEST_REC\r
+global REC_AUTO_SUGGEST_DECODE\r
+global REC_AUTO_SUGGEST_ENCODE\r
+global REC_AUTO_SUGGEST_AVI2MP4\r
+global REC_AUTO_SUGGEST_MKV2MP4\r
+global REC_AUTO_SUGGEST_AVI2FP\r
+global REC_AUTO_SUGGEST_AP2FP\r
+global REC_BAYES_SUGGEST\r
+global REC_AUTO_KEYWORD\r
+REC_RESERVE = "reserve_flexible"\r
+REC_FINAL_RESERVE = "reserve_fixed"\r
+REC_ENCODE_GRID = "convert_ts_mp4_network"\r
+REC_ENCODE_LOCAL = "convert_ts_mp4_running"\r
+REC_ENCODE_QUE = "convert_ts_mp4"\r
+REC_MISS_ENCODE = "convert_avi_mp4_miss"\r
+REC_KEYWORD = "search_today"\r
+REC_KEYWORD_EVERY_SOME_DAYS = "search_everyday"\r
+REC_FIN_LOCAL = "convert_ts_mp4_finished"\r
+REC_MISS_DECODE = "convert_b25_ts_miss"\r
+REC_TS_DECODE_QUE = "convert_b25_ts"\r
+REC_TS_DECODING = "convert_b25_ts_running"\r
+REC_TS_RECORDING = "reserve_running"\r
+REC_CHANGING_CANTAINER = "convert_mkv_mp4_runnings"\r
+REC_AVI_TO_MKV = "convert_avi_mkv"\r
+REC_AVI_TO_MP4 = "convert_avi_mp4"\r
+REC_MKV_TO_MP4 = "convert_mkv_mp4"\r
+\r
+REC_MOVE_END = "move_end"\r
+\r
+REC_AUTO_SUGGEST_REC = "auto_suggest_rec"\r
+REC_AUTO_SUGGEST_DECODE = "auto_suggest_dec"\r
+REC_AUTO_SUGGEST_ENCODE = "auto_suggest_enc"\r
+REC_AUTO_SUGGEST_AVI2FP = "auto_suggest_avi2fp"\r
+REC_AUTO_SUGGEST_AP2FP = "auto_suggest_ap2fp"\r
+REC_AUTO_KEYWORD = "auto_keyword"\r
+REC_BAYES_SUGGEST ="bayes_suggest"\r
+\r
+global BONTSDEMUX_DELAY\r
+BONTSDEMUX_DELAY="0"\r
+\r
+version = 101\r
+version_str="0.9.10"\r
+\r
+global verbose_level_now\r
+global log_level_now\r
+\r
+try:\r
+    log_level_now=int(configreader.getConfLog("log_level"))\r
+    verbose_level_now=int(configreader.getConfLog("verbose_level"))\r
+except:\r
+    log_level_now=900\r
+    verbose_level_now=400\r
+def printutf8(unicode,verbose_level=500):\r
+    if verbose_level_now > verbose_level:\r
+        try:\r
+            str=unicode.encode('utf-8')\r
+            print str\r
+        except Exception, inst:\r
+            recdblist.addCommonlogEX("Error", "printutf8(recdblist.py)", str(type(inst)), str(inst)+traceback.format_exc(),log_level=200)\r
+def printuft8ex(unicode,verbose_level=500,log_level=500):\r
+    str=unicode.encode('utf-8')\r
+    if verbose_level_now > verbose_level:\r
+        print str\r
+    logfname="/var/log/rec10"\r
+    mode="a"\r
+    if log_level_now > log_level:\r
+        if os.path.exists(logfname):\r
+            f=open(logfname,mode)\r
+            f.write(str+"\n")\r
+            f.close()\r
+def addCommonlogEX(type,place,inst,txt,verbose_level=500,log_level=500):\r
+    lt=unicode(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+u":"\r
+    if txt=="":\r
+        lt=lt+u"["+type+u"] "+place+u" "+inst\r
+    else:\r
+        try:\r
+            lt=lt+u"["+type+u"] "+place+u" "+inst+u"\n"+txt\r
+        except:\r
+            print [type,place,inst,txt]\r
+    lt=lt.encode('utf-8')\r
+    logfname="/var/log/rec10"\r
+    mode="a"\r
+    if verbose_level_now > verbose_level:\r
+        print lt\r
+    if log_level_now > log_level:\r
+        if os.path.exists(logfname):\r
+            f=open(logfname,mode)\r
+            f.write(lt+"\n")\r
+            f.close()\r
+def addCommandLog(tspath,log_title,cmd,cmd_log=""):\r
+    addLog(tspath,cmd,log_title+u"ログ-コマンド")\r
+    addLog(tspath,cmd_log,log_title+u"ログ-詳細")\r
+def addCommandLogZip(tspath,log_title,log_filename_add,cmd,cmd_log=""):\r
+    logtitle=getLogTitle(tspath)\r
+    logo=logtitle+"."+log_filename_add+".log"\r
+    logzip=logtitle+".log.zip"\r
+    addLogAll(tspath,cmd+"\n\n"+cmd_log,log_title,logo)\r
+    import zip\r
+    zip.addFile2FileZip(logo,logzip)\r
+    os.remove(logo)\r
+def addCommandSelfLog(tspath,command):\r
+    logpath=getLogTitle(tspath)+".command.log"\r
+    f=""\r
+    if os.path.exists(logpath):\r
+        f=open(logpath,'a')\r
+    else:\r
+        f=open(logpath,'w')\r
+    tc=command+u"\n\n"\r
+    tc=unicode(tc)\r
+    f.write(tc.encode("utf-8"))\r
+    #f.write(tc.encode('utf-8','ignore'))\r
+    f.close()\r
+def getLogTitle(tspath):\r
+    logo=tspath\r
+    logo=logo.replace("_1.wav",".ts")\r
+    logo=logo.replace("_2.wav",".ts")\r
+    logo=logo.replace("_1.aac",".ts")\r
+    logo=logo.replace("_2.aac",".ts")\r
+    logo=logo.replace("_1.mp3",".ts")\r
+    logo=logo.replace("_2.mp3",".ts")\r
+    logo=logo.replace(".ts.tsmix",".ts")\r
+    logo=logo.replace(".ts.b25",".ts")\r
+    logo=logo.replace(".sa.avi",".ts")\r
+    logo=logo.replace(".m2v",".ts")\r
+    logo=logo.replace(".avi",".ts")\r
+    logo=logo.replace(".mkv",".ts")\r
+    logo=logo.replace(".wav",".ts")\r
+    logo=logo.replace(".mp4",".ts")\r
+    logo=logo.replace(".mp3",".ts")\r
+    logo=logo.replace(".aac",".ts")\r
+    logo=logo.replace(".srt",".ts")\r
+    logo=logo.replace(".264",".ts")\r
+    logo=logo.replace(".ts","")\r
+    return logo\r
+def addLog(tspath,txt,log_title,maxtextlength=1500):\r
+    logo=getLogTitle(tspath)+".log"\r
+    f=open(logo,'a')\r
+    s=len(txt)\r
+    stxt=""\r
+    if s>maxtextlength*2 and maxtextlength>0:\r
+        stxt=txt[0:maxtextlength]+"\n\n(ry..)\n"\r
+        st=txt[s-maxtextlength:].find("\n")\r
+        if st>0:\r
+            stxt=stxt+txt[s-1500+st:]\r
+    else:\r
+        stxt=txt\r
+    txtw= datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")\r
+    txtw=txtw+"\n####"+log_title+"####\n"+stxt\r
+    f.write(txtw.encode('utf-8'))\r
+    f.close()\r
+def addLogAll(tspath,txt,log_title,logpath):\r
+    logo=logpath\r
+    f=open(logo,'a')\r
+    s=len(txt)\r
+    stxt=txt\r
+    txtw= datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")\r
+    txtw=txtw+"\n####"+log_title+"####\n"+stxt\r
+    f.write(txtw.encode('utf-8'))\r
+    f.close()\r
diff --git a/dist/trunk/rec10/recque.py b/dist/trunk/rec10/recque.py
new file mode 100755 (executable)
index 0000000..64be4a8
--- /dev/null
@@ -0,0 +1,82 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import datetime\r
+import os\r
+import os.path\r
+import glob\r
+import time\r
+import traceback\r
+\r
+import configreader\r
+import recdblist\r
+import recdb\r
+tmppath = configreader.getConfPath("tmp")+"/"\r
+if not os.path.exists(tmppath):\r
+    os.mkdir(tmppath)\r
+def writeRecQue(parentpath,chtxt,title,opts):\r
+    outputpath=os.path.join(parentpath,title+".recq")\r
+    tmpoppath=os.path.join(tmppath,title+".recq")\r
+    f=open(outputpath,"w")\r
+    optt=opts\r
+    #optt=opts.replace("E","")\r
+    #optt=optt.replace("D","")\r
+    #optt=optt.replace("R","")\r
+    str="99"+","+datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")+","+configreader.getConfEnv("iff")+","+chtxt+","+title+","+optt\r
+    f.write(str.encode('utf-8'))\r
+    f.close()\r
+    if not os.path.exists(outputpath):\r
+        if os.path.exists(tmpoppath):\r
+            os.remove(tmpoppath)\r
+        f2=open(tmpoppath,"w")\r
+        f2.write(str.encode('utf-8'))\r
+        f2.close()\r
+        try:\r
+            os.chmod(tmpoppath)\r
+        except:\r
+            ""\r
+        shutil.copy(tmpoppath,outputpath)\r
+        os.remove(tmpoppath)\r
+def readRecQue(recquepath):\r
+    f=open(recquepath,"r")\r
+    line = unicode(f.readline(),'utf-8')\r
+    title=""\r
+    opts=""\r
+    chtxt=""\r
+    while line:\r
+        linec=line.split(",")\r
+        if len(linec)>3:\r
+            if linec[0]=="99":\r
+                title=linec[4]\r
+                opts=linec[5]\r
+                chtxt=linec[2]+u"_"+linec[3]\r
+                break\r
+        line = unicode(f.readline(),'utf-8')\r
+    dbkey=""\r
+    if opts.find("E")>-1:\r
+        dbkey=""\r
+        opts=opts.replace("E","")\r
+    elif opts.find("D")>-1:\r
+        dbkey=recdblist.REC_ENCODE_QUE\r
+        opts=opts.replace("D","")\r
+    elif opts.find("R")>-1:\r
+        dbkey=recdblist.REC_TS_DECODE_QUE\r
+        opts=opts.replace("R","")\r
+    bt=datetime.datetime.now()+datetime.timedelta(minutes=5)\r
+    et=bt+datetime.timedelta(minutes=30)\r
+    btime=bt.strftime("%Y-%m-%d %H:%M:%S")\r
+    etime=et.strftime("%Y-%m-%d %H:%M:%S")\r
+    if len(dbkey)>2:\r
+        recdb.reserveReckey(dbkey, title, chtxt, btime, etime, opts)\r
+def searchRecQue(folderpath):\r
+    for file in glob.glob(os.path.join(folderpath,"*.recq")):\r
+        dtime = time.time()-os.path.getmtime(file)\r
+        dtime = int(dtime)\r
+        if dtime > 300:\r
+            try:\r
+                readRecQue(os.path.join(folderpath, file))\r
+                os.remove(os.path.join(folderpath, file))\r
+            except Exception, inst:\r
+                recdblist.addCommonlogEX("Error", "searchRecQue(recque.py)", str(type(inst)), str(inst)+traceback.format_exc(),log_level=200)\r
+                \r
diff --git a/dist/trunk/rec10/scan_ch.py b/dist/trunk/rec10/scan_ch.py
new file mode 100755 (executable)
index 0000000..377c19b
--- /dev/null
@@ -0,0 +1,160 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+import os
+import os.path
+import time
+import commands
+import traceback
+import datetime
+
+import chdb
+import rec10d
+import configreader
+import recdblist
+import tv2ts
+tmppath = configreader.getConfPath("tmp")+"/"
+if not os.path.exists(tmppath):
+    os.mkdir(tmppath)
+tssplitterp =configreader.getConfPath("java")+" -jar "+configreader.getConfPath("jTsSplitter")
+def searchCh():
+    rec10d.rec10db.change_installed_in_status(2)
+    #地上デジタル
+    for i in xrange(13,52):#62
+        recdblist.printuft8ex(u"チャンネルスキャン:地上デジタル CH "+str(i), 200, 200)
+        if checkTs(str(i))>0:
+            addCh(str(i),u"te"+str(i),str(i))
+    time.sleep(1)
+    #BSデジタル
+    recdblist.printuft8ex(u"チャンネルスキャン:BSデジタル ", 200, 200)
+    for i in xrange(100,299):#240
+        recdblist.printuft8ex(u"チャンネルスキャン:BSデジタル CH "+str(i), 200, 200)
+        if checkTs(str(i))>0:
+            addCh(str(i),u"bs","BS")
+    time.sleep(1)
+    #スカパーe2!
+    #http://www5e.biglobe.ne.jp/~kazu_f/digital-sat/trapon-nsat110.html
+    #
+    #CS1ネットワーク
+    if checkTs("CS2")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS2 ", 200, 200)
+        addCh("CS2","cs1","CS")
+    if checkTs("CS8")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS8", 200, 200)
+        addCh("CS8","cs1","CS")
+    if checkTs("CS10")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS10", 200, 200)
+        addCh("CS10","cs1","CS")
+    #CS2ネットワーク
+    if checkTs("CS4")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS4", 200, 200)
+        addCh("CS4","cs2","CS")
+    if checkTs("CS6")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS6", 200, 200)
+        addCh("CS6","cs2","CS")
+    if checkTs("CS12")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS12", 200, 200)
+        addCh("CS12","cs2","CS")
+    if checkTs("CS14")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS14", 200, 200)
+        addCh("CS14","cs2","CS")
+    if checkTs("CS16")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS16", 200, 200)
+        addCh("CS16","cs2","CS")
+    if checkTs("CS18")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS18", 200, 200)
+        addCh("CS18","cs2","CS")
+    if checkTs("CS20")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS20", 200, 200)
+        addCh("CS20","cs2","CS")
+    if checkTs("CS22")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS22", 200, 200)
+        addCh("CS22","cs2","CS")
+    if checkTs("CS24")>0:
+        recdblist.printuft8ex(u"チャンネルスキャン:CSSデジタル CH:CS24", 200, 200)
+        addCh("CS24","cs2","CS")
+    rec10d.rec10db.change_installed_in_status(100)
+def checkTs(ch):
+    tv2ts.tv2b25ts(os.path.join(tmppath,"ch_"+str(ch)+".ts"), ch, "1")
+    if os.path.exists(os.path.join(tmppath,"ch_"+str(ch)+".ts")):
+        os.remove(os.path.join(tmppath,"ch_"+str(ch)+".ts"))
+        return 1
+    else:
+        return 0
+def addCh(ch,bctype,chtxthead):
+    prglist=getChProgNum(ch)##[prglist,logt]
+    for lstr in prglist[0]:
+        #print [bctype,chtxthead+"_"+lstr, ch, lstr]
+        try:
+            if ch.find("bs")>-1:
+                if int(lstr)<300:
+                    tnow=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+                    rec10d.rec10db.add_epg_ch(bctype,chtxthead+"_"+lstr, ch, lstr, u"2010-01-01 00:00:00", u"2010-01-01 00:00:00",tnow)
+            else:
+                tnow=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+                rec10d.rec10db.add_epg_ch(bctype,chtxthead+"_"+lstr, ch, lstr, u"2010-01-01 00:00:00", u"2010-01-01 00:00:00",tnow)
+        except Exception, inst:
+            recdblist.addCommonlogEX("Warning", "addCh (scan_ch.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+    checkB25Purchased(ch, prglist[1])
+def getChProgNum(ch):
+    pout=os.path.join(tmppath,"ch_"+str(ch)+".ts")
+    logt=tv2ts.tv2tsmix(pout, ch, "10")
+    retl=getTsProgNum(ch,pout)
+    os.remove(pout)
+    return [retl,logt]
+def getTsProgNum(ch,tspath):
+    pin=tspath
+    pout=os.path.join(tmppath,"chscan.txt")
+    chopt="-ch"
+    if ch.find("CS")>-1:
+        chopt="-cs"
+    elif int(ch)>99:
+        chopt="-bs"
+    doexe = tssplitterp + " "+chopt+" \""+ pin + "\" \""+ pout + "\""
+    doexe = "nice -n 18 " + doexe
+    os.environ['LANG']="ja_JP.UTF-8"
+    os.system(u"touch \""+pout+"\"")
+    txt = unicode(commands.getoutput(doexe.encode('utf-8')),'utf-8','ignore')
+    f=open(pout)
+    lines=f.readlines()
+    f.close()
+    ret=[]
+    for l in lines:
+        try:
+            l=l.replace(" ","")
+            l=l.replace("\n","")
+            ret.append(str(int(l)))
+        except:
+            ""
+    recdblist.addLog(pin, doexe, u"TsSplitログ-コマンド")
+    recdblist.addLog(pin, txt, u"TsSplitログ-詳細")
+    time.sleep(1)
+    try:
+        ""
+        #os.remove(pout)
+    except:
+        ""
+    return ret
+def getB25UnparchasedList(logtxt):
+    warning = 0
+    ret=[]
+    for strt in logtxt.splitlines():
+        if strt.find("unpurchased ECM")>-1:
+            warning=1
+        if strt.find("total TS packet")>-1 and warning>0:
+            warning=0
+        if strt.find("channel")>-1 and warning>0:
+            txt=strt.replace("channel:","")
+            txt=txt.replace("\n","")
+            txt=txt.replace(" ","")
+            ret.append(txt)
+    return ret
+def checkB25Purchased(ch,logtxt):
+    chlists=chdb.searchAllCHFromCh(ch)
+    upl=getB25UnparchasedList(logtxt)
+    if len(upl)>0 and len(chlists)>0:
+        for chl in chlists:
+            if chl != None:
+                if chl['csch'] in upl:
+                    chdb.changeCHShow(chl['chtxt'],"0")
diff --git a/dist/trunk/rec10/status.py b/dist/trunk/rec10/status.py
new file mode 100755 (executable)
index 0000000..09383e8
--- /dev/null
@@ -0,0 +1,41 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import configreader\r
+import os\r
+import rec10d\r
+path = os.path.dirname(os.path.abspath(__file__)) + "/"\r
+def changeEncoding(i):\r
+    """\r
+    iはint 増減\r
+    """\r
+    rec10d.rec10db.change_ts2avi_in_status(i)\r
+def changeTERecording(i):\r
+    rec10d.rec10db.change_terec_in_status(i)\r
+def changeBSCSRecording(i):\r
+    rec10d.rec10db.change_bscsrec_in_status(i)\r
+def changeB25Decoding(i):\r
+    rec10d.rec10db.change_b252ts_in_status(i)\r
+def getEncoding():\r
+    """\r
+    エンコードしている数を帰すint型\r
+    """\r
+    return int(rec10d.rec10db.select_all_in_status()[0][0])\r
+def getTERecording():\r
+    return int(rec10d.rec10db.select_all_in_status()[0][1])\r
+def getBSCSRecording():\r
+    return int(rec10d.rec10db.select_all_in_status()[0][2])\r
+def getB25Decoding():\r
+    return int(rec10d.rec10db.select_all_in_status()[0][3])\r
+def getSettings_auto_bayes():\r
+    return int(rec10d.rec10db.select_all_in_settings()[0][1])\r
+def getSettings_auto_jbk():\r
+    return int(rec10d.rec10db.select_all_in_settings()[0][0])\r
+def getSettings_auto_del_tmp():\r
+    return int(rec10d.rec10db.select_all_in_settings()[0][2])\r
+def getSettings_auto_opt():\r
+    return rec10d.rec10db.select_all_in_settings()[0][3]\r
+\r
+def getRecordingMax():\r
+    return [int(configreader.getConfEnv("te_max")),int(configreader.getConfEnv("bscs_max"))]\r
diff --git a/dist/trunk/rec10/tester.py b/dist/trunk/rec10/tester.py
new file mode 100755 (executable)
index 0000000..e9012ca
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+#import sys
+import epgdb
+import tv2ts
+import os
+import time
+import tv2avi
+import tv2mkv
+import checker
+import guess
+import auto_process
+import install
+#import datetime
+import rec10d
+#import os
+#import time
+#import n_gram
+#import profile
+#import epgdb
+#import recdblist
+#import status
+#import chdb
+#import checker
+#import configreader
+#import classify
+#import epgdb
+#import rec10d
+#import recdb
+#import tv2mkv
+#import tv2avi
+#import xml2db
+#import guess
+#import zenhan
+#import auto_process
+import chdb
+import epgdb
+import datetime
+import tv2mp4
+import ts2x264
+import recque
+path = str(os.path.dirname(os.path.abspath(__file__))) + "/"
+recpath = "/home/ftpusr/ftp-tmp/Recording/"
+ftpusr = "/home/ftpusr/ftp-tmp"
+recordedpath = u"/home/ftpusr/ftp-video"
+if __name__ == "__main__":
+    #rec10d.rec10db.update_db_100to101()
+    #recque.searchRecQue(recpath)
+    #print chdb.updateLogo()
+    #epgdb.updateLogo_bc("bs")
+    print ts2x264.getX264CoreVersion()
+    auto_process.killDeadEncode(recpath)
+    ""
diff --git a/dist/trunk/rec10/timerec.py b/dist/trunk/rec10/timerec.py
new file mode 100755 (executable)
index 0000000..af5cd3c
--- /dev/null
@@ -0,0 +1,765 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+import datetime
+import os
+import os.path
+import re
+import sys
+import time
+import shutil
+import traceback
+
+import auto_rec
+import auto_process
+import chdb
+import configreader
+import epgdb
+import rec10d
+import recdb
+import status
+import tv2audio
+import tv2avi
+import tv2mkv
+import tv2mp4
+import install
+import recdblist
+import recque
+recpath = configreader.getConfPath('recpath')
+movepath = configreader.getConfPath('move_destpath')
+path = str(os.path.dirname(os.path.abspath(__file__))) + "/"
+def task():
+    """
+    数分毎に実行されるタスク処理
+    予定によって子プロセスを生成し処理する。
+    """
+    try:
+        if rec10d.rec10db.select_installed_in_status()==0 or rec10d.rec10db.select_version_in_status()<recdblist.version:
+            install.install()
+        elif rec10d.rec10db.select_installed_in_status()==1:
+            import scan_ch
+            rec10d.rec10db.new_epg_ch()
+            scan_ch.searchCh()
+            rec10d.rec10db.change_installed_in_status(100)
+        elif rec10d.rec10db.select_installed_in_status()==2:
+            recdblist.printuft8ex("Exit because CH scanning.", 200, 200)
+            sys.exit(0)
+    except Exception, inst:
+        recdblist.addCommonlogEX("Error", "install_check(timerec.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        install.install()
+    recdb.deleteOldProgramBeforeTheseHours("24")
+    recdb.delete_old_auto_bayes("1")
+    recdb.delete_old_auto_keyword("1")
+    tasks = recdb.getProgramsInTheseHours("3")
+    inum = recdb.countRecNow_minutes("10")
+    recdblist.printutf8(u"rec10処理開始"+ datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),verbose_level=800)
+    recdblist.printutf8(u"直近録画予約件数:" + str(inum) + u"BS/CS録画中件数:" + str(status.getBSCSRecording()) + u"TE録画中件数:" + str(status.getTERecording()) ,verbose_level=800)
+    encodenum=0
+    b25num=0
+    dnow=datetime.datetime.now()
+    if dnow.minute % 10 < 5:
+        pid = os.fork()
+        if pid != 0:
+            ""
+        else:
+            search_keyword(recdb.getAllJbkKeyword())
+            recque.searchRecQue(recpath)
+            sys.exit()
+    else:
+        pid = os.fork()
+        if pid!=0:
+            ""
+        else:
+            time.sleep(10)
+            auto_process.autoCheck(recpath)
+            time.sleep(10)
+            auto_process.killDeadEncode(recpath)
+            sys.exit()
+    update = chdb.update()
+    updatelogo = chdb.updateLogo()
+    updatelogo=[]
+    if len(update) > 0:
+        pid = os.fork()
+        if pid != 0:
+            ""
+        else:
+            i = 0
+            for bctype in update:
+                recnum = 0
+                if bctype.find('te') > -1:
+                    recnum = status.getTERecording() + recdb.countRecNow_minutes_TE("10")
+                    recdblist.printutf8(u"放送種別:"+bctype + u"||該当チューナー実行中件数:" + str(status.getTERecording()) + u":直近予約件数:" + str(recdb.countRecNow_minutes_TE("10")),verbose_level=800)
+                    recnum = int(configreader.getConfEnv("te_max")) -recnum
+                else:
+                    recnum = status.getBSCSRecording() + recdb.countRecNow_minutes_BSCS("10")
+                    recdblist.printutf8(u"放送種別:"+bctype + u"||該当チューナー実行中件数:" + str(status.getBSCSRecording()) + u":直近予約件数:" + str(recdb.countRecNow_minutes_BSCS("10")),verbose_level=800)
+                    recnum = int(configreader.getConfEnv("bscs_max")) -recnum
+                if recnum >0 :
+                    recdblist.printutf8(str(update),verbose_level=750)
+                    rec10d.rec10db.update_status_by_bctype_epg_ch(bctype, "0")
+                    epgdb.updatebc(bctype)
+                    update = chdb.update()
+                    i = i + 1
+                if i > 0:
+                    break
+            time.sleep(5)
+            auto_process.update_all_timeline_epg()
+            sys.exit()
+    elif len(updatelogo)>0:
+        pid = os.fork()
+        if pid != 0:
+            ""
+        else:
+            i = 0
+            for bctype in updatelogo:
+                recnum = 0
+                if bctype.find('te') > -1:
+                    recnum = status.getTERecording() + recdb.countRecNow_minutes_TE("1200")
+                    recdblist.printutf8(u"ロゴ未取得 : 放送種別-"+bctype + u"||該当チューナー実行中件数:" + str(status.getTERecording()) + u":直近予約件数:" + str(recdb.countRecNow_minutes_TE("10")),verbose_level=800)
+                    recnum = int(configreader.getConfEnv("te_max")) -recnum
+                else:
+                    recnum = status.getBSCSRecording() + recdb.countRecNow_minutes_BSCS("1200")
+                    recdblist.printutf8(u"ロゴ未取得 : 放送種別-"+bctype + u"||該当チューナー実行中件数:" + str(status.getBSCSRecording()) + u":直近予約件数:" + str(recdb.countRecNow_minutes_BSCS("10")),verbose_level=800)
+                    recnum = int(configreader.getConfEnv("bscs_max")) -recnum
+                if recnum >0 :
+                    recdblist.printutf8(u"ロゴ取得"+str(updatelogo),verbose_level=750)
+                    rec10d.rec10db.update_logostatus_by_bctype_epg_ch(bctype,"0")
+                    epgdb.updateLogo_bc(bctype)
+                    updatelogo = chdb.updateLogo()
+                    i = i + 1
+                if i > 0:
+                    break
+            time.sleep(5)
+            sys.exit()
+    else:
+        pid = os.fork()
+        if pid != 0:
+            ""
+        else:
+            auto_process.update_all_timeline_epg()
+            sys.exit()
+    for task in tasks:
+        typetxt = task["type"]
+        try:
+            chtxt = task['chtxt']
+        except:
+            chtxt = ""
+        try:
+            title = task['title']
+        except:
+            title = ""
+        try:
+            btime = task['btime']
+            bt = datetime.datetime.strptime(btime, "%Y-%m-%d %H:%M:%S")
+        except:
+            btime = ""
+            bt = datetime.datetime.strptime("2009-01-01 00:00:00", "%Y-%m-%d %H:%M:%S")
+        try:
+            etime = task['etime']
+            et = datetime.datetime.strptime(etime, "%Y-%m-%d %H:%M:%S")
+        except:
+            etime = ""
+            et = datetime.datetime.strptime("2009-01-01 00:00:00", "%Y-%m-%d %H:%M:%S")
+        try:
+            opt = task['opt']
+        except:
+            opt = ""
+        tnow = datetime.datetime.now()
+        dtt = bt-tnow
+        dt = dtt.days * 24 * 60 * 60 + dtt.seconds
+        if task["type"] == recdblist.REC_RESERVE:#"res,"+chtxt+","+title+","+btime+","+etime+","+opt
+            pid = os.fork()
+            if pid != 0:#親プロセスの場合
+                ""
+            else:#子プロセスの場合 アップデートを行って終了
+                type_reserve(task["type"],chtxt,title,bt,et,opt)
+                sys.exit()
+        elif task["type"] == recdblist.REC_KEYWORD:#"key,"+chtxt+","+keyword+","+btime+","+deltatime+","+opt
+            deltatime = task['deltatime']
+            pid = os.fork()
+            if pid != 0:#親プロセスの場合
+                ""
+            else:#子プロセスの場合 アップデートを行って終了
+                type_keyword(task["type"],chtxt,title, bt, et, opt, deltatime)
+                sys.exit()
+        elif task["type"] == recdblist.REC_KEYWORD_EVERY_SOME_DAYS:#"keyevery,"+chtxt+","+keyword+","+btime+","+deltatime+","+opt+","+deltaday
+            deltatime = task['deltatime']
+            deltaday = task['deltaday']
+            try:
+                keyeverycounter=task['counter']
+            except:
+                keyeverycounter=-1
+            pid = os.fork()
+            if pid != 0:#親プロセスの場合
+                ""
+            else:#子プロセスの場合 アップデートを行って終了
+                type_keyword_every_day(task["type"],chtxt, title, bt, et, opt, deltatime, deltaday,keyeverycounter)
+                sys.exit()
+        elif task["type"] == recdblist.REC_FINAL_RESERVE:#"rec,"+chtxt+","+title+","+btime+","+etime+","+opt
+            pid = os.fork()
+            if pid != 0:#親プロセスの場合
+                ""
+            else:#子プロセスの場合 アップデートを行って終了
+                type_final(task["type"],chtxt, title, bt, et, opt)
+                sys.exit()
+        elif task["type"] == recdblist.REC_TS_DECODE_QUE:
+            b25num=b25num+1
+            pid = os.fork()
+            if pid != 0:#親プロセスの場合
+                ""
+            else:#子プロセスの場合 アップデートを行って終了
+                time.sleep(5*b25num)
+                type_decode_que(task["type"],chtxt, title, bt, et, opt)
+                sys.exit()
+        elif task["type"] == recdblist.REC_ENCODE_QUE:
+            encodenum=encodenum+1
+            pid = os.fork()
+            if pid != 0:#親プロセスの場合
+                ""
+            else:#子プロセスの場合 アップデートを行って終了
+                time.sleep(5*encodenum)
+                type_encode_que(task["type"],chtxt, title, bt, et, opt)
+                sys.exit()
+        elif task["type"] == recdblist.REC_AVI_TO_MKV:
+            if dt < 10 * 60:
+                pid = os.fork()
+                if pid > 0:#親プロセスの場合
+                    ""
+                else:
+                    makeMP4=1
+                    try:
+                        if configreader.getConfEnv("make_mp4")==0:
+                            makeMP4=0
+                    except:
+                        ""
+                    if re.search("m", opt):
+                        makeMP4=0
+                    if re.search("4", opt):
+                        makeMP4=1
+                    recdb.deleteReckey(recdblist.REC_AVI_TO_MKV, title, chtxt, btime)
+                    recdb.reserveReckey(recdblist.REC_CHANGING_CANTAINER, title, chtxt, btime, etime, opt)
+                    if makeMP4==1:
+                        tv2mp4.raw2mp4(os.path.join(recpath,title+".264"),os.path.join(recpath,title+".mp4"),opt)
+                    else:
+                        tv2mp4.raw2mp4(os.path.join(recpath,title+".264"),os.path.join(recpath,title+".mp4"),opt)
+                        tv2mkv.mp42mkv(os.path.join(recpath,title+".mp4"), os.path.join(recpath,title+".mkv"))
+                        os.remove(os.path.join(recpath,title+".mp4"))
+                    recdb.deleteReckey(recdblist.REC_CHANGING_CANTAINER, title, chtxt, btime)
+                    sys.exit()
+        elif task["type"] == recdblist.REC_AVI_TO_MP4:
+            if dt < 10 * 60:
+                pid = os.fork()
+                if pid > 0:#親プロセスの場合
+                    ""
+                else:
+                    makeMP4=0
+                    try:
+                        if configreader.getConfEnv("make_mp4")==1:
+                            makeMP4=1
+                    except:
+                        ""
+                    if re.search("m", opt):
+                        makeMP4=0
+                    if re.search("4", opt):
+                        makeMP4=1
+                    recdb.deleteReckey(recdblist.REC_AVI_TO_MP4, title, chtxt, btime)
+                    recdb.reserveReckey(recdblist.REC_CHANGING_CANTAINER, title, chtxt, btime, etime, opt)
+                    if makeMP4==1:
+                        tv2mp4.ts2mp4(pin, pout, opt)
+                        tv2mp4.raw2mp4(os.path.join(recpath,title+".264"),os.path.join(recpath,title+".mp4"),opt)
+                    else:
+                        tv2mkv.raw2mkv(os.path.join(recpath,title+".264"),os.path.join(recpath,title+".mkv"),opt)
+                    recdb.deleteReckey(recdblist.REC_CHANGING_CANTAINER, title, chtxt, btime)
+                    sys.exit()
+        elif task["type"] == recdblist.REC_MKV_TO_MP4:
+            if dt < 10 * 60:
+                pid = os.fork()
+                if pid > 0:#親プロセスの場合
+                    ""
+                else:
+                    recdb.deleteReckey(recdblist.REC_MKV_TO_MP4, title, chtxt, btime)
+                    recdb.reserveReckey(recdblist.REC_CHANGING_CANTAINER, title, chtxt, btime, etime, opt)
+                    tv2mp4.mkv2mp4(os.path.join(recpath,title+".mkv"),os.path.join(recpath,title+".mp4"))
+                    recdb.deleteReckey(recdblist.REC_CHANGING_CANTAINER, title, chtxt, btime)
+                    sys.exit()
+    sys.exit()
+def search_keyword(key):
+    tnow = datetime.datetime.now()
+    nows =tnow.strftime("%Y-%m-%d %H:%M:%S")
+    for k,auto,opt in key:
+        recdatum = epgdb.searchTimeAuto(k,nows, "144")
+        for recdata in recdatum:
+            if recdata[1] != "":
+                chtxtt = recdata[0]
+                titlet = recdata[1]
+                btimet = recdata[2]
+                etimet = recdata[3]
+                btt = datetime.datetime.strptime(btimet, "%Y-%m-%d %H:%M:%S")
+                ett = datetime.datetime.strptime(etimet, "%Y-%m-%d %H:%M:%S")
+                btimet = btt.strftime("%Y-%m-%d %H:%M:%S")
+                etimet = ett.strftime("%Y-%m-%d %H:%M:%S")
+                #if status.getSettings_auto_jbk()==1:
+                if auto==1 or status.getSettings_auto_jbk()==1:
+                    topt=opt
+                    if len(topt)==0:
+                        topt=status.getSettings_auto_opt()
+                    try:
+                        maxnum=0
+                        ch=chdb.searchCHFromChtxt(chtxtt)
+                        if len(ch['ch'])>2:
+                            maxnum=epgdb.countSchedule(btimet, etimet)[1]
+                            maxnum=int(configreader.getConfEnv("bscs_max"))-maxnum
+                        else:
+                            maxnum=epgdb.countSchedule(btimet, etimet)[0]
+                            maxnum=int(configreader.getConfEnv("te_max"))-maxnum
+                        if maxnum>0:
+                            if recdb.checkDuplicated(titlet, chtxtt, btimet, etimet)==0:
+                                recdb.reserveReckey(recdblist.REC_RESERVE,titlet,chtxtt, btimet, etimet,topt)
+                    except Exception, inst:
+                        recdblist.addCommonlogEX("Error", "search_keyword_auto_jbk(timerec.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+                try:
+                    recdb.reserveAutoKeyword(chtxtt, titlet, btimet, etimet)
+                except Exception, inst:
+                    recdblist.addCommonlogEX("Error", "search_keyword(timerec.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+def type_reserve(typetxt,chtxt,title,bt,et,opt):
+    btime = bt.strftime("%Y-%m-%d %H:%M:%S")
+    etime = et.strftime("%Y-%m-%d %H:%M:%S")
+    typetxtnow=typetxt
+    typetxtfinal=""
+    if typetxt==recdblist.REC_RESERVE:
+        typetxtfinal=recdblist.REC_FINAL_RESERVE
+    tnow = datetime.datetime.now()
+    dtt = bt-tnow
+    dt = dtt.days * 24 * 60 * 60 + dtt.seconds
+    if (dt < 58 * 60 and dt > 30 * 60):
+        bctypet = chdb.searchCHFromChtxt(chtxt)['bctype']
+        chdatat = rec10d.rec10db.select_by_bctype_epg_ch(bctypet)
+        dt1 = bt - datetime.datetime.strptime(chdatat[0][4], "%Y-%m-%d %H:%M:%S")
+        dt1 = dt1.days * 24 * 60 * 60 + dt1.seconds
+        if dt1 < 60 * 60:
+            recdata = epgdb.searchTime(title, btime, "5", chtxt)
+            chtxtn = recdata[0]
+            titlen = recdata[1]
+            btimen = recdata[2]
+            etimen = recdata[3]
+            exp = recdata[4]
+            longexp = recdata[5]
+            category=recdata[6]
+            bt = datetime.datetime.strptime(btimen, "%Y-%m-%d %H:%M:%S")
+            et = datetime.datetime.strptime(etimen, "%Y-%m-%d %H:%M:%S")
+            btimen = bt.strftime("%Y-%m-%d %H:%M:%S")
+            etimen = et.strftime("%Y-%m-%d %H:%M:%S")
+            if chtxt != "":
+                try:
+                    recdb.deleteReckey(typetxtnow, title, chtxt, btime)
+                    recdb.reserveReckey(typetxtfinal, titlen, chtxtn, btimen, etimen, opt)
+                    recdb.addRecLogProgram(titlen, chtxtn, btimen, etimen, opt, exp, longexp, category)
+                    auto_rec.addKey(chtxt, titlen,exp+" "+longexp)
+                    auto_rec.addKey("ALL", titlen,exp+" "+longexp)
+                    recdblist.printutf8(u"追いかけ機能実行中: "+title+" : "+titlen+" "+btimen+" "+etimen)
+                except Exception, inst:
+                    recdblist.addCommonlogEX("Error", "Oikake DB(timerec.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+            else:
+                recdblist.printutf8(u"追いかけ機能エラー:番組データが見付かりません。")
+        else:
+            if rec10d.rec10db.select_by_bctype_epg_ch(bctypet)[0][5] != "0":
+                rec10d.rec10db.update_status_by_bctype_epg_ch(bctypet, "3")
+        sys.exit()
+    elif (dt <= 30 * 60 and dt > 20 * 60):
+        recdata = epgdb.searchTime(title, btime, "5", chtxt)
+        chtxtn = recdata[0]
+        titlen = recdata[1]
+        btimen = recdata[2]
+        etimen = recdata[3]
+        exp = recdata[4]
+        longexp = recdata[5]
+        category=recdata[6]
+        bt = datetime.datetime.strptime(btimen, "%Y-%m-%d %H:%M:%S")
+        et = datetime.datetime.strptime(etimen, "%Y-%m-%d %H:%M:%S")
+        btimen = bt.strftime("%Y-%m-%d %H:%M:%S")
+        etimen = et.strftime("%Y-%m-%d %H:%M:%S")
+        if chtxt != "":
+            try:
+                recdb.deleteReckey(typetxtnow, title, chtxt, btime)
+                recdb.reserveReckey(typetxtfinal, titlen, chtxtn, btimen, etimen, opt)
+                recdb.addRecLogProgram(titlen, chtxtn, btimen, etimen, opt, exp, longexp, category)
+                auto_rec.addKey(chtxt, titlen,exp+" "+longexp)
+                auto_rec.addKey("ALL", titlen,exp+" "+longexp)
+                #recdblist.printutf8(u"追いかけ機能実行中: "+title+" : "+titlen+" "+btimen+" "+etimen)
+                recdblist.addCommonlogEX(u"通常", "Oikake (timerec.py)",u"追いかけ機能実行中",u"追いかけ機能実行中: "+title+" : "+titlen+" "+btimen+" "+etimen,log_level=500)
+            except Exception, inst:
+                recdblist.addCommonlogEX("Error", "Oikake DB(timerec.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+    elif dt <= 20 * 60:
+        try:
+            recdb.deleteReckey(typetxtnow, title, chtxt, btime)
+            recdb.reserveReckey(typetxtfinal, title, chtxt, btime, etime, opt)
+        except Exception, inst:
+            recdblist.addCommonlogEX("Error", "Oikake DB(timerec.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+def type_final(typetxt,chtxt,title,bt,et,opt):
+    btime = bt.strftime("%Y-%m-%d %H:%M:%S")
+    etime = et.strftime("%Y-%m-%d %H:%M:%S")
+    typetxtnow=typetxt
+    typetxting=""
+    typetxtdecque=""
+    if typetxt==recdblist.REC_FINAL_RESERVE:
+        typetxting=recdblist.REC_TS_RECORDING
+        typetxtdecque=recdblist.REC_TS_DECODE_QUE
+    tnow = datetime.datetime.now()
+    dtt = bt-tnow
+    dt = dtt.days * 24 * 60 * 60 + dtt.seconds
+    if dt < 6 * 60 and dt > 0:
+        newtitle=title
+        recdb.deleteReckey(typetxtnow, title, chtxt, btime)
+        testpath=[os.path.join(recpath,title+".ts.b25")]
+        testpath.append(os.path.join(recpath,title+".ts"))
+        testpath.append(os.path.join(recpath,title+".avi"))
+        testpath.append(os.path.join(recpath,title+".mp4"))
+        testpath.append(os.path.join(recpath,title+".log"))
+        tcheck=0
+        for ti in testpath:
+            if os.path.exists(ti):
+                tcheck=tcheck+1
+        if re.search("N", opt) or tcheck>0:
+            iff=""
+            try:
+                iff=u"("+configreader.getConfEnv("iff")+u")_"
+            except:
+                iff=""
+            newtime=bt
+            newtitle=newtitle+u"_"+iff+newtime.strftime("%Y-%m-%dT%H-%M-%S")
+        recdb.reserveReckey(typetxting, newtitle, chtxt, btime, etime, opt)
+        recdblist.addCommonlogEX(u"通常","timerec.py",u"録画開始 "+newtitle+" "+btime+" "+etime,"",log_level=500)
+        tv2avi.timetv2b25(recpath + "/" + newtitle + ".avi", chtxt, btime, etime, opt)
+        recdb.deleteReckey(typetxting, newtitle, chtxt, btime)
+        if not re.search("R", opt):
+            tnow = datetime.datetime.now()
+            bt = datetime.datetime.strptime(btime, "%Y-%m-%d %H:%M:%S")
+            et = datetime.datetime.strptime(etime, "%Y-%m-%d %H:%M:%S")
+            dt = tnow-bt
+            bt = tnow + datetime.timedelta(seconds=600)
+            et = et + dt + datetime.timedelta(seconds=600)
+            btime = bt.strftime("%Y-%m-%d %H:%M:%S")
+            etime = et.strftime("%Y-%m-%d %H:%M:%S")
+            recdb.reserveReckey(typetxtdecque, newtitle, chtxt, btime, etime, opt)
+        else:
+            try:
+                try:
+                    shutil.copy(os.path.join(recpath,title+".ts.b25"), os.path.join(movepath,title+".ts.b25"))
+                except:
+                    ""
+                try:
+                    os.chmod(os.path.join(movepath,title+".ts.b25"),0777)
+                except:
+                    ""
+                recque.writeRecQue(movepath, chtxt, title, opt)
+                try:
+                    os.chmod(os.path.join(movepath,title+".recq"),0777)
+                except:
+                    ""
+            except Exception, inst:
+                recdblist.addCommonlogEX("Error", "Move option(timerec.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+            recdb.reserveReckey(recdblist.REC_MOVE_END, newtitle, chtxt, btime, etime, opt)
+        sys.exit()
+def type_keyword(typetxt,chtxt,title,bt,et,opt,deltatime):
+    btime = bt.strftime("%Y-%m-%d %H:%M:%S")
+    etime = et.strftime("%Y-%m-%d %H:%M:%S")
+    typetxtnow=typetxt
+    typetxtres=""
+    if typetxt==recdblist.REC_KEYWORD:
+        typetxtres=recdblist.REC_RESERVE
+    tnow = datetime.datetime.now()
+    dtt = bt-tnow
+    dt = dtt.days * 24 * 60 * 60 + dtt.seconds
+    recdblist.printutf8(str(dt), verbose_level=800)
+    if dt <= 90 * 60 and dt > 70 * 60:
+        recdata = epgdb.searchTime(title, btime, deltatime, chtxt)
+        if recdata[1] != "":
+            chtxtt = recdata[0]
+            titlet = recdata[1]
+            btimet = recdata[2]
+            etimet = recdata[3]
+            exp = recdata[4]
+            longexp = recdata[5]
+            category=recdata[6]
+            bt = datetime.datetime.strptime(btimet, "%Y-%m-%d %H:%M:%S")
+            et = datetime.datetime.strptime(etimet, "%Y-%m-%d %H:%M:%S")
+            btimet = bt.strftime("%Y-%m-%d %H:%M:%S")
+            etimet = et.strftime("%Y-%m-%d %H:%M:%S")
+            #try:
+            recdb.deleteReckey(typetxtnow, title, chtxt, btime)
+            recdb.reserveReckey(typetxtres, titlet, chtxt, btimet, etimet, opt)
+            recdb.addRecLogProgram(titlet, chtxtt, btimet, etimet, opt, exp,longexp,category)
+            auto_rec.addKey(chtxt, titlet,exp+" "+longexp)
+            auto_rec.addKey("ALL", titlet,exp+" "+longexp)
+            recdblist.addCommonlogEX(u"通常","timerec.py",u"key "+title+u" : "+titlet+u" "+btimet+u" "+etimet,"",log_level=500)
+            #except Exception, inst:
+            #    recdblist.printutf8("Error happened in REC_KEYWORD DB")
+            #    recdblist.printutf8(type(inst))
+            #    recdblist.printutf8(inst)
+        else:
+            recdblist.printutf8("nothing match")
+    elif dt <= 70 * 60:
+        recdb.deleteReckey(typetxtnow, title, chtxt, btime)
+        recdb.reserveReckey(typetxtres, title, chtxt, btime, etime, opt)
+        recdblist.addCommonlogEX(u"エラー","timerec.py",u"nothing match","",log_level=200)
+        recdblist.addCommonlogEX(u"エラー","timerec.py",u"key "+title+u" "+btime+u" "+etime,"",log_level=200)
+def type_keyword_every_day(type,chtxt,title,bt,et,opt,deltatime,deltaday,counter):
+    btime = bt.strftime("%Y-%m-%d %H:%M:%S")
+    etime = et.strftime("%Y-%m-%d %H:%M:%S")
+    tnow = datetime.datetime.now()
+    dtt = bt-tnow
+    dt = dtt.days * 24 * 60 * 60 + dtt.seconds
+    dd = datetime.timedelta(days=int(deltaday))
+    if dtt.days < 0:
+        recdb.deleteReckey(recdblist.REC_KEYWORD_EVERY_SOME_DAYS, title, chtxt, btime)
+        bt = bt + dd
+        et = et + dd
+        btxt = bt.strftime("%Y-%m-%d %H:%M:%S")
+        etxt = et.strftime("%Y-%m-%d %H:%M:%S")
+        if counter>0:
+            recdb.reserveEverydayKeyword(title, chtxt, btxt, etxt, deltatime, opt, deltaday,counter-1)
+        elif counter==-1:
+            recdb.reserveEverydayKeyword(title, chtxt, btxt, etxt, deltatime, opt, deltaday,-1)
+    elif dt < 120 * 60:
+        recdb.deleteReckey(recdblist.REC_KEYWORD_EVERY_SOME_DAYS, title, chtxt, btime)
+        bt = bt + dd
+        et = et + dd
+        btxt = bt.strftime("%Y-%m-%d %H:%M:%S")
+        etxt = et.strftime("%Y-%m-%d %H:%M:%S")
+        if counter>0:
+            recdb.reserveEverydayKeyword(title, chtxt, btxt, etxt, deltatime, opt, deltaday,counter-1)
+        elif counter==-1:
+            recdb.reserveEverydayKeyword(title, chtxt, btxt, etxt, deltatime, opt, deltaday,-1)
+        recdata = epgdb.searchTime(title, btime, deltatime, chtxt)
+        if recdata[1] != "":
+            chtxtt = recdata[0]
+            titlet = recdata[1]
+            btimet = recdata[2]
+            etimet = recdata[3]
+            exp = recdata[4]
+            longexp = recdata[5]
+            category=recdata[6]
+            bt = datetime.datetime.strptime(btimet, "%Y-%m-%d %H:%M:%S")
+            et = datetime.datetime.strptime(etimet, "%Y-%m-%d %H:%M:%S")
+            btimet = bt.strftime("%Y-%m-%d %H:%M:%S")
+            etimet = et.strftime("%Y-%m-%d %H:%M:%S")
+            #try:
+            recdb.reserveKeyword(titlet, chtxt, btimet, etimet, deltatime, opt)
+        else:
+            recdb.reserveKeyword(title, chtxt, btime, etime, deltatime, opt)
+def type_decode_que(typetxt,chtxt,title,bt,et,opt):
+    btime = bt.strftime("%Y-%m-%d %H:%M:%S")
+    etime = et.strftime("%Y-%m-%d %H:%M:%S")
+    tnow = datetime.datetime.now()
+    dtt = bt-tnow
+    dt = dtt.days * 24 * 60 * 60 + dtt.seconds
+    typetxtnow=typetxt
+    typetxting=""
+    typetxtmiss=""
+    typetxtencque=""
+    if typetxt== recdblist.REC_TS_DECODE_QUE:
+        typetxting=recdblist.REC_TS_DECODING
+        typetxtmiss=recdblist.REC_MISS_DECODE
+        typetxtencque=recdblist.REC_ENCODE_QUE
+    tnow = datetime.datetime.now()
+    dtt = bt-tnow
+    dt = dtt.days * 24 * 60 * 60 + dtt.seconds
+    if dt < 10 * 60:
+        if status.getB25Decoding() < 2:
+            pin = recpath + "/" + title
+            recdb.deleteReckey(typetxtnow, title, chtxt, btime)
+            recdb.reserveReckey(typetxting, title, chtxt, btime, etime, opt)
+            tv2avi.b252ts(pin, chtxt, btime, etime, opt)
+            recdb.deleteReckey(typetxting, title, chtxt, btime)
+            if not os.access(recpath + "/" + title + ".ts", os.F_OK):
+                recdb.deleteReckey(typetxting, title, chtxt, btime)
+                recdb.reserveReckey(typetxtmiss, title, chtxt, btime, etime, opt)
+            else:
+                auto_process.deleteTmpFile(recpath, title, ".ts")
+            bt = datetime.datetime.strptime(btime, "%Y-%m-%d %H:%M:%S")
+            et = datetime.datetime.strptime(etime, "%Y-%m-%d %H:%M:%S")
+            dt = et-bt
+            if not re.search("D", opt):
+                tnow = datetime.datetime.now()
+                bt = tnow + datetime.timedelta(seconds=600)
+                et = bt + dt
+                btime = bt.strftime("%Y-%m-%d %H:%M:%S")
+                etime = et.strftime("%Y-%m-%d %H:%M:%S")
+                recdb.reserveReckey(typetxtencque, title, chtxt, btime, etime, opt)
+            else:
+                try:
+                    try:
+                        shutil.copy(os.path.join(recpath,title+".ts"), os.path.join(movepath,title+".ts"))
+                    except:
+                        ""
+                    try:
+                        os.chmod(os.path.join(movepath,title+".ts"),0777)
+                    except:
+                        ""
+                    recque.writeRecQue(movepath, chtxt, title, opt)
+                    try:
+                        os.chmod(os.path.join(movepath,title+".recq"),0777)
+                    except:
+                        ""
+                    time.sleep(5)
+                    if os.path.getsize(os.path.join(recpath,title+".ts"))==os.path.getsize(os.path.join(movepath,title+".ts")):
+                        os.remove(os.path.join(recpath,title+".ts"))
+                except Exception, inst:
+                    errtxt1="move ts error.\n"
+                    errtxt2=str(type(inst))+"\n"
+                    errtxt2=errtxt2+str(inst)
+                    recdblist.addCommonlogEX("Error", "type_decode_que(timerec.py)", errtxt1,errtxt2+traceback.format_exc(),log_level=200)
+                recdb.reserveReckey(recdblist.REC_MOVE_END, title, chtxt, btime, etime, opt)
+        else:
+            recdb.deleteReckey(typetxtnow, title, chtxt, btime)
+            bt = bt + datetime.timedelta(seconds=600)
+            et = et + datetime.timedelta(seconds=600)
+            btime = bt.strftime("%Y-%m-%d %H:%M:%S")
+            etime = et.strftime("%Y-%m-%d %H:%M:%S")
+            recdb.reserveReckey(typetxtnow, title, chtxt, btime, etime, opt)
+    sys.exit()
+
+def type_encode_que(typetxt,chtxt,title,bt,et,opt):
+    btime = bt.strftime("%Y-%m-%d %H:%M:%S")
+    etime = et.strftime("%Y-%m-%d %H:%M:%S")
+    tnow = datetime.datetime.now()
+    dtt = bt-tnow
+    dt = dtt.days * 24 * 60 * 60 + dtt.seconds
+    typetxtnow=typetxt
+    typetxting=""
+    typetxtfin=""
+    if typetxt==recdblist.REC_ENCODE_QUE:
+        typetxting=recdblist.REC_ENCODE_LOCAL
+        typetxtfin=recdblist.REC_FIN_LOCAL
+    if dt < 10 * 60:
+        if status.getEncoding() < int(configreader.getConfEnv("enc_max")):
+            recdb.deleteReckey(typetxtnow, title, chtxt, btime)
+            recdb.reserveReckey(typetxting, title, chtxt, btime, etime, opt)
+            recdblist.printutf8(opt)
+            pin = recpath + "/" + title + ".ts"
+            if re.search("d", opt):
+                pin = recpath + "/" + title + ".m2v"
+                if not os.path.exists(pin) or os.path.getsize(pin)<100*1000:
+                    paac2 = recpath + "/" + title + "_2.aac"
+                    pmp32 = recpath + "/" + title + "_2.mp3"
+                    if not os.path.exists(paac2) and not os.path.exists(pmp32):
+                        tv2audio.ts2dualaudio_BonTsDemux(os.path.join(recpath, title+".ts"),recdblist.BONTSDEMUX_DELAY,opt)
+                time.sleep(3)
+            elif re.search("5", opt):
+                pin = recpath + "/" + title + ".m2v"
+                if not os.path.exists(pin) or os.path.getsize(pin)<100*1000:
+                    paac2 = recpath + "/" + title + "_2.aac"
+                    pmp32 = recpath + "/" + title + "_2.mp3"
+                    if not os.path.exists(paac2) and not os.path.exists(pmp32):
+                        tv2audio.ts2pentaaudio_BonTsDemux(os.path.join(recpath, title+".ts"), recdblist.BONTSDEMUX_DELAY, opt)
+                time.sleep(3)
+            elif re.search("b", opt):
+                pin = recpath + "/" + title + ".m2v"
+                if not os.path.exists(pin) or os.path.getsize(pin)<100*1000:
+                    paac2 = recpath + "/" + title + ".aac"
+                    pmp32 = recpath + "/" + title + ".mp3"
+                    if not os.path.exists(paac2) and not os.path.exists(pmp32):
+                        tv2audio.ts2single_fp_BonTsDemux(os.path.join(recpath, title+".ts"),opt)
+                time.sleep(3)
+            makeMP4=0
+            try:
+                if configreader.getConfEnv("make_mp4")=="1":
+                    makeMP4=1
+            except:
+                ""
+            if re.search("m", opt):
+                makeMP4=0
+            if re.search("4", opt):
+                makeMP4=1
+            recdblist.printutf8(pin)
+            if not re.search("0", opt):
+                if makeMP4==1:
+                    pout = recpath + "/" + title + ".mp4"
+                    tv2mp4.ts2mp4(pin, pout, opt)
+                else:
+                    pout = recpath + "/" + title + ".mkv"
+                    tv2mkv.ts2mkv(pin, pout, opt)
+                if re.search("1", opt) or re.search("2", opt):
+                    optt=opt.replace("1","MW1")
+                    optt=optt.replace("2","MW2")
+                    poutt = recpath + "/" + "m_"+title + ".mp4"
+                    if re.search("d", opt) or re.search("5", opt):
+                        if os.path.exists(os.path.join(recpath, "m_"+title+".m2v")):
+                            shutil.move(os.path.join(recpath, title+".m2v"),os.path.join(recpath, "m_"+title+".m2v"))
+                        if os.path.exists(os.path.join(recpath, "m_"+title+"_1.aac")):
+                            shutil.move(os.path.join(recpath, title+"_1.aac"),os.path.join(recpath, "m_"+title+"_1.aac"))
+                        if os.path.exists(os.path.join(recpath, "m_"+title+"_1.mp3")):
+                            shutil.move(os.path.join(recpath, title+"_1.mp3"),os.path.join(recpath, "m_"+title+"_1.mp3"))
+                        if os.path.exists(os.path.join(recpath, "m_"+title+"_2.aac")):
+                            shutil.move(os.path.join(recpath, title+"_2.aac"),os.path.join(recpath, "m_"+title+"_2.aac"))
+                        if os.path.exists(os.path.join(recpath, "m_"+title+"_2.mp3")):
+                            shutil.move(os.path.join(recpath, title+"_2.mp3"),os.path.join(recpath, "m_"+title+"_2.mp3"))
+                    shutil.move(os.path.join(recpath, title+".ts"),os.path.join(recpath, "m_"+title+".ts"))
+                    tv2mp4.ts2mp4(os.path.join(recpath, "m_"+title+".ts"), poutt, optt)
+                    shutil.move(os.path.join(recpath, "m_"+title+".ts"),os.path.join(recpath, title+".ts"))
+            else:
+                optt=opt
+                poutt = recpath + "/" + "m_"+title + ".mp4"
+                shutil.move(os.path.join(recpath, title+".ts"),os.path.join(recpath, "m_"+title+".ts"))
+                if re.search("d", opt) or re.search("5", opt):
+                    if os.path.exists(os.path.join(recpath, "m_"+title+".m2v")):
+                        shutil.move(os.path.join(recpath, title+".m2v"),os.path.join(recpath, "m_"+title+".m2v"))
+                    if os.path.exists(os.path.join(recpath, "m_"+title+"_1.aac")):
+                        shutil.move(os.path.join(recpath, title+"_1.aac"),os.path.join(recpath, "m_"+title+"_1.aac"))
+                    if os.path.exists(os.path.join(recpath, "m_"+title+"_1.mp3")):
+                        shutil.move(os.path.join(recpath, title+"_1.mp3"),os.path.join(recpath, "m_"+title+"_1.mp3"))
+                    if os.path.exists(os.path.join(recpath, "m_"+title+"_2.aac")):
+                        shutil.move(os.path.join(recpath, title+"_2.aac"),os.path.join(recpath, "m_"+title+"_2.aac"))
+                    if os.path.exists(os.path.join(recpath, "m_"+title+"_2.mp3")):
+                        shutil.move(os.path.join(recpath, title+"_2.mp3"),os.path.join(recpath, "m_"+title+"_2.mp3"))
+                tv2mp4.ts2mp4(os.path.join(recpath, "m_"+title+".ts"), poutt, optt)
+                shutil.move(os.path.join(recpath, "m_"+title+".ts"),os.path.join(recpath, title+".ts"))
+            recdb.deleteReckey(typetxting, title, chtxt, btime)
+            time.sleep(10)
+            if re.search("E", opt):
+                try:
+                    if os.path.exists(os.path.join(recpath,title+".mp4")):
+                        try:
+                            shutil.copy(os.path.join(recpath,title+".mp4"), os.path.join(movepath,title+".mp4"))
+                        except:
+                            ""
+                        try:
+                            os.chmod(os.path.join(movepath,title+".mp4"),0777)
+                        except:
+                            ""
+                        recque.writeRecQue(movepath, chtxt, title, opt)
+                        try:
+                            os.chmod(os.path.join(movepath,title+".recq"),0777)
+                        except:
+                            ""
+                    elif os.path.exists(os.path.join(recpath,title+".mkv")):
+                        try:
+                            shutil.copy(os.path.join(recpath,title+".mkv"), os.path.join(movepath,title+".mkv"))
+                        except:
+                            ""
+                        try:
+                            os.chmod(os.path.join(movepath,title+".mkv"),0777)
+                        except:
+                            ""
+                        recque.writeRecQue(movepath, chtxt, title, opt)
+                        try:
+                            os.chmod(os.path.join(movepath,title+".recq"),0777)
+                        except:
+                            ""
+                except Exception, inst:
+                    errtxt1="move mkv/mp4 error."
+                    errtxt2=str(type(inst))+"\n"
+                    errtxt2=errtxt2+str(inst)
+                    recdblist.addCommonlogEX("Error", "type_encode_que(timerec.py)", errtxt1,errtxt2+traceback.format_exc(),log_level=200)
+                recdb.reserveReckey(recdblist.REC_MOVE_END, title, chtxt, btime, etime, opt)
+            recdb.reserveReckey(typetxtfin, title, chtxt, btime, etime, opt)
+            sys.exit()
+        else:
+            recdb.deleteReckey(typetxtnow, title, chtxt, btime)
+            bt = bt + datetime.timedelta(seconds=600)
+            et = et + datetime.timedelta(seconds=600)
+            btime = bt.strftime("%Y-%m-%d %H:%M:%S")
+            etime = et.strftime("%Y-%m-%d %H:%M:%S")
+            recdb.reserveReckey(typetxtnow, title, chtxt, btime, etime, opt)
+            sys.exit()
diff --git a/dist/trunk/rec10/ts2epg.py b/dist/trunk/rec10/ts2epg.py
new file mode 100755 (executable)
index 0000000..011eb96
--- /dev/null
@@ -0,0 +1,66 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+#import sys # モジュール属性 argv を取得するため\r
+import os\r
+import re\r
+import time\r
+import commands\r
+\r
+import chdb\r
+import configreader\r
+import tv2ts\r
+import recdblist\r
+\r
+def writeEpgXML(pout, ch):\r
+    """\r
+    tsを取得してepgの入ったxmlとして書き出す\r
+    """\r
+    timet = "90"\r
+    if re.search(u'CS', ch):\r
+        timet = "180"\r
+    elif len(ch)>2:\r
+        timet = "240"\r
+    writeEpgXMLTime(pout, ch ,timet)\r
+def writeLogoEpgXML(pout, ch):\r
+    """\r
+    tsを取得してepgの入ったxmlとして書き出す\r
+    """\r
+    timet = "600"\r
+    if re.search(u'CS', ch):\r
+        timet = "10"\r
+    elif len(ch)>2:\r
+        timet = "1200"\r
+    writeEpgXMLTime(pout, ch ,timet,islogo=1)\r
+def writeEpgXMLTime(pout, ch ,times,islogo=0):\r
+    """\r
+    指定された時間分tsを取得してepgの入ったxmlとして書き出す\r
+    """\r
+    if islogo==0:\r
+        recdblist.addCommonlogEX(u"通常","write_time(ts2epg.py)",u"Ts-EPG XML書き出し処理開始" ,u"CH:"+ch,log_level=500)\r
+    elif islogo==1:\r
+        recdblist.addCommonlogEX(u"通常","write_time(ts2epg.py)",u"Ts-EPG LOGO : XML書き出し処理開始" ,u"CH:"+ch,log_level=500)\r
+    timet = times\r
+    if re.search(u'CS', ch):\r
+        mode = "/CS"\r
+    elif len(ch)>2:\r
+        mode = "/BS"\r
+    else:\r
+        mode = str(chdb.searchCHFromBctype(u'te' + ch)['ch'])\r
+    epgdump = configreader.getConfPath("epgdump")\r
+    if os.access(pout + ".ts", os.F_OK):\r
+        os.remove(pout + ".ts")\r
+    time.sleep(10)\r
+    tv2ts.tv2b25ts(pout+ ".ts", ch, times)\r
+    logoopt=""\r
+    if islogo==1:\r
+        logoopt="/LOGO "\r
+    exe = "export LANG=ja_JP.UTF-8 && nice -n 15 " + epgdump + " " +logoopt+ mode + " " + pout + ".ts " + pout\r
+    recdblist.printutf8(exe)\r
+    recdblist.addCommonlogEX(u"通常", "write_time(ts2epg.py) "+str(ch), exe,"",log_level=500)\r
+    unicode(commands.getoutput(exe),'utf-8','ignore')\r
+    time.sleep(10)\r
+    if os.path.exists(pout+".ts"):\r
+        os.remove(pout+ ".ts")\r
+\r
diff --git a/dist/trunk/rec10/ts2x264.py b/dist/trunk/rec10/ts2x264.py
new file mode 100755 (executable)
index 0000000..ef46832
--- /dev/null
@@ -0,0 +1,619 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import commands\r
+import configreader\r
+import os\r
+import os.path\r
+import re\r
+import random\r
+import time\r
+import traceback\r
+import zip\r
+\r
+import recdblist\r
+def ts2x264(pin, pout, opts):#sizeは"HD"か"SD"\r
+    """\r
+    pinで指定されたファイルをpoutにx264でエンコードして書き出す\r
+    """\r
+    dualpass = 0\r
+    is24fps=0\r
+    size="HD"\r
+    crf=18\r
+    quality=4\r
+    quality=int(configreader.getConfEnv("x264_preset"))\r
+    crf=int(configreader.getConfEnv("crf"))\r
+    deinterlace=1\r
+    bluray=0\r
+    sar=1\r
+    if re.search("H", opts):\r
+        size = "HD"\r
+    if re.search("S", opts):\r
+        size = "WVGA"\r
+    if re.search("F", opts):\r
+        size = "FullHD"\r
+    if re.search("W",opts):\r
+        size = "WVGA"\r
+    if re.search("MW1",opts):\r
+        size = "QVGA_BASE"\r
+        crf=crf+4\r
+        sar=0\r
+    if re.search("MW2", opts):\r
+        size = "WVGA_BASE"\r
+        crf=crf+2\r
+        sar=0\r
+    if re.search("v", opts):\r
+        is24fps=1\r
+        crf=int(configreader.getConfEnv("animation_crf"))\r
+    if re.search("a", opts):\r
+        is24fps=1\r
+        crf=int(configreader.getConfEnv("animation_crf"))\r
+    if re.search("I", opts):\r
+        deinterlace=0\r
+    if re.search("B", opts):\r
+        bluray=1\r
+        sar=0\r
+    if re.search("q",opts):\r
+        quality=quality-2\r
+    if re.search("w",opts):\r
+        quality=quality-1\r
+    if re.search("e",opts):\r
+        quality=quality+1\r
+    if re.search("r",opts):\r
+        quality=quality+2\r
+    if re.search("u",opts):\r
+        crf=crf+2\r
+    if re.search("i",opts):\r
+        crf=crf+1\r
+    if re.search("o",opts):\r
+        crf=crf-1\r
+    if re.search("p",opts):\r
+        crf=crf-2\r
+    if re.search("d",opts):#二カ国語放送の場合\r
+        tm2v=pin.replace(".ts",".m2v")\r
+        encodeFfmpegSar(tm2v,pout,size,is24fps,quality,crf,deinterlace=deinterlace,usebluray=bluray,usesar=sar)\r
+    elif re.search("5",opts):#5.1chの場合\r
+        encodeFfmpegSar(pin,pout,size,is24fps,quality,crf,deinterlace=deinterlace,usebluray=bluray,usesar=sar)\r
+    elif re.search("b",opts):#BonTsDemuxを使いたい場合\r
+        tm2v=pin.replace(".ts",".m2v")\r
+        encodeFfmpegSar(tm2v,pout,size,is24fps,quality,crf,deinterlace=deinterlace,usebluray=bluray,usesar=sar)\r
+    else:\r
+        try:\r
+            encodeMencoderSar(pin, pout,size,is24fps,quality,crf,deinterlace=deinterlace,uselavf=1,usebluray=bluray,usesar=sar)\r
+            if os.path.exists(pout):\r
+                if not os.path.getsize(pout)>1*1000:\r
+                    recdblist.addCommonlogEX("Warning", "Old mencoder option used.","","",log_level=200)\r
+                    try:\r
+                        encodeMencoderSar(pin, pout,size,is24fps,quality,crf,deinterlace=deinterlace,uselavf=0,usebluray=bluray,usesar=sar)\r
+                    except Exception, inst:\r
+                        recdblist.addCommonlogEX("Error", "ts2x264_mencoder_old(ts2x264.py)", str(type(inst)), str(inst)+traceback.format_exc(),log_level=200)\r
+            else:\r
+                recdblist.addCommonlogEX("Warning", "Old mencoder option used.","","",log_level=200)\r
+                try:\r
+                    encodeMencoderSar(pin, pout,size,is24fps,quality,crf,deinterlace=deinterlace,uselavf=0,usebluray=bluray,usesar=sar)\r
+                except Exception, inst:\r
+                    recdblist.addCommonlogEX("Error", "ts2x264_mencoder_old(ts2x264.py)", str(type(inst)), str(inst)+traceback.format_exc(),log_level=200)\r
+        except Exception, inst:\r
+            recdblist.addCommonlogEX("Error", "ts2x264(ts2x264.py)", str(type(inst)), str(inst)+traceback.format_exc(),log_level=200)\r
+def encodeMencoderSar(pin,pout,size,is24fps,quality,crf,deinterlace=1,uselavf=0,usebluray=0,usesar=1):\r
+    mencoder=configreader.getConfPath("mencoder")\r
+    tee=configreader.getConfPath("tee")\r
+    encvf=""\r
+    txt=""\r
+    encvf="-sws 9 -vf yadif=0,pp=l5"\r
+    harddup=",hqdn3d=2:1:2,unsharp=l3x3:0.75:c3x3:0.75,harddup"\r
+    ofps="-ofps 30000/1001"\r
+    fps="-fps 30000/1001"\r
+    x264fps="30000/1001 --keyint 30"\r
+    x264streamsize=""\r
+    x264preset=""\r
+    x264tune=""\r
+    x264_bitrate="5000"\r
+    x264interlaced=0\r
+    x264sar="1:1"\r
+    tsar=getMoviePAR2(pin)\r
+    if usesar==1:\r
+        x264sar=str(tsar[0])+u":"+str(tsar[1])\r
+    lavft=""\r
+    if is24fps==1:\r
+        ofps="-ofps 24000/1001"\r
+        fps="-fps 30000/1001"\r
+        x264fps="24000/1001 --keyint 24"\r
+        x264tune="--tune animation"\r
+        encvf="-sws 9 -vf pullup,softskip"\r
+        harddup=",pp=l5,unsharp=l3x3:0.75:c3x3:0.75,hqdn3d=2:1:2,harddup"\r
+    if size == "HD":\r
+        tsize=getParSize(pin,720)\r
+        if usesar==1:\r
+            encvf = encvf + ",scale=-3:720::0:3"+harddup\r
+            x264streamsize=str(tsize[0])+u"x720"\r
+        else:\r
+            encvf = encvf + ",scale=-2:720::0:3,expand=1280:720"+harddup\r
+            x264streamsize=u"1280x720"\r
+        x264_bitrate="2500"\r
+    elif size == "WVGA":\r
+        tsize=getParSize(pin,480)\r
+        if usesar==1:\r
+            encvf = encvf + ",scale=-3:480::0:3"+harddup\r
+            x264streamsize=str(tsize[0])+u"x480"\r
+        else:\r
+            encvf = encvf + ",scale=-2:480::0:3,expand=854:480"+harddup\r
+            x264streamsize=u"854x480"\r
+        x264_bitrate="1500"\r
+    elif size == "FullHD":\r
+        tsize=getParSize(pin,1080)\r
+        if usesar==1:\r
+            encvf = encvf + ",scale=-3:1080::0:3"+harddup\r
+            x264streamsize=str(tsize[0])+u"x1080"\r
+        else:\r
+            encvf = encvf + ",scale=-2:1080::0:3,expand=1920:1080"+harddup\r
+            x264streamsize=u"1920x1080"\r
+        x264_bitrate="5000"\r
+    elif size == "QVGA_BASE":\r
+        tsize=getParSize(pin,240)\r
+        if usesar==1:\r
+            encvf = encvf + ",scale=-3:240::0:3"+harddup\r
+            x264streamsize=str(tsize[0])+u"x240"\r
+        else:\r
+            encvf = encvf + ",scale=320:-2::0:3,expand=320:240"+harddup\r
+            x264streamsize=u"320x240"\r
+        x264_bitrate="300"\r
+    elif size == "WVGA_BASE":\r
+        tsize=getParSize(pin,480)\r
+        if usesar==1:\r
+            encvf = encvf + ",scale=-3:480::0:3"+harddup\r
+            x264streamsize=str(tsize[0])+u"x480"\r
+        else:\r
+            encvf = encvf + ",scale=-2:480::0:3,expand=854:480"+harddup\r
+            x264streamsize=u"854x480"\r
+        x264_bitrate="1500"\r
+    else:\r
+        tsize=getParSize(pin,720)\r
+        if usesar==1:\r
+            encvf = encvf + ",scale=-3:720::0:3"+harddup\r
+            x264streamsize=str(tsize[0])+u"x720"\r
+        else:\r
+            encvf = encvf + ",scale=-2:720::0:3,expand=1280:720"+harddup\r
+            x264streamsize=u"1280x720"\r
+        x264_bitrate="2500"\r
+    if deinterlace==0:\r
+        tsize=getMovieBaseSize2(pin)\r
+        ofps="-ofps 30000/1001"\r
+        #fps="-fps 30000/1001"\r
+        fps=""\r
+        x264fps="30000/1001 --keyint 30"\r
+        x264interlaced=1\r
+        encvf="-vf hqdn3d=2:1:2"\r
+        harddup=",harddup"\r
+        encvf=encvf+harddup\r
+        x264streamsize=str(tsize[0])+u"x"+str(tsize[1])\r
+        if usebluray==1:\r
+            encvf = encvf + ",scale=-2:1080::0:3,expand=1920:1080"+harddup\r
+            x264streamsize=u"1920x1080"\r
+    if tsize[0] <= 0 or tsize[1] <= 0:\r
+        encvf="-sws 9 -vf yadif=0,pp=l5"\r
+        harddup=",hqdn3d=2:1:2,unsharp=l3x3:0.75:c3x3:0.75,harddup"\r
+        ofps="-ofps 30000/1001"\r
+        fps="-fps 30000/1001"\r
+        x264fps="30000/1001 --keyint 30"\r
+        tsize=[1280,720]\r
+        encvf = encvf + ",scale=-2:720::0:3,expand=1280:720"+harddup\r
+        x264streamsize=u"1280x720"\r
+        x264_bitrate="2500"\r
+    if quality==1:\r
+        x264preset=u"ultrafast"\r
+    elif quality==2:\r
+        x264preset=u"veryfast"\r
+    elif quality==3:\r
+        x264preset=u"fast"\r
+    elif quality==4:\r
+        x264preset=u"medium"\r
+    elif quality==5:\r
+        x264preset=u"slow"\r
+    elif quality==6:\r
+        x264preset=u"slower"\r
+    else:\r
+        x264preset=u"medium"\r
+    if size == "WVGA_BASE" or size == "QVGA_BASE":\r
+        x264profile=" --level 32 --profile baseline "\r
+    else:\r
+        x264profile=" --level 41 --profile high "\r
+    if uselavf==1:\r
+        lavft="-demuxer lavf "\r
+    x264crf=str(crf)\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    random.seed(pin)\r
+    random.jumpahead(10)\r
+    temptime=int(time.time())\r
+    temptime=temptime % 9697\r
+    random.jumpahead(temptime)\r
+    streampath=os.path.join(os.path.dirname(pin),str(random.randint(10000, 99999999)))\r
+    unicode(commands.getoutput(u"mkfifo "+streampath),'utf-8','ignore')\r
+    logmencoder=recdblist.getLogTitle(pin)+".mencoder.log"\r
+    logx264=recdblist.getLogTitle(pin)+".x264.log"\r
+    encexe=mencoder+u" \""+pin+u"\" -quiet -vfm ffmpeg "+lavft+encvf+u",format=i420 "+fps+" "+ofps+" -oac mp3lame -ovc raw -of rawvideo -o \""+streampath+"\" 2>&1 | "+tee+" \""+logmencoder+"\" & "\r
+    encexe=encexe+getX264Commandline(x264preset, x264sar, x264fps, x264profile, x264tune, pout, streampath, x264streamsize, crf=x264crf,interlaced=x264interlaced,bluray=usebluray)\r
+    #encexe=encexe+u" nice -n 19 "+x264+" "+x264_sar+" "+x264crf+u" "+x264_addline+u"  --threads "+x264_thread+" "+x264profile+x264preset+" "+x264tune+" "+x264fps+" -o \""+pout+"\" "+streampath+" "+x264streamsize\r
+    encexe=u"nice -n 19 " +encexe+" 2>&1 | "+tee+" \""+logx264+"\""\r
+    try:\r
+        recdblist.addCommandSelfLog(pin, encexe)\r
+    except Exception, inst:\r
+        print type(inst)\r
+        print str(inst)\r
+        print traceback.print_exc(file=sys.stdout)\r
+    recdblist.printutf8(encexe)\r
+    txt=""\r
+    try:\r
+        txt=unicode(commands.getoutput(encexe.encode('utf-8')),'utf-8','ignore')\r
+    except:\r
+        ""\r
+    os.remove(streampath)\r
+    zip.addFile2FileZip(logmencoder, recdblist.getLogTitle(pin)+".log.zip")\r
+    zip.addFile2FileZip(logx264, recdblist.getLogTitle(pin)+".log.zip")\r
+    os.remove(logmencoder)\r
+    os.remove(logx264)\r
+    recdblist.addCommandLog(pin, u"Mencoder", encexe, txt)\r
+#    recdblist.addCommandLogTar(pin,u"Mencoder","mencoder", encexe,txt)\r
+def encodeFfmpegSar(pin,pout,size,is24fps,quality,crf,deinterlace=1,usebluray=0,usesar=1):\r
+    """\r
+\r
+    """\r
+    ffmpeg=configreader.getConfPath("ffmpeg")\r
+    tee=configreader.getConfPath("tee")\r
+    fps=u"-r 29.970030 "\r
+    x264fps="30000/1001 --keyint 30"\r
+    x264streamsize=""\r
+    x264preset=""\r
+    x264tune=""\r
+    x264_bitrate="2500"\r
+    x264_thread="auto"\r
+    x264interlaced=0\r
+    tsar=getMoviePAR2(pin)\r
+    filter="-deinterlace"\r
+    x264sar=str(tsar[0])+":"+str(tsar[1])\r
+    if is24fps==1:\r
+        fps=u"-r 23.976023 "\r
+        x264fps="24000/1001 --keyint 24"\r
+        x264tune="--tune animation"\r
+    if size == "HD":\r
+        tsize=getParSize(pin,720)\r
+        s = "-s "+str(tsize[0])+"x720 "\r
+        x264streamsize=str(tsize[0])+u"x720"\r
+        x264_bitrate="2500"\r
+    elif size == "WVGA":\r
+        tsize=getParSize(pin,480)\r
+        s = "-s "+str(tsize[0])+"x480 "\r
+        x264streamsize=str(tsize[0])+u"x480"\r
+        x264_bitrate="1500"\r
+    elif size == "FullHD":\r
+        tsize=getParSize(pin,1080)\r
+        s = "-s "+str(tsize[0])+"x1080 "\r
+        x264streamsize=str(tsize[0])+u"x1080"\r
+        x264_bitrate="5000"\r
+    elif size == "SD":\r
+        tsize=getParSize(pin,480)\r
+        s = "-s "+str(tsize[0])+"x480 "\r
+        x264streamsize=str(tsize[0])+u"x480"\r
+        x264_bitrate="1250"\r
+    elif size == "QVGA_BASE":\r
+        tsize=getParSize(pin,240)\r
+        s = "-s "+str(tsize[0])+"x240 "\r
+        x264streamsize=str(tsize[0])+u"x240"\r
+        x264_bitrate="300"\r
+    elif size == "WVGA_BASE":\r
+        tsize=getParSize(pin,480)\r
+        s = "-s "+str(tsize[0])+"x480 "\r
+        x264streamsize=str(tsize[0])+u"x480"\r
+        x264_bitrate="1500"\r
+    else:\r
+        tsize=getParSize(pin,720)\r
+        s = "-s "+str(tsize[0])+"x720 "\r
+        x264streamsize=str(tsize[0])+u"x720"\r
+        x264_bitrate="2500"\r
+    if deinterlace==0:\r
+        tsize=getMovieBaseSize2(pin)\r
+        fps=""\r
+        s = "-s "+str(tsize[0])+"x"+str(tsize[1])+" "\r
+        x264fps="30000/1001 --keyint 30"\r
+        x264interlaced=1\r
+        filter=""\r
+        x264streamsize=str(tsize[0])+u"x"+str(tsize[1])\r
+    if quality==1:\r
+        x264preset=u"ultrafast"\r
+    elif quality==2:\r
+        x264preset=u"veryfast"\r
+    elif quality==3:\r
+        x264preset=u"fast"\r
+    elif quality==4:\r
+        x264preset=u"medium"\r
+    elif quality==5:\r
+        x264preset=u"slow"\r
+    elif quality==6:\r
+        x264preset=u"slower"\r
+    else:\r
+        x264preset=u"medium"\r
+    if size == "WVGA_BASE" or size == "QVGA_BASE":\r
+        x264profile=" --level 32 --profile baseline "\r
+    else:\r
+        x264profile=" --level 41 --profile high "\r
+    x264crf=str(crf)\r
+    txt=""\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    log_ffmpeg=recdblist.getLogTitle(pin)+".ffmpeg.log"\r
+    log_x264=recdblist.getLogTitle(pin)+".x264.log"\r
+    exe=ffmpeg+u" -y -i \""+pin+"\" -vsync 400 -vcodec rawvideo -pix_fmt yuv420p "+s+fps+" "+filter+" -an -f rawvideo - 2> \""+log_ffmpeg+"\" | "\r
+    exe=exe+getX264Commandline(x264preset, x264sar, x264fps, x264profile, x264tune, pout,"-", x264streamsize, crf=x264crf,interlaced=x264interlaced,bluray=usebluray)\r
+    exe = "nice -n 19 " + exe+" 2>&1 | "+tee+" \""+log_x264+"\""\r
+    txt=""\r
+    #recdblist.addCommandSelfLog(log_ffmpeg,recdblist.getLogTitle(pin)+".log.zip")\r
+    #recdblist.addCommandSelfLog(log_x264,recdblist.getLogTitle(pin)+".log.zip")\r
+    recdblist.printutf8(exe)\r
+    recdblist.addCommandSelfLog(pin,exe)\r
+    try:\r
+        txt=unicode(commands.getoutput(exe.encode('utf-8')),'utf-8','ignore')\r
+    except:\r
+        ""\r
+    recdblist.addCommandLog(pin, u"FFmpeg動画エンコード", exe, txt)\r
+    zip.addFile2FileZip(log_ffmpeg, recdblist.getLogTitle(pin+".log.zip"))\r
+    zip.addFile2FileZip(log_x264, recdblist.getLogTitle(pin+".log.zip"))\r
+    os.remove(log_ffmpeg)\r
+    os.remove(log_x264)\r
+def getMovieBaseSize(pin):\r
+    ffmpeg=configreader.getConfPath("ffmpeg")\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    exe=ffmpeg+u" -i \""+pin+"\" 2>&1"\r
+    txts=unicode(commands.getoutput(exe.encode('utf-8')),'utf-8','ignore')\r
+    rT=re.compile(u".*Stream.*#.*:.*\D+([\d]+x[\d]+)\D+PAR\D+(\d+:\d+)\D+.*\Z")\r
+    sizeMaxX=0\r
+    sizeMaxY=0\r
+    txtls=txts.split("\n")\r
+    for t in txtls:\r
+        rM=rT.match(t)\r
+        if rM:\r
+            sizetxt=rM.group(1)\r
+            partxt=rM.group(2)\r
+            tX=int(sizetxt.split("x")[0])\r
+            tY=int(sizetxt.split("x")[1])\r
+            tEX=int(partxt.split(":")[0])\r
+            tEY=int(partxt.split(":")[1])\r
+            if sizeMaxX<tX:\r
+                sizeMaxX=tX\r
+                sizeMaxY=tY\r
+    return [sizeMaxX,sizeMaxY]\r
+def getMovieBaseSize2(pin):##動画開始後すぐに解像度が変更されたときに対処\r
+    ffmpeg=configreader.getConfPath("ffmpeg")\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    exe=ffmpeg+u" -ss 5 -fs 1 -i \""+pin+"\" \""+pin+".size.ts\" 2>&1"\r
+    try:\r
+        recdblist.addCommandSelfLog(pin, exe)\r
+    except Exception, inst:\r
+        print type(inst)\r
+        print str(inst)\r
+        print traceback.print_exc(file=sys.stdout)\r
+    txts=unicode(commands.getoutput(exe.encode('utf-8')),'utf-8','ignore')\r
+    rT=re.compile(u"Stream.*#.*:.*\D+([\d]+x[\d]+)\D+PAR\D+(\d+:\d+)\D+.*\Z")\r
+    sizeMaxX=0\r
+    sizeMaxY=0\r
+    txtls=txts.split("\n")\r
+    for t in txtls:\r
+        rM=rT.search(t)\r
+        if rM:\r
+            sizetxt=rM.group(1)\r
+            partxt=rM.group(2)\r
+            tX=int(sizetxt.split("x")[0])\r
+            tY=int(sizetxt.split("x")[1])\r
+            tEX=int(partxt.split(":")[0])\r
+            tEY=int(partxt.split(":")[1])\r
+            if sizeMaxX<tX:\r
+                sizeMaxX=tX\r
+                sizeMaxY=tY\r
+    os.remove(pin+".size.ts")\r
+    return [sizeMaxX,sizeMaxY]\r
+def getMoviePAR(pin):\r
+    ffmpeg=configreader.getConfPath("ffmpeg")\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    exe=ffmpeg+u" -i \""+pin+"\" 2>&1"\r
+    txts=unicode(commands.getoutput(exe.encode('utf-8')),'utf-8','ignore')\r
+    rT=re.compile(u".*Stream.*#.*:.*\D+([\d]+x[\d]+)\D+PAR\D+(\d+:\d+)\D+.*\Z")\r
+    sizeMaxX=0\r
+    parx=0\r
+    pary=0\r
+    txtls=txts.split("\n")\r
+    for t in txtls:\r
+        rM=rT.match(t)\r
+        if rM:\r
+            sizetxt=rM.group(1)\r
+            dartxt=rM.group(2)\r
+            tX=int(sizetxt.split("x")[0])\r
+            tY=int(sizetxt.split("x")[1])\r
+            tEX=int(dartxt.split(":")[0])\r
+            tEY=int(dartxt.split(":")[1])\r
+            if sizeMaxX<tX:\r
+                sizeMaxX=tX\r
+                if tX==1920 and tY==1080:\r
+                    parx=1\r
+                    pary=1\r
+                else:\r
+                    parx=tEX\r
+                    pary=tEY\r
+    return [parx,pary]\r
+def getMoviePAR2(pin):\r
+    ffmpeg=configreader.getConfPath("ffmpeg")\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    exe=ffmpeg+u" -ss 5 -fs 1 -i \""+pin+"\" \""+pin+".size.ts\" 2>&1"\r
+    try:\r
+        recdblist.addCommandSelfLog(pin, exe)\r
+    except Exception, inst:\r
+        print type(inst)\r
+        print str(inst)\r
+        print traceback.print_exc(file=sys.stdout)\r
+    txts=unicode(commands.getoutput(exe.encode('utf-8')),'utf-8','ignore')\r
+    rT=re.compile(u".*Stream.*#.*:.*\D+([\d]+x[\d]+)\D+PAR\D+(\d+:\d+)\D+.*\Z")\r
+    sizeMaxX=0\r
+    parx=0\r
+    pary=0\r
+    txtls=txts.split("\n")\r
+    for t in txtls:\r
+        rM=rT.match(t)\r
+        if rM:\r
+            sizetxt=rM.group(1)\r
+            dartxt=rM.group(2)\r
+            tX=int(sizetxt.split("x")[0])\r
+            tY=int(sizetxt.split("x")[1])\r
+            tEX=int(dartxt.split(":")[0])\r
+            tEY=int(dartxt.split(":")[1])\r
+            if sizeMaxX<tX:\r
+                sizeMaxX=tX\r
+                if tX==1920 and tY==1080:\r
+                    parx=1\r
+                    pary=1\r
+                else:\r
+                    parx=tEX\r
+                    pary=tEY\r
+    os.remove(pin+".size.ts")\r
+    return [parx,pary]\r
+def getMovieDAR(pin):\r
+    ffmpeg=configreader.getConfPath("ffmpeg")\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    exe=ffmpeg+u" -i \""+pin+"\" 2>&1"\r
+    txts=unicode(commands.getoutput(exe.encode('utf-8')),'utf-8','ignore')\r
+    rT=re.compile(u".*Stream.*#.*:.*\D+([\d]+x[\d]+)\D+.*DAR\D+(\d+:\d+)\D+.*\Z")\r
+    sizeMaxX=0\r
+    darx=0\r
+    dary=0\r
+    txtls=txts.split("\n")\r
+    for t in txtls:\r
+        rM=rT.match(t)\r
+        if rM:\r
+            sizetxt=rM.group(1)\r
+            dartxt=rM.group(2)\r
+            tX=int(sizetxt.split("x")[0])\r
+            tY=int(sizetxt.split("x")[1])\r
+            tEX=int(dartxt.split(":")[0])\r
+            tEY=int(dartxt.split(":")[1])\r
+            if sizeMaxX<tX:\r
+                sizeMaxX=tX\r
+                if tX==1920 and tY==1080:\r
+                    darx=16\r
+                    dary=9\r
+                else:\r
+                    darx=tEX\r
+                    dary=tEY\r
+    return [darx,dary]\r
+def getMovieDAR2(pin):\r
+    ffmpeg=configreader.getConfPath("ffmpeg")\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    exe=ffmpeg+u" -ss 5 -fs 1 -i \""+pin+"\" \""+pin+".size.ts\" 2>&1"\r
+    txts=unicode(commands.getoutput(exe.encode('utf-8')),'utf-8','ignore')\r
+    rT=re.compile(u".*Stream.*#.*:.*\D+([\d]+x[\d]+)\D+.*DAR\D+(\d+:\d+)\D+.*\Z")\r
+    sizeMaxX=0\r
+    darx=0\r
+    dary=0\r
+    txtls=txts.split("\n")\r
+    for t in txtls:\r
+        rM=rT.match(t)\r
+        if rM:\r
+            sizetxt=rM.group(1)\r
+            dartxt=rM.group(2)\r
+            tX=int(sizetxt.split("x")[0])\r
+            tY=int(sizetxt.split("x")[1])\r
+            tEX=int(dartxt.split(":")[0])\r
+            tEY=int(dartxt.split(":")[1])\r
+            if sizeMaxX<tX:\r
+                sizeMaxX=tX\r
+                if tX==1920 and tY==1080:\r
+                    darx=16\r
+                    dary=9\r
+                else:\r
+                    darx=tEX\r
+                    dary=tEY\r
+    os.remove(pin+".size.ts")\r
+    return [darx,dary]\r
+def getParSize(pin,y):\r
+    tSize=getMovieBaseSize2(pin)\r
+    if tSize[1] != 0 :\r
+        tX=tSize[0]*10*y/tSize[1]\r
+        tY=y\r
+        if tX>int(tX/10)*10:\r
+            tX=tX/10+1\r
+        else:\r
+            tX=tX/10\r
+    else:\r
+        tX=-1\r
+        tY=-1\r
+    return [tX,tY]\r
+def getX264CoreVersion():\r
+    x264=configreader.getConfPath("x264")\r
+    #print x264\r
+    t1=commands.getoutput(x264+" --help|grep core")\r
+    #print t1\r
+    rT=re.compile(u"x264 core:(\d*)[\d]*.*\Z")\r
+    rM=rT.match(t1)\r
+    v=-1\r
+    if rM:\r
+        v=int(rM.group(1))\r
+    return v\r
+def getX264Commandline(preset,sar,fps,x264profile,x264tune,pout,pin,x264streamsize,crf=-1,bitrate=0,interlaced=0,bluray=0):\r
+    x264=configreader.getConfPath("x264")\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    x264_sar="--sar "+sar\r
+    x264preset=u"--preset "+preset\r
+    x264fps="--fps "+fps\r
+    x264interlaced=""\r
+    x264bluray=""\r
+    x264_addline=configreader.getConfEnv("x264_addline")\r
+    if crf==-1:\r
+        x264bitrate=u"--bitrate "+str(bitrate)\r
+    else:\r
+        x264crf=u"--crf "+str(crf)\r
+    if interlaced==1:\r
+        x264interlaced="--tff --nal-hrd vbr"\r
+    if bluray==1:\r
+        if getX264CoreVersion()<115:\r
+            x264bluray="--demuxer raw --weightp 1 --nal-hrd vbr --bframes 3 --b-pyramid none --open-gop bluray --slices 4 --aud --colorprim bt709 --transfer bt709 "\r
+            x264_addline=""\r
+            if fps=="24000/1001 --keyint 24" or fps =="24000/1001":\r
+                if x264streamsize=="1280x720":\r
+                    x264bluray=u"--ref 6 "+x264bluray\r
+                if x264streamsize=="1920x1080":\r
+                    x264bluray=u"--ref 3 "+x264bluray\r
+            elif fps=="30000/1001 --keyint 30" or fps =="30000/1001":\r
+                if x264streamsize=="1280x720":\r
+                    x264bluray=u"--ref 6 --pulldown double "+x264bluray\r
+                if x264streamsize=="1920x1080":\r
+                    if interlaced==0:\r
+                        x264bluray=u"--ref 3 --fake-interlaced --pic-struct "+x264bluray\r
+                    else:\r
+                        x264bluray=u"--ref 3 "+x264bluray\r
+        elif getX264CoreVersion()>=115:\r
+            x264bluray="--demuxer raw --bluray-compat --open-gop --nal-hrd vbr --bframes 3 --b-pyramid none --aud --colorprim bt709 --transfer bt709 "\r
+            x264_addline=""\r
+            if fps=="24000/1001 --keyint 24" or fps =="24000/1001":\r
+                if x264streamsize=="1280x720":\r
+                    x264bluray=u"--ref 6 "+x264bluray\r
+                if x264streamsize=="1920x1080":\r
+                    x264bluray=u"--ref 3 "+x264bluray\r
+            elif fps=="30000/1001 --keyint 30" or fps =="30000/1001":\r
+                if x264streamsize=="1280x720":\r
+                    x264bluray=u"--ref 6 "+x264bluray\r
+                if x264streamsize=="1920x1080":\r
+                    if interlaced==0:\r
+                        x264bluray=u"--ref 3 --fake-interlaced --pic-struct "+x264bluray\r
+                    else:\r
+                        x264bluray=u"--ref 3 "+x264bluray\r
+    x264_thread="auto"\r
+    try:\r
+        xtt=configreader.getConfEnv("x264_thread")\r
+        xtt=int(xtt)\r
+        if xtt>0:\r
+            x264_thread=str(xtt)\r
+    except:\r
+        x264_thread="auto"\r
+    x264_addline=configreader.getConfEnv("x264_addline")\r
+    if getX264CoreVersion()>103:\r
+        x264res=u"--input-res "+x264streamsize\r
+        exe=u"nice -n 19 "+x264+" "+x264_sar+" "+x264crf+u" "+x264bluray+u" "+x264interlaced+u" "+x264_addline+u" --colormatrix bt709 --threads "+x264_thread+" "+x264profile+x264preset+" "+x264tune+" "+x264fps+" "+x264res+" -o \""+pout+"\" "+pin\r
+    else:\r
+        exe=u"nice -n 19 "+x264+" "+x264_sar+" "+x264crf+u" "+x264bluray+u" "+x264interlaced+u" "+x264_addline+u" --colormatrix bt709 --threads "+x264_thread+" "+x264profile+x264preset+" "+x264tune+" "+x264fps+" -o \""+pout+"\" "+pin+" "+x264streamsize\r
+    return exe\r
diff --git a/dist/trunk/rec10/tv2audio.py b/dist/trunk/rec10/tv2audio.py
new file mode 100755 (executable)
index 0000000..cc837e8
--- /dev/null
@@ -0,0 +1,267 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+\r
+import commands\r
+import os\r
+import re\r
+import shutil\r
+import time\r
+import os.path\r
+import subprocess\r
+import signal\r
+\r
+import configreader\r
+import recdblist\r
+\r
+def wav2aac_nero(pin,pout):\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    neroaac=configreader.getConfPath('NeroAAC')\r
+    exe=neroaac+" -br 128000 -2pass -if \""+pin+"\" -of \""+pout+"\""\r
+    try:\r
+        txt=commands.getoutput(exe.encode('utf-8'))\r
+        recdblist.addLog(pin, exe, u"Wav2aac_Neroログ-コマンド")\r
+        recdblist.addLog(pin, txt, u"Wav2aac_Neroログ-詳細")\r
+    except:\r
+        if not os.path.exists(pout):\r
+            lame="lame"\r
+            exe=lame+" -b 128 \""+pin+"\" \""+pout+"\""\r
+            txt=commands.getoutput(exe.encode('utf-8'))\r
+            recdblist.addLog(pin, exe, u"Wav2aac_Lameログ-コマンド")\r
+            recdblist.addLog(pin, txt, u"Wav2aac_Lameログ-詳細")\r
+def wav2mp3_lame(pin,pout):\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    lame=configreader.getConfPath('lame')\r
+    exe=lame+" -b 128 \""+pin+"\" \""+pout+"\""\r
+    try:\r
+        txt=commands.getoutput(exe.encode('utf-8'))\r
+    except:\r
+        ""\r
+    recdblist.addLog(pin, exe, u"Wav2aac_Lameログ-コマンド")\r
+    recdblist.addLog(pin, txt, u"Wav2aac_Lameログ-詳細")\r
+def ts2single_audio(pts,opts):\r
+    paac=pts.replace(".ts",".aac")\r
+    ffmpeg=configreader.getConfPath("ffmpeg")\r
+    e0=ffmpeg+" -i \""+pts+"\" -y -vn -acodec copy \""+paac+"\""\r
+    p0=subprocess.Popen(e0,shell=True)\r
+    os.waitpid(p0.pid, 0)\r
+    if p0.poll==None:#実行中\r
+        if os.path.exists(paac):\r
+            if os.path.getsize(paac)<1000:#1mで1kb以下の場合自動で終了\r
+                try:\r
+                    logt=unicode(p0.communicate()[0], "UTF-8")\r
+                    recdblist.addLog(pts,e0, "FFmpeg音声取り出しログ-コマンド")\r
+                    recdblist.addLog(pts,logt, "FFmpeg音声取り出しログ-詳細")\r
+                except:\r
+                    ""\r
+                recdblist.addCommonlogEX("[Error]", "ffmpeg aac getting. (ts2single_audio@tv2audio.py)", u"AAC demux error(ffmpeg)", "", verbose_level=200, log_level=200)\r
+                os.kill(p0.pid,signal.SIGKILL)\r
+                os.remove(paac)\r
+                ts2single_mp3_ffmpeg(pts)\r
+                if not os.path.exists(pts.replace(".ts",".mp3")):\r
+                    ts2single_fp_BonTsDemux(pts,opts)\r
+            else:\r
+                logt=unicode(p0.communicate()[0], "UTF-8")\r
+                recdblist.addLog(pts,e0, "FFmpeg音声取り出しログ-コマンド")\r
+                recdblist.addLog(pts,logt, "FFmpeg音声取り出しログ-詳細")\r
+        else:\r
+            try:\r
+                logt=unicode(p0.communicate()[0], "UTF-8")\r
+                recdblist.addLog(pts,e0, "FFmpeg音声取り出しログ-コマンド")\r
+                recdblist.addLog(pts,logt, "FFmpeg音声取り出しログ-詳細")\r
+            except:\r
+                ""\r
+            recdblist.addCommonlogEX("[Error]", "ffmpeg aac getting. (ts2single_audio@tv2audio.py)", u"AAC demux error(ffmpeg)", "", verbose_level=200, log_level=200)\r
+            try:\r
+                os.kill(p0.pid,signal.SIGKILL)\r
+            except:\r
+                ""\r
+            ts2single_mp3_ffmpeg(pts)\r
+            if not os.path.exists(pts.replace(".ts",".mp3")):\r
+                ts2single_fp_BonTsDemux(pts,opts)\r
+    else:\r
+        if os.path.exists(paac):\r
+            if os.path.getsize(paac)<1000:#1mで1kb以下の場合自動で終了\r
+                try:\r
+                    logt=unicode(p0.communicate()[0], "UTF-8")\r
+                    recdblist.addLog(pts,e0, "FFmpeg音声取り出しログ-コマンド")\r
+                    recdblist.addLog(pts,logt, "FFmpeg音声取り出しログ-詳細")\r
+                except:\r
+                    ""\r
+                recdblist.addCommonlogEX("[Error]", "ffmpeg aac getting. (ts2single_audio@tv2audio.py)", u"AAC demux error(ffmpeg)", "", verbose_level=200, log_level=200)\r
+                os.remove(paac)\r
+                ts2single_mp3_ffmpeg(pts)\r
+                if not os.path.exists(pts.replace(".ts",".mp3")):\r
+                    ts2single_fp_BonTsDemux(pts,opts)\r
+            else:\r
+                try:\r
+                    logt=unicode(p0.communicate()[0], "UTF-8")\r
+                    recdblist.addLog(pts,e0, "FFmpeg音声取り出しログ-コマンド")\r
+                    recdblist.addLog(pts,logt, "FFmpeg音声取り出しログ-詳細")\r
+                except:\r
+                    ""\r
+        else:\r
+            try:\r
+                logt=unicode(p0.communicate()[0], "UTF-8")\r
+                recdblist.addLog(pts,e0, "FFmpeg音声取り出しログ-コマンド")\r
+                recdblist.addLog(pts,logt, "FFmpeg音声取り出しログ-詳細")\r
+            except:\r
+                ""\r
+            recdblist.addCommonlogEX("[Error]", "ffmpeg aac getting. (ts2single_audio@tv2audio.py)", u"AAC demux error(ffmpeg)", "", verbose_level=200, log_level=200)\r
+            ts2single_mp3_ffmpeg(pts)\r
+            if not os.path.exists(pts.replace(".ts",".mp3")):\r
+                ts2single_fp_BonTsDemux(pts,opts)\r
+def ts2singlewav(pts,opts):\r
+    bontsdemux = configreader.getConfPath('bontsdemux')\r
+    bonpin = "Z:\\" + pts[1:]\r
+    outf = os.path.splitext(pts)[0]\r
+    bonpout = "Z:\\" + outf[1:]\r
+    delayt=""\r
+    exe = 'wine ' + bontsdemux + " -i \"" + bonpin + "\" "+delayt+" -nd -sound 0 -o \"" + bonpout + "\""\r
+    #recdblist.printutf8(exe)\r
+    recdblist.printutf8(exe)\r
+    txt=commands.getoutput(exe.encode('utf-8'))\r
+    recdblist.addCommandLog(pts, u"BonTsDemux 音声取り出し", exe, txt)\r
+def ts2single_mp3_ffmpeg(pts):\r
+    pmp3=pts.replace(".ts",".mp3")\r
+    ffmpeg=configreader.getConfPath("ffmpeg")\r
+    e0=ffmpeg+" -i \""+pts+"\" -y -vn -ab 128k \""+pmp3+"\""\r
+    p0=subprocess.Popen(e0,shell=True)\r
+    os.waitpid(p0.pid, 0)\r
+    try:\r
+        logt=unicode(p0.communicate()[0], "UTF-8")\r
+        recdblist.addLog(pts,e0, "FFmpeg_mp3音声取り出しログ-コマンド")\r
+        recdblist.addLog(pts,logt, "FFmpeg_mp3音声取り出しログ-詳細")\r
+    except:\r
+        ""\r
+def ts2single_fp_BonTsDemux(pts,opts):\r
+    useNero=0\r
+    try:\r
+        if configreader.getConfPath("useNeroAAC")=="1" and os.path.exists(configreader.getConfPath("NeroAAC")):\r
+            useNero=1\r
+    except:\r
+        useNero=0\r
+    if useNero==1:\r
+        ts2single_aac_BonTsDemux_Nero(pts,opts)\r
+    else:\r
+        ts2single_mp3_BonTsDemux(pts,opts)\r
+def ts2single_aac_BonTsDemux_Nero(pts,opts):\r
+    ts2singlewav(pts,opts)\r
+    aout=pts.replace(".ts",".aac")\r
+    ain=pts.replace(".ts",".wav")\r
+    wav2aac_nero(ain,aout)\r
+def ts2single_mp3_BonTsDemux(pts,opts):\r
+    ts2singlewav(pts,opts)\r
+    aout=pts.replace(".ts",".mp3")\r
+    ain=pts.replace(".ts",".wav")\r
+    wav2mp3_lame(ain,aout)\r
+def ts2dualaudio_BonTsDemux(pin, delay,opts):\r
+    """\r
+    delay is string\r
+    """\r
+    bontsdemux = configreader.getConfPath('bontsdemux')\r
+    wine = configreader.getConfPath('wine')\r
+    bonpin = "Z:\\" + pin[1:]\r
+    outf = os.path.splitext(pin)[0]\r
+    bonpout = "Z:\\" + outf[1:]\r
+    exe = wine + ' ' + bontsdemux + " -i \"" + bonpin + "\" -delay " + delay + " -nd -sound 1 -o \"" + bonpout + "\""\r
+    recdblist.printutf8(exe)\r
+    txt=commands.getoutput(exe.encode('utf-8'))\r
+    try:\r
+        recdblist.addCommandLog(pin, u"BonTsDemux 第一音声取り出し", exe, txt)\r
+    except:\r
+        ""\r
+    ffpin = pin.replace(".ts", "")\r
+    ffpin1 = pin.replace("ts", "wav")\r
+    ffpin2 = pin.replace("ts", "m2v")\r
+    ffpout1 = ffpin + "_1.wav"\r
+    ffpout2 = ffpin + "_2.wav"\r
+    ffpout3 = ffpin + ".m2v"\r
+    shutil.move(ffpin1, ffpout1)\r
+    exe = wine + ' ' + bontsdemux + " -i \"" + bonpin + "\" -delay " + delay + " -nd -sound 2 -encode Demux\(wav\) -o \"" + bonpout + "\""\r
+    recdblist.printutf8(exe)\r
+    txt=commands.getoutput(exe.encode('utf-8'))\r
+    try:\r
+        recdblist.addCommandLog(pin, u"BonTsDemux 第二音声取り出し", exe, txt)\r
+    except:\r
+        ""\r
+    #os.system(exe)\r
+    shutil.move(ffpin1, ffpout2)\r
+    shutil.move(ffpin2, ffpout3)\r
+    ffpout21=ffpout1.replace(".wav",".mp3")\r
+    ffpout22=ffpout2.replace(".wav",".mp3")\r
+    useNero=0\r
+    try:\r
+        if os.path.exists(configreader.getConfPath("NeroAAC")):\r
+            useNero=1\r
+    except:\r
+        useNero=0\r
+    if useNero==1:\r
+        ffpout21=ffpout1.replace(".wav",".aac")\r
+        ffpout22=ffpout2.replace(".wav",".aac")\r
+        wav2aac_nero(ffpout1, ffpout21)\r
+        wav2aac_nero(ffpout2, ffpout22)\r
+    else:\r
+        wav2mp3_lame(ffpout1, ffpout21)\r
+        wav2mp3_lame(ffpout2, ffpout22)\r
+    time.sleep(3)\r
+    os.remove(ffpout1)\r
+    os.remove(ffpout2)\r
+def ts2pentaaudio_BonTsDemux(pin, delay,opts):\r
+    bontsdemux = configreader.getConfPath('bontsdemux')\r
+    wine = configreader.getConfPath('wine')\r
+    bonpin = "Z:\\" + pin[1:]\r
+    outf = os.path.splitext(pin)[0]\r
+    bonpout = "Z:\\" + outf[1:]\r
+    exe = wine + ' ' + bontsdemux + " -i \"" + bonpin + "\" -delay "+delay+" -nd -sound 3 -o \"" + bonpout + "\""\r
+    recdblist.printutf8(exe)\r
+    txt=commands.getoutput(exe.encode('utf-8'))\r
+    try:\r
+        recdblist.addCommandLog(pin, u"BonTsDemux5.1ch 第一音声取り出し", exe, txt)\r
+    except:\r
+        ""\r
+    ffpin = pin.replace(".ts", "")\r
+    ffpin1 = pin.replace("ts", "wav")\r
+    ffpin2 = pin.replace("ts", "m2v")\r
+    ffpout1 = ffpin + "_1.wav"\r
+    ffpout2 = ffpin + "_2.aac"\r
+    shutil.move(ffpin1, ffpout1)\r
+    exe = "ffmpeg -i '"+pin+"' -vn -f aac -acodec copy '"+ffpout2+"'"\r
+    recdblist.printutf8(exe)\r
+    txt=commands.getoutput(exe.encode('utf-8'))\r
+    try:\r
+        recdblist.addCommandLog(pin, u"FFmpeg 5.1ch 第二音声(raw AAC)取り出し", exe, txt)\r
+    except:\r
+        ""\r
+    ffpout21=ffpout1.replace(".wav",".mp3")\r
+    useNero=0\r
+    try:\r
+        if os.path.exists(configreader.getConfPath("NeroAAC")):\r
+            useNero=1\r
+    except:\r
+        useNero=0\r
+    if useNero==1:\r
+        ffpout21=ffpout1.replace(".wav",".aac")\r
+        wav2aac_nero(ffpout1, ffpout21)\r
+    else:\r
+        wav2mp3_lame(ffpout1, ffpout21)\r
+    if not os.path.exists(ffpout21):\r
+        exe = wine + ' ' + bontsdemux + " -i \"" + bonpin + "\" -delay "+delay+" -nd -sound 0 -o \"" + bonpout + "\""\r
+        recdblist.printutf8(exe)\r
+        txt=commands.getoutput(exe.encode('utf-8'))\r
+        try:\r
+            recdblist.addCommandLog(pin, u"BonTsDemux 修正版第二音声(2chDownmix)取り出し", exe, txt)\r
+        except:\r
+            ""\r
+        shutil.move(ffpin1, ffpout1)\r
+        if useNero==1:\r
+            ffpout21=ffpout1.replace(".wav",".aac")\r
+            wav2aac_nero(ffpout1, ffpout21)\r
+        else:\r
+            wav2mp3_lame(ffpout1, ffpout21)\r
+        time.sleep(3)\r
+    ffpout21=ffpout1.replace(".wav",".aac")\r
+    if os.path.exists(ffpout21):\r
+        if os.path.getsize(ffpout21)>10*1000*1000:\r
+            os.remove(ffpout1)\r
diff --git a/dist/trunk/rec10/tv2avi.py b/dist/trunk/rec10/tv2avi.py
new file mode 100755 (executable)
index 0000000..9af76d2
--- /dev/null
@@ -0,0 +1,111 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import commands\r
+import datetime\r
+import os\r
+import re\r
+import shutil\r
+import time\r
+import os.path\r
+import traceback\r
+\r
+import chdb\r
+import configreader\r
+import status\r
+import ts2x264\r
+import tv2ts\r
+import recdblist\r
+import tv2audio\r
+\r
+\r
+global Bitrate_SD\r
+global Bitrate_HD\r
+global Bitrate_FHD\r
+global Bitrate_Short\r
+global Bitrate_LowHD\r
+Bitrate_SD = 1250\r
+Bitrate_HD = 3750\r
+Bitrate_LowHD = 2500\r
+Bitrate_FHD = 5000\r
+Bitrate_Short = 1250\r
+def timetv2b25(pout, chtxt, btime, etime, opt):\r
+    """\r
+    poutはタイトル\r
+    """\r
+    bt = datetime.datetime.strptime(btime, "%Y-%m-%d %H:%M:%S")\r
+    et = datetime.datetime.strptime(etime, "%Y-%m-%d %H:%M:%S")\r
+    extt = os.path.splitext(pout)\r
+    tsout = extt[0]\r
+    tnow = datetime.datetime.now()\r
+    wt = bt-tnow\r
+    waitt = wt.seconds\r
+    if waitt>0:\r
+        time.sleep(waitt)\r
+    tnow = datetime.datetime.now()\r
+    dt = et-tnow\r
+    rectime = dt.seconds-5\r
+    rectime = str(rectime)\r
+    tv2ts.tv2b25ts(tsout + ".ts.b25", chdb.searchCHFromChtxt(chtxt)['ch'], rectime)\r
+def b252ts(pout, chtxt, btime, etime, opt):\r
+    """\r
+    poutはタイトル(自動的にtitle.b25 title.tsと名前がつきます。)\r
+    """\r
+    #status.setB25Decoding(status.getB25Decoding() + 1)\r
+    status.changeB25Decoding(1)\r
+    try:\r
+        try:\r
+            chs=chdb.searchCHFromChtxt(chtxt)\r
+            ch=chs['ch']\r
+            csch=chs['csch']\r
+            #print [ch,csch,chtxt]\r
+        except:\r
+            ch=0\r
+            csch=0\r
+        tv2ts.b252ts(pout + ".ts", ch, csch)\r
+        tsout = pout\r
+        aviin = pout + ".ts"\r
+        dualaudio = 0\r
+        pentaaudio = 0\r
+        singleaudiosplit = 0\r
+        if re.search("5", opt):\r
+            pentaaudio = 1\r
+        if re.search("d", opt):\r
+            dualaudio = 1\r
+        if re.search("b", opt):\r
+            singleaudiosplit = 1\r
+        if re.search(u"\[二\]", pout):\r
+            dualaudio = 1\r
+        elif re.search(u'(二)', pout):\r
+            dualaudio = 1\r
+        elif re.search(u'\(二\)', pout):\r
+            dualaudio = 1\r
+        if dualaudio == 1:\r
+            tv2audio.ts2dualaudio_BonTsDemux(aviin, recdblist.BONTSDEMUX_DELAY, opt)\r
+        if pentaaudio == 1:\r
+            tv2audio.ts2pentaaudio_BonTsDemux(aviin, recdblist.BONTSDEMUX_DELAY, opt)\r
+        if singleaudiosplit == 1:\r
+            tv2audio.ts2single_fp_BonTsDemux(aviin, opt)\r
+    except Exception, inst:\r
+        recdblist.addCommonlogEX("Error", "b252ts(tv2avi.py)", str(type(inst))+traceback.format_exc(), str(inst))\r
+    status.changeB25Decoding(-1)\r
+def ts2avi(pin, pout, opt):\r
+    status.changeEncoding(1)\r
+    try:\r
+        ts2x264.ts2x264(pin, pout, opt)\r
+    except Exception, inst:\r
+        recdblist.printutf8("error occures in tv2avi.py ts2avi")\r
+        recdblist.printutf8(str(type(inst)))\r
+        recdblist.printutf8(str(inst)+traceback.format_exc())\r
+    status.changeEncoding(-1)\r
+def ts2raw(pin, pout, opt):\r
+    status.changeEncoding(1)\r
+    try:\r
+        ts2x264.ts2x264(pin, pout, opt)\r
+    except Exception, inst:\r
+        recdblist.printutf8("error occures in tv2avi.py ts2raw")\r
+        recdblist.printutf8(str(type(inst)))\r
+        recdblist.printutf8(str(inst)+traceback.format_exc())\r
+    status.changeEncoding(-1)\r
+\r
diff --git a/dist/trunk/rec10/tv2mkv.py b/dist/trunk/rec10/tv2mkv.py
new file mode 100755 (executable)
index 0000000..e713f98
--- /dev/null
@@ -0,0 +1,21 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import os\r
+import os.path\r
+import tv2mp4\r
+import configreader\r
+import subprocess\r
+import auto_process\r
+def ts2mkv(pin, pout, opt):\r
+    tpout=pout.replace(".mkv",".mp4")\r
+    tv2mp4.ts2mp4(pin, tpout, opt)\r
+    mp42mkv(pout, tpout)\r
+    if os.path.exists(pout) and os.path.getsize(pout)>os.path.getsize(tpout)*0.9:\r
+        os.remove(tpout)\r
+def mp42mkv(pmkv,pmp4):\r
+    exe = configreader.getConfPath("mkvmerge")\r
+    e1=exe +" -o \""+pmkv+u"\" \""+pmp4+"\""\r
+    p=subprocess.Popen(e1,shell=True)\r
+    os.waitpid(p.pid, 0)\r
diff --git a/dist/trunk/rec10/tv2mp4.py b/dist/trunk/rec10/tv2mp4.py
new file mode 100755 (executable)
index 0000000..b5f311f
--- /dev/null
@@ -0,0 +1,228 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+import commands\r
+import shutil\r
+import auto_process\r
+import os\r
+import re\r
+import os.path\r
+import string\r
+import base64\r
+import time\r
+import subprocess\r
+import traceback\r
+import zip\r
+\r
+import tv2avi\r
+import recdblist\r
+import configreader\r
+import status\r
+import tv2audio\r
+\r
+def ts2mp4(pin, pout, opt):\r
+    dir=os.path.split(pout)[0]\r
+    title=os.path.split(pout)[1]\r
+    title=os.path.splitext(title)[0]\r
+    tpraw=os.path.join(dir, title+".264")\r
+    tpmp4=os.path.join(dir, title+".mp4")\r
+    if os.path.isfile(pin) and os.path.getsize(pin)>10*1000:\r
+        tv2avi.ts2raw(pin, tpraw, opt)\r
+        time.sleep(10)\r
+        if os.path.isfile(tpraw) and os.path.getsize(tpraw)>10*1000:\r
+            raw2mp4(tpraw, tpmp4, opt)\r
+        time.sleep(10)\r
+        if os.path.exists(tpraw) and not re.search("B",opt):\r
+            os.remove(tpraw)\r
+    zip.addFile2FileZip(recdblist.getLogTitle(pin)+".command.log", recdblist.getLogTitle(pin)+".log.zip")\r
+    if os.path.exists(recdblist.getLogTitle(pin)+".command.log"):\r
+        os.remove(recdblist.getLogTitle(pin)+".command.log")\r
+def raw2mp4(pin,pout,opt):\r
+    dir=os.path.split(pout)[0]\r
+    title=os.path.split(pout)[1]\r
+    title=os.path.splitext(title)[0]\r
+    duration="-fps 29.970030 "\r
+    if re.search("a",opt):\r
+        duration="-fps 23.976023 "\r
+    if re.search("I",opt):\r
+        duration="-fps 29.970030 "\r
+    exe = configreader.getConfPath("mp4box")\r
+    txt=""\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    pints=pin.replace(".264",".ts")\r
+    e1=exe +u" "+duration+" -add \""+pin+"\" -new \""+pout+"\""\r
+    execmp4box(pin, pout, e1)\r
+    addAudio(pints, pout, opt)\r
+    addCaption(pints, pout)\r
+    if status.getSettings_auto_del_tmp()==1:\r
+        if os.path.exists(pout):\r
+            if not re.search("B",opt):\r
+                auto_process.deleteTmpFile(dir, title, ".mp4")\r
+            else:\r
+                auto_process.deleteTmpFile(dir, title, ".264")\r
+def mkv2mp4(pin,pout):\r
+    exeb = configreader.getConfPath(u"mkvextract")\r
+    exe = configreader.getConfPath(u"mp4Box")\r
+    #dtsedit=configreader.getConfPath("DtsEdit")\r
+    wineexe=configreader.getConfPath("wine")\r
+    dir=os.path.split(pin)[0]\r
+    title=os.path.split(pin)[1]\r
+    title=os.path.splitext(title)[0]\r
+    etitle=base64.b16encode(title.encode('utf-8'))\r
+    audiopath=os.path.join(dir,etitle+u"_audio.aac")\r
+    videopath=os.path.join(dir,etitle+u"_video.264")\r
+    timecodepath=os.path.join(dir,etitle+u"_1_timecode.txt")\r
+    tmpmp4=os.path.join(dir,etitle+u".tmp.mp4")\r
+    exe0=exeb+u" tracks \'"+pin+u"\' 1:\'"+videopath+u"\' 2:\'"+audiopath+u"\'"\r
+    exe1=exeb+u" timecodes_v2 \'"+pin+"\' 1:\'"+timecodepath+"\'"\r
+    exe2=exe+u" -fps 29.970030 -add \'"+videopath+u"\' -add \'"+audiopath+u"\' -new \'"+tmpmp4+u"\'"\r
+    exe3=wineexe+u" "+dtsedit+u" -tc \'Z:\\"+timecodepath+u"\' \'Z:\\"+tmpmp4+u"\' -o \'Z:\\"+pout+u"\'"\r
+    os.environ['LANG']="ja_JP.UTF-8"\r
+    txt=""\r
+    try:\r
+        txt=txt+execcomd(exe0)+"\n"\r
+        txt=txt+execcomd(exe1)+"\n"\r
+        txt=txt+execcomd(exe2)+"\n"\r
+        txt=txt+execcomd(exe3)+"\n"\r
+    except:\r
+        ""\r
+    recdblist.addLog(pin, txt, u"MKV2MP4-log")\r
+    txt = "\n####MKV2MP4-log####\n"+txt\r
+    time.sleep(10)\r
+    if status.getSettings_auto_del_tmp()==1:\r
+        if os.path.exists(pout):\r
+            auto_process.deleteTmpFile(dir, title, ".mp4")\r
+def addCaption(pts,pmp4):##字幕の追加を試みる。\r
+    wineexe=configreader.getConfPath("wine")\r
+    pincap=pts.replace(".ts",".srt")\r
+    try:\r
+        cap2ass=configreader.getConfPath("caption2ass")\r
+    except:\r
+        cap2ass=""\r
+    if os.path.isfile(cap2ass):\r
+        e0=wineexe+u" "+cap2ass+u" -format srt \"Z:\\"+pts+"\" \"Z:\\"+pincap+"\""\r
+        recdblist.printutf8(e0)\r
+        p0=subprocess.Popen(e0,shell=True,stdout=subprocess.PIPE)\r
+        time.sleep(100)\r
+        if p0.poll==None:#実行中\r
+            #if os.path.getsize(pincap)<1000:#2mで1kb以下の場合自動で終了\r
+             #   os.kill(p0.pid,signal.SIGKILL)\r
+            #else:\r
+            os.waitpid(p0.pid, 0)\r
+            logt=unicode(p0.communicate()[0], "UTF-8")\r
+            recdblist.addLog(pts,e0, u"Captionログ-コマンド")\r
+            recdblist.addLog(pts,logt, u"Captionログ-詳細")\r
+            recdblist.addCommandLogZip(pts, "mp4box_caption", "mp4box_caption", e0, logt)\r
+        if os.path.exists(pincap):\r
+            if os.path.getsize(pincap)>1000:\r
+                exe = configreader.getConfPath("mp4box")\r
+                e1s=exe +u" -add \""+pincap+"\" \""+pmp4+"\""\r
+                addmp4(pincap,pmp4,e1s)\r
+def addAudio(pts,pmp4,opts):#オプションに応じた音声の追加を行う\r
+    exe = configreader.getConfPath("mp4box")\r
+    if re.search("d",opts) or re.search("5",opts):#二カ国語放送/5.1ch放送の場合\r
+        paac1=pts.replace(".ts","_1.aac")\r
+        paac2=pts.replace(".ts","_2.aac")\r
+        recdblist.printutf8(paac1)\r
+        if not os.path.exists(paac1):\r
+            paac1=pts.replace(".ts","_1.mp3")\r
+        if not os.path.exists(paac2):\r
+            paac2=pts.replace(".ts","_2.mp3")\r
+        e1a1=exe +u" -add \""+paac1+"\" \""+pmp4+"\""\r
+        e1a2=exe +u" -add \""+paac2+"\" \""+pmp4+"\""\r
+        if os.path.exists(paac1):\r
+            addmp4(paac1, pmp4, e1a1)\r
+        if os.path.exists(paac2):\r
+            addmp4(paac2, pmp4, e1a2)\r
+    elif re.search("b",opts):#BonTsDemuxを使って音声をスプリットした場合\r
+        paac=pts.replace(".ts",".aac")\r
+        if not os.path.exists(paac):\r
+            paac=pts.replace(".ts",".mp3")\r
+        e1a1=exe +u" -add \""+paac+"\" \""+pmp4+"\""\r
+        if os.path.exists(paac):\r
+            addmp4(paac, pmp4, e1a1)\r
+    else:\r
+        tv2audio.ts2single_audio(pts,opts)\r
+        pinaac=pts.replace(".ts",".aac")\r
+        if not os.path.exists(pinaac):\r
+            pinaac=pinaac.replace(".aac",".mp3")\r
+        e1a=exe +u" -add \""+pinaac+"\" \""+pmp4+"\""\r
+        if os.path.exists(pinaac):\r
+            addmp4(pinaac, pmp4, e1a)\r
+def execmp4box(pin,pout,cmd):\r
+    title=os.path.splitext(os.path.split(pin)[1])[0]\r
+    nt=base64.b16encode(title.encode('utf-8'))\r
+    if len(nt)>200:\r
+        nt=nt[:180]\r
+    ptin=os.path.join(os.path.dirname(pin),nt+".264")\r
+    recdblist.printutf8(ptin)\r
+    shutil.move(pin,ptin)\r
+    time.sleep(10)\r
+    ptout=os.path.join(os.path.dirname(pout),nt+".mp4")\r
+    cmdn=string.replace(cmd,pin,ptin)\r
+    cmdn=string.replace(cmdn,pout,ptout)\r
+    recdblist.printutf8(cmdn)\r
+    recdblist.addCommandSelfLog(pin, cmdn)\r
+    txt=""\r
+    try:\r
+        txt=execcomd(cmdn)\r
+    except Exception, inst:\r
+        txt= "error occures in execmp4box\n"\r
+        txt=txt+ str(type(inst))+"\n"\r
+        txt=txt+str(inst)\r
+        recdblist.addCommonlogEX("Error", "excecmp4box(tv2mp4.py)", str(type(inst)), str(inst)+traceback.format_exc(),verbose_level=200,log_level=200)\r
+    recdblist.addLog(pin, cmdn, u"MP4Boxログ-コマンド")\r
+    recdblist.addLog(pin, txt, u"MP4Boxログ-詳細")\r
+    recdblist.addCommandLogZip(pin, "MP4Box", "mp4box", cmdn,txt)\r
+    time.sleep(5)\r
+    shutil.move(ptin,pin)\r
+    shutil.move(ptout,pout)\r
+    time.sleep(5)\r
+def addmp4(padd,pout,cmd):#without video\r
+    title=os.path.splitext(os.path.split(padd)[1])[0]\r
+    ext=os.path.splitext(os.path.split(padd)[1])[1]\r
+    nt=base64.b16encode(title.encode('utf-8'))\r
+    if len(nt)>200:\r
+        nt=nt[:180]\r
+    ptadd=os.path.join(os.path.dirname(padd),nt+ext)\r
+    ptoutb=os.path.join(os.path.dirname(pout),nt+"_b.mp4")\r
+    ptout=os.path.join(os.path.dirname(pout),nt+".mp4")\r
+    shutil.move(padd,ptadd)\r
+    if os.path.isfile(pout):\r
+        shutil.move(pout,ptoutb)\r
+    time.sleep(5)\r
+    cmdn=string.replace(cmd,padd,ptadd)\r
+    cmdn=string.replace(cmdn,u"-out \""+pout,u"-add \""+ptoutb+"\" -new \""+ptout)\r
+    cmdn=string.replace(cmdn,u"\""+pout,u"-add \""+ptoutb+"\" -new \""+ptout)\r
+    cmdn=string.replace(cmdn,pout,ptout)\r
+    recdblist.printutf8(cmdn)\r
+    txt=""\r
+    try:\r
+        txt=execcomd(cmdn)\r
+    except Exception, inst:\r
+        txt= "error occures in addmp4\n"\r
+        txt=txt+ str(type(inst))+"\n"\r
+        txt=txt+str(inst)\r
+    recdblist.addLog(pout, cmdn, u"MP4Box追加ログ-コマンド")\r
+    recdblist.addLog(pout, txt, u"MP4Box追加ログ-詳細")\r
+    recdblist.addCommandLogZip(pout, "MP4Box_add", "mp4box_add", cmdn, txt)\r
+    time.sleep(5)\r
+    shutil.move(ptadd,padd)\r
+    if os.path.exists(ptout):\r
+        shutil.move(ptout,pout)\r
+        os.remove(ptoutb)\r
+    else:\r
+        txtt=padd+u"のインポートエラー"\r
+        recdblist.addLog(pout, txtt, u"MP4Box追加ログ-コマンド")\r
+        shutil.move(ptoutb,pout)\r
+    time.sleep(5)\r
+def execcomd(cmd):\r
+    txt=""\r
+    try:\r
+        txt=u"Cmd : "+cmd+"\n"\r
+        txt2=commands.getoutput(cmd.encode('utf-8'))\r
+        txt=txt+unicode(txt2,"utf-8")+"\n"\r
+    except:\r
+        ""\r
+    return txt\r
diff --git a/dist/trunk/rec10/tv2ts.py b/dist/trunk/rec10/tv2ts.py
new file mode 100755 (executable)
index 0000000..8f706f4
--- /dev/null
@@ -0,0 +1,118 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+#import sys # モジュール属性 argv を取得するため
+import commands
+import os
+import os.path
+import time
+import traceback
+
+import configreader
+import status
+import recdblist
+mypath = str(os.path.dirname(os.path.abspath(__file__))) + "/"
+def tv2tsmix(pout, ch, time,getlog=0):
+    tv2b25ts(pout + ".b25", ch, time)
+    txt=b252tsmix(pout + ".b25", pout)
+    return txt
+    #if os.access(pout, os.F_OK):
+    #    try:
+    #        os.remove(pout + ".b25")
+    #    except:
+    #        ""
+def tv2ts(pout, ch, csch, time):
+    if ch.replace(" ","").replace("CS","").isdigit():
+        if len(ch) > 2:#BS/CSは100とかCS??とかなので3文字以上
+            status.changeBSCSRecording(1)
+        else:
+            status.changeTERecording(1)
+        try:
+            tv2b25ts(pout + ".b25", ch, time)
+        except Exception, inst:
+            recdblist.addCommonlogEX(u"Error",u"tv2ts(tv2ts.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)
+        if len(ch) > 2:#BS/CSは100とかCS??とかなので3文字以上
+            status.changeBSCSRecording(-1)
+        else:
+            status.changeTERecording(-1)
+    else:
+         ch="0"
+         csch="0"
+    b252tsmix(pout + ".b25", pout + ".tsmix")
+    tch="0"
+    if csch!=u"0":
+        tch=csch
+    elif ch==u"101":
+        tch="101"
+    elif ch==u"102":
+        tch="102"
+    #else:
+    #    tch=ch
+    tsmix2ts(pout + ".tsmix", pout, tch)
+    if os.access(pout, os.F_OK):
+        try:
+            #os.remove(path + "/" + t + ext)
+            ""
+        except:
+            ""
+def b252ts(pout, ch, csch):
+    b252tsmix(pout + ".b25", pout + ".tsmix")
+    tch=u"0"
+    if ch.replace(" ","").replace("CS","").isdigit():
+        if csch!=u"0":
+            tch=csch
+        elif ch==u"101":
+            tch=u"101"
+        elif ch==u"102":
+            tch=u"102"
+    else:
+        tch="0"
+    tsmix2ts(pout + ".tsmix", pout, tch)
+def tv2b25ts(pout, ch, time):
+    exe = configreader.getConfPath('recpt1')
+    if len(ch) > 2:#BS/CSは100とかCS??とかなので3文字以上
+        status.changeBSCSRecording(1)
+    else:
+        status.changeTERecording(1)
+    try:
+        doexe = exe + ' ' + ch + ' ' + time + ' \'' + pout + '\''
+        recdblist.printutf8(doexe)
+        recdblist.addLog(pout, doexe, u"recpt1ログ-コマンド")
+        recdblist.addLog(pout, unicode(commands.getoutput(doexe.encode('utf-8')),'utf-8'), u"recpt1ログ-詳細")
+    except Exception, inst:
+        recdblist.addCommonlogEX(u"Error",u"tv2b25ts(tv2ts.py)", str(type(inst)),str(inst))
+    if len(ch) > 2:#BS/CSは100とかCS??とかなので3文字以上
+        status.changeBSCSRecording(-1)
+    else:
+        status.changeTERecording(-1)
+def b252tsmix(pin, pout):
+    if not (os.path.exists(pout) and os.path.getsize(pin)>os.path.getsize(pout)*0.95 and os.path.getsize(pin)<os.path.getsize(pout)*1.05):
+        exe=""
+        if configreader.getConfPath('b25_remote')=="1":
+            try:
+                exe = configreader.getConfPath('b25_env')+" && "
+            except:
+                inst=u"b25_remoteがオンになっていますが、b25_envが設定されていないかコメントアウトされています。"
+                recdblist.addCommonlogEX(u"Error",u"b252tsmix(tv2ts.py)", "",inst)
+        exe = exe + "nice -n 17 " + configreader.getConfPath('b25')
+        doexe = exe + u' \"' + pin + u'\" \"' + pout + u'\"'
+        recdblist.printutf8(doexe)
+        recdblist.addCommandSelfLog(pin,doexe)
+        txt = unicode(commands.getoutput(doexe.encode('utf-8')),'utf-8')
+        recdblist.addLog(pin, doexe, u"b25ログ-コマンド")
+        recdblist.addLog(pin, txt, u"b25ログ-詳細")
+        recdblist.addCommandLogZip(pin, "b25", "b25", doexe, txt)
+        return txt
+def tsmix2ts(pin, pout, csch):#csch=0ならcsの処理をしない
+    tssplitterex=configreader.getConfPath("java")+" -jar "+configreader.getConfPath("jTsSplitter")
+    doexe =tssplitterex + " \""+ pin + "\" \""+ pout + "\" " + str(csch)
+    doexe = "nice -n 18 " + doexe
+    os.environ['LANG']="ja_JP.UTF-8"
+    txt = unicode(commands.getoutput(doexe.encode('utf-8')),'utf-8')
+    recdblist.addLog(pin, doexe, u"TsSplitログ-コマンド")
+    recdblist.addLog(pin, txt, u"TsSplitログ-詳細")
+    time.sleep(1)
+    if os.access(pout, os.F_OK) and os.path.getsize(pout)>10*1000*1000:
+        os.remove(pin)
+        
diff --git a/dist/trunk/rec10/xml2db_dom.py b/dist/trunk/rec10/xml2db_dom.py
new file mode 100755 (executable)
index 0000000..fd41840
--- /dev/null
@@ -0,0 +1,143 @@
+#!/usr/bin/python\r
+# coding: UTF-8\r
+# Rec10 TS Recording Tools\r
+# Copyright (C) 2009-2011 Yukikaze\r
+\r
+import xml.dom.minidom\r
+import datetime\r
+import re\r
+import traceback\r
+\r
+import zenhan\r
+import chdb\r
+import auto_rec\r
+import recdb\r
+import rec10d\r
+import n_gram\r
+import recdblist\r
+import epgdb\r
+import status\r
+def getText(elm):\r
+    nodelist = elm.childNodes\r
+    rc = ""\r
+    # 全てのノードに対して\r
+    for node in nodelist:\r
+        # テキストノードなら値を取得\r
+        if node.nodeType == node.TEXT_NODE:\r
+            rc = rc + node.data\r
+    return rc\r
+def getText_item(obj):\r
+    rc=""\r
+    for o in obj:\r
+        rc=rc+getText(o)\r
+    return rc\r
+def writeMultiTVDB(bctype,tvlists):\r
+    rec10d.rec10db.new_epg_timeline(bctype)\r
+    for channel,start,stop,title,desc,longdesc,category in tvlists:\r
+        rec10d.rec10db.add_epg_timeline(bctype, channel, start, stop, title, desc, longdesc, category)\r
+def writeMultiCHDB(chlists):\r
+    for chtxt,dn in chlists:\r
+        rec10d.rec10db.update_chname_by_chtxt_epg_ch(chtxt,dn)\r
+def writeMultiLogoDB(logolists):\r
+    #[type,sv,pngdata]\r
+    for type,sv,pngdata in logolists:\r
+        chtxt=chdb.searchCHFromCsch(sv)['chtxt']\r
+        if len(chtxt)>0:\r
+            rec10d.rec10db.change_logodata_epg_ch(chtxt,type,pngdata)\r
+def xml2db_dom(xmlpath, bctype):#bctypeは放送種別で'TE'(地デジ)BS,CSがある。地デジの場合は te数字 が入る\r
+    dtb=datetime.datetime.now()\r
+    dom=xml.dom.minidom.parse(file(xmlpath))\r
+    chlist=[]\r
+    tvlist=[]\r
+    bayes={}\r
+    rHisch=re.compile(u"『([^『]+)』(.+)\Z")##History CHのタイトル#01  exp:「#01説明」をタイトルに含める\r
+    for ch in dom.getElementsByTagName('channel'):\r
+        chtxtt=ch.getAttribute("id")\r
+        chname=ch.getElementsByTagName("display-name").item(0).childNodes[0].data\r
+        chlist.append([chtxtt,chname])\r
+    for tv in dom.getElementsByTagName('programme'):\r
+        channel=zenhan.toHankaku_ABC123(tv.getAttribute("channel"))\r
+        start=tv.getAttribute("start").replace(" +0900", "")\r
+        stop=tv.getAttribute("stop").replace(" +0900", "")\r
+        title=zenhan.toHankaku_ABC123(getText_item(tv.getElementsByTagName("title"))).replace(",", "_")\r
+        desc=zenhan.toHankaku_ABC123(getText_item(tv.getElementsByTagName("desc")))\r
+        longdesc=zenhan.toHankaku_ABC123(getText_item(tv.getElementsByTagName("longdesc")))\r
+        category=zenhan.toHankaku_ABC123(getText_item(tv.getElementsByTagName("category")))\r
+        title=addTitle_Subtitle(rHisch,1,title,desc)\r
+        tch=chdb.searchCHFromChtxt(channel)\r
+        if tch!=None:\r
+            if tch.get('bctype',"")==bctype and not tch['visible']==0:\r
+                bt=bayes.get(tch['chtxt'],["","",0])\r
+                bt2=[bt[0]+title+" ",bt[1]+desc+" "+longdesc+" ",bt[2]+1]\r
+                bayes[tch['chtxt']]=bt2\r
+                tvlist.append([channel,start,stop,title,desc,longdesc,category])\r
+                p=auto_rec.calcKey(tch['chtxt'], title,desc+" "+longdesc)\r
+                if p>2000:\r
+                    bttt=datetime.datetime.strptime(start,"%Y%m%d%H%M%S")\r
+                    bttt=bttt-datetime.timedelta(seconds=1200)\r
+                    bttime=bttt.strftime("%Y-%m-%d %H:%M:%S")\r
+                    ettt=datetime.datetime.strptime(stop,"%Y%m%d%H%M%S")\r
+                    ettt=ettt+datetime.timedelta(seconds=1200)\r
+                    ettime=ettt.strftime("%Y-%m-%d %H:%M:%S")\r
+                    chs=rec10d.rec10db.select_bytime_bychtxt_all_timeline(bttime,ettime,tch['chtxt'])\r
+                    p2=0\r
+                    if len(chs)>0:\r
+                        for ch in chs:\r
+                            p2t=n_gram.trigram(ch['title'],title)\r
+                            if p2t>p2:\r
+                                p2=p2t\r
+                    if p2<350:\r
+                        if status.getSettings_auto_bayes()==1:\r
+                            if p2<200:\r
+                                maxnum=0\r
+                                if len(ch['ch'])>2:\r
+                                    maxnum=epgdb.count_schedule_timeline(bttime, ettime)[1]\r
+                                    maxnum=int(configreader.getConfEnv("bscs_max"))-maxnum\r
+                                else:\r
+                                    maxnum=epgdb.count_schedule_timeline(bttime, ettime)[0]\r
+                                    maxnum=int(configreader.getConfEnv("te_max"))-maxnum\r
+                                if maxnum>0:\r
+                                    topt=status.getSettings_auto_opt()\r
+                                    recdb.reserveReckey(recdblist.REC_RESERVE,title,tch['chtxt'], bttime, ettime,topt)\r
+                        else:\r
+                            recdb.addAutoBayesKeyword(tch['chtxt'],title,start,stop,p)\r
+    dom.unlink()\r
+    if len(chlist) > 0:\r
+        writeMultiCHDB(chlist)\r
+        chlist = []\r
+        if len(tvlist) > 0:\r
+            writeMultiTVDB(bctype,tvlist)\r
+        tvlist = []\r
+        for ct,list in bayes.items():\r
+            auto_rec.updateRecall(ct,list[0],list[1],list[2])\r
+            auto_rec.updateRecall("ALL",list[0],list[1],list[2])\r
+    dtb=datetime.datetime.now()-dtb\r
+    recdblist.printutf8(bctype + u" epg取り出し終了")\r
+    recdblist.printutf8(str(dtb.days * 24 * 60 * 60 + dtb.seconds)+u"seconds taken for updating bayes-auto DB .")\r
+def xml2db_dom_logo(xmlpath, bctype):#bctypeは放送種別で'TE'(地デジ)BS,CSがある。地デジの場合は te数字 が入る\r
+    dtb=datetime.datetime.now()\r
+    dom=xml.dom.minidom.parse(file(xmlpath))\r
+    logolist=[]\r
+    for logo in dom.getElementsByTagName('logo'):\r
+        type=int(logo.getAttribute("type"))\r
+        sv=logo.getAttribute("sv")\r
+        pngdata=logo.childNodes[0].data\r
+        logolist.append([type,sv,pngdata])\r
+    dom.unlink()\r
+    if len(logolist) > 0:\r
+        writeMultiLogoDB(logolist)\r
+    dtb=datetime.datetime.now()-dtb\r
+    recdblist.printutf8(bctype + u" epg取り出し終了")\r
+    recdblist.printutf8(str(dtb.days * 24 * 60 * 60 + dtb.seconds)+u"seconds taken for updating logo DB .")\r
+def addTitle_Subtitle(recompiled,num,title,exp):\r
+    try:\r
+        tST=recompiled.match(exp)\r
+        newtitle=u""\r
+        if tST:\r
+            newtitle=title+u"『"+tST.group(num)+u"』"\r
+        else:\r
+            newtitle=title\r
+    except Exception, inst:\r
+        recdblist.addCommonlogEX("Error", "addTitle_Subtitle(xml2db_dob.py)", str(type(inst)),str(inst)+traceback.format_exc(),log_level=200)\r
+        newtitle=title\r
+    return newtitle\r
diff --git a/dist/trunk/rec10/zenhan.py b/dist/trunk/rec10/zenhan.py
new file mode 100755 (executable)
index 0000000..ff930dd
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+
+import recdblist
+global z_ascii
+global h_ascii
+global z_number
+global h_number
+z_ascii = u"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !”#$%&’()*+,−./:;<=>?@[¥]^_‘{|}〜 〜"
+h_ascii = u"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ -"
+z_ascii_sp = unichr(0x2212)+unichr(0xff0e)
+h_ascii_sp = unichr(0x002d)+unichr(0x002e)
+z_number = u"0123456789"
+h_number = u"0123456789"
+z_alphabet = u"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #"
+h_alphabet = u"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #"
+def toHankaku(str):
+    retstr = u""
+    for s in str:
+        i = z_ascii.find(s)
+        if (i != -1):
+            s = h_ascii[i]
+        i = z_ascii_sp.find(s)
+        if (i != -1):
+            s = h_ascii_sp[i]
+        i = z_number.find(s)
+        if (i != -1):
+            s = h_number[i]
+        retstr = retstr + s
+    return retstr
+def toHankaku_ABC123(str):
+    retstr = u""
+    for s in str:
+        i = z_alphabet.find(s)
+        if (i != -1):
+            s = h_alphabet[i]
+        i = z_ascii_sp.find(s)
+        if (i != -1):
+            s = h_ascii_sp[i]
+        i = z_number.find(s)
+        if (i != -1):
+            s = h_number[i]
+        retstr = retstr + s
+    return retstr
+def checkCharacterType(character):
+    """
+    return code is 1:Alphabet 2:Hiragana 3:Katakana 4:Kanji
+    """
+    chcode=ord(character)
+    if chcode>=0x0000 and chcode<=0x007F:
+        return 1
+    elif chcode>=0x3040 and chcode<=0x309F:
+        return 2
+    elif chcode>=0x30A0 and chcode<=0x30FF:
+        return 3
+    elif chcode>=0x4E00 and chcode<=0x9FFF:
+        return 4
diff --git a/dist/trunk/rec10/zip.py b/dist/trunk/rec10/zip.py
new file mode 100755 (executable)
index 0000000..7dc9ab5
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+# coding: UTF-8
+# Rec10 TS Recording Tools
+# Copyright (C) 2009-2011 Yukikaze
+
+import os
+import os.path
+import zipfile
+
+def addFile2FileZip(addfile,basefile):
+    th=0
+
+    if os.path.exists(basefile):
+        th=zipfile.ZipFile(basefile,'a',zipfile.ZIP_DEFLATED)
+    else:
+        th=zipfile.ZipFile(basefile,'w',zipfile.ZIP_DEFLATED)
+    if os.path.exists(addfile):
+        th.write(addfile,os.path.basename(addfile))
+    th.close()
diff --git a/dist/trunk/rec10Manual0.9.9.pdf b/dist/trunk/rec10Manual0.9.9.pdf
new file mode 100755 (executable)
index 0000000..3e503ed
Binary files /dev/null and b/dist/trunk/rec10Manual0.9.9.pdf differ
diff --git a/dist/trunk/tstools/BonTsDemux/BonTsDemux.exe b/dist/trunk/tstools/BonTsDemux/BonTsDemux.exe
new file mode 100755 (executable)
index 0000000..b1ae355
Binary files /dev/null and b/dist/trunk/tstools/BonTsDemux/BonTsDemux.exe differ
diff --git a/dist/trunk/tstools/BonTsDemux/BonTsDemux.txt b/dist/trunk/tstools/BonTsDemux/BonTsDemux.txt
new file mode 100755 (executable)
index 0000000..ea8cf28
--- /dev/null
@@ -0,0 +1,458 @@
+BonTsDemux mod 10k7 + nogui + es + fix03 rec10\89ü\95Ï\94Å\r
+\81\9b\95Ï\8dX\93_\81E\97\9a\97ð\r
+\r
+2010/10/24\r
\81E10/22\94Å\82ð\83x\81[\83X\82Éwine\82Å\82à\93®\82­\82æ\82¤\82ÉVS2005\82Å\83r\83\8b\83h\81A\83R\83}\83\93\83h\83\89\83C\83\93\94Å\82Ì\82Ý\82Ì\8fo\97Í\r
+         \81@\82ð\82¨\82±\82È\82¢\82Ü\82µ\82½\81B\93¯\8d«\82³\82ê\82Ä\82¢\82½ffmpeg\82Írec10\82©\82ç\82Í\8eg\82í\82È\82¢\82½\82ß\93¯\8d«\82µ\r
+         \81@\82Ä\82¢\82Ü\82¹\82ñ\81BBonTsDemuxC\82ðBonTsDemux\82Æ\83\8a\83l\81[\83\80\82µ\82Ü\82µ\82½(\8cÝ\8a·\90«\88Û\8e\9d)\r
+         \81@DLL\82È\82Ç\83G\83\89\81[\82Ì\82à\82Æ\82Æ\82È\82è\82»\82¤\82È\82à\82Ì\82ð\93¯\8d«\82µ\82Ü\82µ\82½\81B\r
+         \81@by gn64_jp(rec10)\r
+2010/10/22\81@\r
\81EFFmpeg\82ð0.6.1\82É\82µ\82Ü\82µ\82½\81B\r
+     \81¦\92\8d\88Ó\81¦\r
+         \81E\93¯\8d«\82µ\82Ä\82¢\82éFFmpeg\82Ílibfaac\82ª\8eg\82¦\82Ü\82¹\82ñ\81B\82©\82í\82è\82É\93à\91 aac\83G\83\93\83R\81[\83_\r
+         \81@\82ª\8eg\97p\82Å\82«\82Ü\82·\82ª\82 \82Ü\82è\8e¿\82Í\82æ\82­\82È\82¢\82æ\82¤\82Å\82·\81Blibfaac\82ð\8eg\97p\82³\82ê\82½\82¢\r
+         \81@\95û\82Í\8e©\95ª\82ÅFFmpeg\82ð\83r\83\8b\83h\82µ\82È\82¯\82ê\82Î\82¢\82¯\82È\82¢\82æ\82¤\82Å\82·\81B\r
+         \81Ecap_sts_sea.ini\82Ì\93à\97e\82ð\93¯\8d«FFmpeg \97p\82É\8fC\90³\82µ\82Ä\82¢\82Ü\82·\81B\r
+         \81@\89æ\8e¿\82Í\82½\82Ô\82ñ\93¯\93\99\82Å\82·\82ª\81AFFmpeg\82Ì\83r\83\8b\83h\82ª\82¤\82Ü\82­\8dÅ\93K\89»\82Å\82«\82Ä\82È\82¢\82©\82ç\r
+         \81@\82©\83G\83\93\83R\81[\83h\8e\9e\8aÔ\82ª\92·\82­\82È\82Á\82Ä\82Ü\82·\81B\r
+         \81E\82¨\82Ü\82¯\82Å\81Acap_sts_sea.ini\82É\82Ü\82Æ\82ß\83T\83C\83g\82Ì\93à\97e\81AH264\82ÌHigh Profile\82Å\r
+         \81@\83G\83\93\83R\81[\83h\82·\82éX264_HQ,X264_HQ_SMALL\81A\82Ü\82½WEBM\82ð\92Ç\89Á\82µ\82Ü\82µ\82½\81B\r
+         \81Effpreset\83t\83@\83C\83\8b\82ð\93¯\8d«\82µ\82Ü\82µ\82½\81B\r
\81E\83R\83}\83\93\83h\83\89\83C\83\93\83I\83v\83V\83\87\83\93\82É -help\82ð\92Ç\89Á\82µ\82Ü\82µ\82½\81B\r
\81ECUI\90ê\97p BonTsDemuxC.exe\82ð\97p\88Ó\82µ\82Ü\82µ\82½\81B\88ø\90\94\82ÍGUI\82Æ\93¯\82\82Å\82·\81B\r
\81@CUI\94Å\82Í\83G\83\89\81[\82©\82Ç\82¤\82©\82ð\83\8a\83^\81[\83\93\83R\81[\83h\82Å\94»\92f\82Å\82«\82Ü\82·\81B1\81F\83G\83\89\81[,0:\90³\8fí\8fI\97¹\r
\81EGUI\82Ì\90i\92»\8fó\8bµ\95\\8e¦\82ð\82í\82©\82è\82â\82·\82­\8fC\90³\82µ\82Ü\82µ\82½\81B\r
\81EFFmpeg\82ð\8dÅ\8f¬\89»\82µ\82Ä\8bN\93®\82·\82é\82æ\82¤\82É\95Ï\8dX\82µ\82Ü\82µ\82½\81B\r
\81E\83J\83\93\83}\82 \82è\82Ì\83t\83@\83C\83\8b\82ð\90³\82µ\82­\8f\88\97\9d\82Å\82«\82é\82æ\82¤\82É\82µ\82Ü\82µ\82½\81B\r
+       \r
+       \81¦1 \8d¡\89ñ\82ÍVisual Studio 2005 \82Å\83r\83\8b\83h\82µ\82Ä\82¢\82Ü\82·\81B\r
+       \81¦2 FFmpeg\82ÍUbuntu 9,04\82Å\83r\83\8b\83h\82µ\82Ä\82¢\82Ü\82·\81B\r
+       \r
+2010/05/20\r
+\81E\89æ\96Ê\90Ý\92è\82ðBonTsDemux.ini\82É\95Û\91\81A\95\9c\8bA\82·\82é\82æ\82¤\82É\8fC\90³\r
+  \81¦\83R\83}\83\93\83h\83\89\83C\83\93\82©\82ç-nogui,-start,-quit\82ª\8ew\92è\82³\82ê\82½\8fê\8d\87\r
+    \90Ý\92è\82Ì\95Û\91\81A\95\9c\8bA\82Í\8ds\82¢\82Ü\82¹\82ñ\81B\r
+    \r
+    \r
+2010/05/09 \r
+\81E\83t\83@\83C\83\8b\82Ì\8dÅ\8cã\82É\83S\83~\82ª\82Â\82©\82È\82¢\82æ\82¤\82É\8fC\90³\81B\r
+\81E\83t\83@\83C\83\8b\82Ì\8dÅ\8cã\82ª\8c\87\97\8e\82·\82é\82±\82Æ\82ª\82 \82Á\82½\82Ì\82ð\8fC\90³\81B\r
+\r
+\81¦\83r\83\8b\83h\8aÂ\8b«\82É\95Ï\8dX\82Í\82 \82è\82Ü\82¹\82ñ\81B\r
+\r
+----------------------------------------------------------------------------\r
+BonTsDemux mod 10k7 + nogui + es (modified by pika)\r
+\r
+LxbEvo.FpE\8e\81\81Akt\8e\81\81Abm\8e\81\81Asaba\8e\81\81Amoke\8e\81\82É\82æ\82é \r
+BonTsDemux mod 10k7 + nogui (modified by moke) \82ð\89ü\91¢\82µ\82½\82à\82Ì\81B\r
+\r
+\81\9b\95Ï\8dX\93_\r
+\r
+\81Ebm\82³\82ñ\82Ì\92Ç\89Á\82µ\82½\83o\83b\83N\83O\83\89\83E\83\93\83h\83\82\81[\83h\82Ì\82½\82ß\82É\r
+\81@\83R\83}\83\93\83h\83\89\83C\83\93\88ø\90\94\81@-bg\81i-background\81j\81@\82ð\92Ç\89Á\81i\92Ê\8fí\82ÌGUI\8f\88\97\9d\82Å\82Ì\82Ý\97L\8cø\81j\r
+\r
+\81E\83T\81[\83r\83X\8ew\92è\82ð\8fÈ\97ª\82µ\82ÄES\94Ô\8d\86\82ð\8ew\92è\82µ\82½\8e\9e\81A\r
+\81@\90æ\93ª\82Ì\83T\81[\83r\83X\82ª\8ew\92è\82³\82ê\82½\82à\82Ì\82Æ\82µ\82Ä\8f\88\97\9d\82ð\8ds\82¤\82æ\82¤\82É\82µ\82½\r
+\r
+\81E\95¡\90\94\83v\83\8d\83O\83\89\83\80\81i\83T\81[\83r\83X\81j\81\95\95¡\90\94\89¹\90º\82ÌTS\82Ì\8fê\8d\87\81A\r
+\81@\82Q\82Â\96Ú\88È\8d~\82Ì\83v\83\8d\83O\83\89\83\80\82Ì\82Q\82Â\96Ú\88È\8d~\82Ì\89¹\90º\82ª\82¤\82Ü\82­\8eæ\82è\8fo\82¹\82Ä\82¢\82È\82©\82Á\82½\82Ì\82ð\r
+\81@\8eæ\82ê\82é\82æ\82¤\82É\82µ\82½\81B\r
+\r
+\81¦\92\8d\88Ó\r
+\81@\93®\8dì\8am\94F\82Í\81AXP32bitProfessionalSP3\8fã\82Å\82µ\82©\8ds\82Á\82Ä\82¢\82Ü\82¹\82ñ\81B\r
+\81@\83e\83X\83g\83\\81[\83X\82Í\92n\83f\83W\82Ì\82Ý\81B\r
+\r
+\81\9b\83r\83\8b\83h\82É\95K\97v\82È\8aÂ\8b«/\83\89\83C\83u\83\89\83\8a\r
+\81EMicrosoft Visual Studio 2008 \88È\8fã\r
+\81EFAAD 2.7\r
+  http://www.audiocoding.com/downloads.html\r
+  \81i\83R\83\93\83p\83C\83\8b\82µ\82Ä\82Å\82«\82½\83\8a\83\8a\81[\83X\94Å libfaad.lib \82ð BonTsDemux.vcproj \82È\82Ç\82Æ\r
+    \93¯\82\8aK\91w\82É\92u\82­\82±\82Æ\81B\82Ü\82½\81A\83f\83o\83b\83O\94Å\82Ì\83\89\83C\83u\83\89\83\8a\82Í libfaadd.lib \82É\83\8a\83l\81[\83\80\r
+    \82µ\82Ä\93¯\82\8aK\91w\82É\92u\82­\82±\82Æ\81B\81j\r
+\81¦ \82¨\82»\82ç\82­\82Í\8f­\81X\82Ì\8fC\90³\82ÅVisual Studio 2003/2005\82Å\82à\83r\83\8b\83h\89Â\94\\82¾\82Æ\8ev\82¤\81B\r
+\r
+\81\9b\97\9a\97ð\r
+2010/03/04  (mod 10k7 + nogui) + es\r
+\81E-bg\83R\83}\83\93\83h\83\89\83C\83\93\88ø\90\94\92Ç\89Á\r
+\81E\83T\81[\83r\83X\8fÈ\97ªES\8ew\92è\91Î\89\9e\r
+\81EES\8eæ\82è\8fo\82µ\98R\82ê\8fC\90³\r
+\r
+----------------------------------------------------------------------------\r
+BonTsDemux mod 10k7 + nogui (modified by moke)\r
+\r
+LxbEvo.FpE\8e\81\81Akt\8e\81\81Abm\8e\81\81Asaba\8e\81\82É\82æ\82é BonTsDemux mod 10k7 (modified by saba) \82ð\89ü\91¢\82µ\82½\82à\82Ì\81B\r
+\r
+\81\9b\95Ï\8dX\93_\r
+\r
+\81E-nogui\83R\83}\83\93\83h\82Ì\92Ç\89Á\r
+\81@\8ew\92è\82µ\82½\8fê\8d\87\81AGUI\82ð\95\\8e¦\82¹\82¸\83R\83}\83\93\83h\83v\83\8d\83\93\83v\83g\8fã\82Ì\82Ý\82Å\8f\88\97\9d\82ð\8ds\82¤\81B\r
+\81@Wine\82Å\8eÀ\8ds\82·\82é\8fê\8d\87GUI\82ª\8e×\96\82\82É\82È\82è\8eÀ\8ds\82Å\82«\82È\82¢\8fê\8d\87\82ª\82 \82é\82½\82ß\92Ç\89Á\81B\r
+\r
+\81@\82±\82Ì\83R\83}\83\93\83h\82ð\8ew\92è\82µ\82½\8fê\8d\87-start\82Æ-quit\83R\83}\83\93\83h\82Í\96³\8e\8b\82·\82é\81i\8ew\92è\82µ\82È\82­\82Ä\82à\8e©\93®\8aJ\8en\81A\8e©\93®\8fI\97¹\82·\82é\81j\r
+\r
+\81\9b\83r\83\8b\83h\82É\95K\97v\82È\8aÂ\8b«/\83\89\83C\83u\83\89\83\8a\r
+\81EMicrosoft Visual Studio 2008 \88È\8fã\r
+\81EFAAD 2.7\r
+  http://www.audiocoding.com/downloads.html\r
+  \81i\83R\83\93\83p\83C\83\8b\82µ\82Ä\82Å\82«\82½\83\8a\83\8a\81[\83X\94Å libfaad.lib \82ð BonTsDemux.vcproj \82È\82Ç\82Æ\r
+    \93¯\82\8aK\91w\82É\92u\82­\82±\82Æ\81B\82Ü\82½\81A\83f\83o\83b\83O\94Å\82Ì\83\89\83C\83u\83\89\83\8a\82Í libfaadd.lib \82É\83\8a\83l\81[\83\80\r
+    \82µ\82Ä\93¯\82\8aK\91w\82É\92u\82­\82±\82Æ\81B\81j\r
+\81¦ \82¨\82»\82ç\82­\82Í\8f­\81X\82Ì\8fC\90³\82ÅVisual Studio 2003/2005\82Å\82à\83r\83\8b\83h\89Â\94\\82¾\82Æ\8ev\82¤\81B\r
+\r
+\81\9b\97\9a\97ð\r
+2010/03/02  mod 10k7 + nogui .1\r
+\81E-nogui\8ew\92è\8e\9e\82É-o\83I\83v\83V\83\87\83\93\82ª\8cø\82©\82È\82©\82Á\82½\83o\83O\82ð\8fC\90³\r
+\r
+2010/02/21  mod 10k7 + nogui\r
+\81E-nogui\83R\83}\83\93\83h\82Ì\92Ç\89Á\r
+\r
+----------------------------------------------------------------------------\r
+\r
+BonTsDemux mod 10k7 (modified by saba)\r
+\r
+LxbEvo.FpE\8e\81\81Akt\8e\81\81Abm\8e\81\82É\82æ\82é BonTsDemux mod 10k6 + BM (modified by bm) \82ð\89ü\91¢\82µ\82½\82à\82Ì\81B\r
+\r
+\81\9b\95Ï\8dX\93_\r
+\r
+BonTsDemux \82ð\91½\8fd\8bN\93®\82µ\82Ä\82à\93®\8dì\82·\82é\82æ\82¤\82É\82µ\82½\81B\r
+\8f]\97\88\82Í ffmpeg \82Æ\92Ê\90M\82·\82é TCP \83|\81[\83g\94Ô\8d\86\82ª 1234 \8cÅ\92è\82¾\82Á\82½\82Ì\82Å\81A\91½\8fd\8bN\93®\82·\82é\82Æ\r
+\82¨\82©\82µ\82­\82È\82Á\82Ä\82¢\82½\81B\r
+\82±\82ê\82ð\81A\8bó\82¢\82Ä\82¢\82é\83|\81[\83g\82ð\93®\93I\82É\91I\91ð\82·\82é\82æ\82¤\82É\95Ï\8dX\82µ\82½\82Ì\82Å\81A\91½\8fd\8bN\93®\82µ\82Ä\82à\90³\82µ\82­\93®\8dì\82·\82é\81B\r
+\r
+\81\9b\83r\83\8b\83h\82É\95K\97v\82È\8aÂ\8b«/\83\89\83C\83u\83\89\83\8a\r
+\81EMicrosoft Visual Studio 2008 \88È\8fã\r
+\81EFAAD 2.7\r
+  http://www.audiocoding.com/downloads.html\r
+  \81i\83R\83\93\83p\83C\83\8b\82µ\82Ä\82Å\82«\82½\83\8a\83\8a\81[\83X\94Å libfaad.lib \82ð BonTsDemux.vcproj \82È\82Ç\82Æ\r
+    \93¯\82\8aK\91w\82É\92u\82­\82±\82Æ\81B\82Ü\82½\81A\83f\83o\83b\83O\94Å\82Ì\83\89\83C\83u\83\89\83\8a\82Í libfaadd.lib \82É\83\8a\83l\81[\83\80\r
+    \82µ\82Ä\93¯\82\8aK\91w\82É\92u\82­\82±\82Æ\81B\81j\r
+\81¦ \82¨\82»\82ç\82­\82Í\8f­\81X\82Ì\8fC\90³\82ÅVisual Studio 2003/2005\82Å\82à\83r\83\8b\83h\89Â\94\\82¾\82Æ\8ev\82¤\81B\r
+\r
+\81\9b\97\9a\97ð\r
+2009/12/20  mod 10k7\r
+\81E\91½\8fd\8bN\93®\82É\91Î\89\9e\81B\r
+\r
+----------------------------------------------------------------------------\r
+\r
+BonTsDemux mod 10k6 + BM (modified by bm)\r
+\r
+LxbEvo.FpE\8e\81\81Akt\8e\81\82É\82æ\82é BonTsDemux mod 10k6 \82ð\89ü\91¢\82µ\82½\82à\82Ì\81B\r
+\r
+\81\9b\95Ï\8dX\93_\r
+\81Emod 10k6 \82É\83o\83b\83N\83O\83\89\83E\83\93\83h\83\82\81[\83h\82ð\92Ç\89Á\81B\r
+\81@\82±\82Ì\83`\83F\83b\83N\83{\83b\83N\83X\82ð\83I\83\93\82É\82µ\82Ä\95Ï\8a·\8aJ\8en\82µ\82½\8fê\8d\87\81A\r
+\81@\8bï\91Ì\93I\82É\82Í\81AWindows Vista \82Å\93±\93ü\82³\82ê\82½ Low-priority I/O \82ð\8eg\97p\82·\82é\81B\r
+\81@\81iWindows XP \82¾\82Á\82½\82ç\91ã\82í\82è\82Æ\82µ\82Ä\83v\83\8d\83Z\83X\97D\90æ\93x\82ð\81u\92á\81v\82É\82·\82é\81j\r
+\81E\83r\83\8b\83h\82ÉVisual C++ 2008 SP1\82ð\8eg\97p\81B\r
+\81@\93®\93I\83\8a\83\93\83N\82É\82µ\82Ä\82¢\82é\82½\82ß\81A\83\89\83\93\83^\83C\83\80\83\89\83C\83u\83\89\83\8a\82ª\95K\97v\81B\r
+http://www.microsoft.com/Downloads/details.aspx?displaylang=ja&FamilyID=a5c84275-3b97-4ab7-a40d-3802b2af5fc2\r
+\r
+\81\9b\83r\83\8b\83h\82É\95K\97v\82È\8aÂ\8b«/\83\89\83C\83u\83\89\83\8a\r
+\81EMicrosoft Visual Studio 2008 \88È\8fã\r
+\81EFAAD 2.6.1\r
+  http://www.audiocoding.com/downloads.html\r
+  \81i\83R\83\93\83p\83C\83\8b\82µ\82Ä\82Å\82«\82½\83\8a\83\8a\81[\83X\94Å libfaad.lib \82ð BonTsDemux.vcproj \82È\82Ç\82Æ\r
+    \93¯\82\8aK\91w\82É\92u\82­\82±\82Æ\81B\82Ü\82½\81A\83f\83o\83b\83O\94Å\82Ì\83\89\83C\83u\83\89\83\8a\82Í libfaadd.lib \82É\83\8a\83l\81[\83\80\r
+    \82µ\82Ä\93¯\82\8aK\91w\82É\92u\82­\82±\82Æ\81B\81j\r
+\81¦ \82¨\82»\82ç\82­\82Í\8f­\81X\82Ì\8fC\90³\82ÅVisual Studio 2003/2005\82Å\82à\83r\83\8b\83h\89Â\94\\82¾\82Æ\8ev\82¤\81B\r
+\r
+\81\9b\97\9a\97ð\r
+2009/07/07  mod 10k6 + BM\r
+\81E\83o\83b\83N\83O\83\89\83E\83\93\83h\83\82\81[\83h\82ð\92Ç\89Á\r
+\r
+----------------------------------------------------------------------------\r
+BonTsDemux mod 10k6 readme\r
+----------------------------------------------------------------------------\r
+\r
+BonTsDemux mod 10k6 (modified by bm)\r
+\r
+LxbEvo.FpE\8e\81\82É\82æ\82é BonTsDemux mod 10 \82ð\89ü\91¢\82µ\82½\82à\82Ì\81B\r
+\r
+AAC \82Ì Demux \82ð\83o\83b\83`\8f\88\97\9d\82Å\82«\82é\83\\83t\83g\82ª\8c©\93\96\82½\82ç\82È\82©\82Á\82½\82½\82ß\82É\8dì\90¬\81B\r
+\r
+\81\9b\95Ï\8dX\93_\r
+\81EAAC \82Ì Demux \8b@\94\\82ð\95\9c\8a\88\81B\r
+  AAC Demux\8e\9e\82É\82Í\81A\83t\83@\83C\83\8b\96¼\82É\92x\89\84\8e\9e\8aÔ\82ð\93ü\82ê\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+  \81iDGIndex \82È\82Ç\82Æ\93¯\82\8c`\8e®\81B\81j\r
+  \81¦WAV Demux\8e\9e\82Í\81A\92x\89\84\8e\9e\8aÔ\82Í\95â\90³\8dÏ\82Ý\81B\r
+\r
+\81E\89¹\90º\82Ì\92x\89\84\8e\9e\8aÔ\82ð\95â\90³\82Å\82«\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+  \83R\83}\83\93\83h\83\89\83C\83\93\82Å\82Í -delay nnn \82Å\8ew\92è\89Â\94\\81B\81innn \82Í\81Ams\92P\88Ê\82Ì\90®\90\94\81j\r
+\r
+\81ERF64\83T\83|\81[\83g\81AVideo Frame\95â\8a®\82Ì\90Ý\92è\82ð\83t\83@\83C\83\8b\82²\82Æ\82É\8bL\89¯\82·\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+  D&D \82Å\83t\83@\83C\83\8b\82ð\93o\98^\82·\82é\8fê\8d\87\82Í\81A\91¼\82Ì\83I\83v\83V\83\87\83\93\82Æ\93¯\97l\82É\81A\90æ\82É\8aó\96]\82Ì\90Ý\92è\82ð\r
+  \91I\82ñ\82Å\82¨\82¢\82½\8fó\91Ô\82Å D&D \82·\82é\82±\82Æ\81B\r
+\r
+\81E\83X\83N\83\89\83\93\83u\83\8b\89ð\8f\9c\82ð\8ds\82í\82È\82¢\83I\83v\83V\83\87\83\93\82ð\92Ç\89Á\81B\r
+  \83R\83}\83\93\83h\83\89\83C\83\93\82Å\82Í -nd \82Å\8ew\92è\89Â\94\\81B\r
+  \81i\83X\83N\83\89\83\93\83u\83\8b\89ð\8f\9c\8dÏ\82Ý\83t\83@\83C\83\8b\82Ì\8f\88\97\9d\8d\82\91¬\89»\97p\81j\r
+\r
+\81E\91\80\8dì\90«\8cü\8fã\82Ì\82½\82ß\81A\88ê\95\94\82Ì\83{\83^\83\93\93\99\82É\83A\83N\83Z\83X\83L\81[\82ð\92Ç\89Á\81B\r
+\r
+\81E\93ü\97ÍTS\83t\83@\83C\83\8b\82ð\95¡\90\94\91I\91ð\82Å\82«\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+\r
+\81E\83f\83t\83H\83\8b\83g\82Ì\8fo\97Í\83t\83H\83\8b\83_\82ð\8ew\92è\82Å\82«\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+  \83f\83t\83H\83\8b\83g\8fo\97Í\83t\83H\83\8b\83_\82Ì\97\93\82ª\8bó\82Å\82È\82¯\82ê\82Î\81ATS\83t\83@\83C\83\8b\82ð\91I\91ð\82µ\82½\82Æ\82«\82âD&D\82µ\82½\r
+  \82Æ\82«\82É\81A\8fo\97Í\83t\83H\83\8b\83_\82ª\8ew\92è\82µ\82½\83t\83H\83\8b\83_\82É\82È\82é\81B\r
+  \8bó\82Å\82 \82ê\82Î\81A\8d¡\82Ü\82Å\92Ê\82èTS\83t\83@\83C\83\8b\82ª\82 \82é\83t\83H\83\8b\83_\82ª\8fo\97Í\83t\83H\83\8b\83_\82Æ\82È\82é\81B\r
+\r
+\81E\82»\82Ì\91¼\82Ì\8d×\82©\82¢\95Ï\8dX\82Í\89º\8bL\82Ì\97\9a\97ð\82ð\8eQ\8fÆ\82Ì\82±\82Æ\81B\r
+\r
+\r
+\81\9b\83r\83\8b\83h\82É\95K\97v\82È\8aÂ\8b«/\83\89\83C\83u\83\89\83\8a\r
+\81EMicrosoft Visual Studio 2003 \88È\8fã\r
+\81EFAAD 2.6.1\r
+  http://www.audiocoding.com/downloads.html\r
+  \81i\83R\83\93\83p\83C\83\8b\82µ\82Ä\82Å\82«\82½\83\8a\83\8a\81[\83X\94Å libfaad.lib \82ð BonTsDemux.vcproj \82È\82Ç\82Æ\r
+    \93¯\82\8aK\91w\82É\92u\82­\82±\82Æ\81B\82Ü\82½\81A\83f\83o\83b\83O\94Å\82Ì\83\89\83C\83u\83\89\83\8a\82Í libfaadd.lib \82É\83\8a\83l\81[\83\80\r
+    \82µ\82Ä\93¯\82\8aK\91w\82É\92u\82­\82±\82Æ\81B\81j\r
+\r
+\81\9b\97\9a\97ð\r
+2009/04/29  mod 10k6\r
+\81Effmpeg\8bN\93®\8e\9e\82É\83n\83\93\83h\83\8b\83\8a\81[\83N\82µ\82Ä\82¢\82½\82Ì\82ð\8fC\90³\81B\r
+\81Effmpeg\8bN\93®\8e\9e\82Ì\8dì\8bÆ\83o\83b\83t\83@\83T\83C\83Y\8fC\90³\81B\81iMAX_PATH\82Ì\92l\82Í256\82Å\82Í\82È\82¢\81B\81j\r
+\81Effmpeg\8eg\97p\8e\9e\82É\83o\83b\83t\83@\83I\81[\83o\81[\83\89\83\93\82Å\97\8e\82¿\82é\8fê\8d\87\82ª\82 \82Á\82½\82Ì\82ð\8fC\90³\81B\r
+  MFC\82ð\83_\83C\83i\83~\83b\83N\83\8a\83\93\83N\82µ\82Ä\82¢\82é\82Æ\82«\82Í\94­\8c»\82µ\82Ä\82¢\82È\82©\82Á\82½\96Í\97l\81B(HttpSend.cpp)\r
+\81E\83X\83\8c\83b\83h\82Ì\8bN\93®\82É _beginthread() \82Í\8eg\82í\82È\82¢\82æ\82¤\82É\8fC\90³\81B\r
+\81EPSP\97p\82Ì\90Ý\92è\82ª\8aÔ\88á\82Á\82Ä\82¢\82½\82ç\82µ\82¢\82Ì\82Å\8fC\90³\81B\81i\93®\8dì\96¢\8am\94F\81j\r
+\81E\93ü\97ÍTS\83t\83@\83C\83\8b\82ð\95¡\90\94\91I\91ð\82Å\82«\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+\81E\83f\83t\83H\83\8b\83g\82Ì\8fo\97Í\83t\83H\83\8b\83_\82ð\8ew\92è\82Å\82«\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+\81i\81EWindows Driver Kit\82ð\8eg\82¤\82±\82Æ\82Å\81AVC++ 6.0\83\89\83\93\83^\83C\83\80\82Ì\82Ý\82Å\93®\8dì\82·\82é\8eÀ\8ds\r
+  \83t\83@\83C\83\8b\82ð\8dì\82ë\82¤\82Æ\82µ\82½\82ª\81ASSE2\82ð\8eg\82Á\82Ä\82¢\82é\8aÖ\8cW\82ÅVista\82Å\82µ\82©\93®\8dì\82µ\82È\82¢\r
+  \82à\82Ì\82ª\82Å\82«\82½\82½\82ß\92f\94O\81B\83r\83\8b\83h\97p\82Ì\90Ý\92è\83t\83@\83C\83\8b\82Í\93¯\8d«\81B\81j\r
+\r
+2009/01/10  mod 10k5\r
+\81E\91\80\8dì\90«\8cü\8fã\82Ì\82½\82ß\81A\88ê\95\94\82Ì\83{\83^\83\93\93\99\82É\83A\83N\83Z\83X\83L\81[\82ð\92Ç\89Á\81B\r
+\81EMFC\82ð\83X\83^\83e\83B\83b\83N\83\8a\83\93\83N\82·\82é\82æ\82¤\82É\95Ï\8dX\81B\81i\83\89\83\93\83^\83C\83\80\83\89\83C\83u\83\89\83\8a\82Í\95s\97v\82É\81B\81j\r
+\r
+2008/09/13  mod 10k4\r
+\81E\83X\83N\83\89\83\93\83u\83\8b\89ð\8f\9c\82ð\8ds\82í\82È\82¢\83I\83v\83V\83\87\83\93\82ð\92Ç\89Á\81B\r
+\81E\90Ý\92è\82ð\95Ï\8dX\82µ\82Ä\82¢\82È\82¢\82É\82à\8aÖ\82í\82ç\82¸\81A\95Ï\8a·\8aJ\8en\8e\9e\82É\83o\83b\83`\83\8a\83X\83g\82É\92Ç\89Á\93o\98^\82³\82ê\82é\r
+  \8fê\8d\87\82ª\82 \82Á\82½\82Ì\82ð\8fC\90³\81B\r
+\r
+2008/09/10  mod 10k3\r
+\81E\83\89\83\93\83^\83C\83\80\83\89\83C\83u\83\89\83\8a\82ª\95s\91«\82µ\82Ä\82¢\82½\82Ì\82Å\92Ç\89Á\81B\81i\92\86\90g\82Ì\95Ï\8dX\82Í\96³\82µ\81B\81j\r
+\r
+2008/09/07  mod 10k3\r
+\81Emod 10k2 \82Å\81A\89¹\90º\82Ì\92x\89\84\8e\9e\8aÔ\82Ì\95â\90³\82ª\8cø\82¢\82Ä\82¢\82È\82©\82Á\82½\82Ì\82ð\8fC\90³\81B\r
+  \82È\82¨\81A\95â\90³\92l\82É\82 \82Ü\82è\91å\82«\82È\92l\81i\90\94\95b\88È\8fã\81H\81j\82ð\93ü\82ê\82é\82Æ\93®\8dì\82ª\82¨\82©\82µ\82­\82È\82é\82©\82à\r
+  \92m\82ê\82È\82¢\82Ì\82Å\92\8d\88Ó\81B\r
+\r
+2008/09/07  mod 10k2\r
+\81E\8f\88\97\9d\82ª\8fI\97¹\82µ\82½\82ç\83E\83B\83\93\83h\83E\82ð\93_\96Å\82³\82¹\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+\81ERF64\83T\83|\81[\83g\81AVideo Frame\95â\8a®\82Ì\90Ý\92è\82ð\83t\83@\83C\83\8b\82²\82Æ\82É\95Û\91\82·\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+\81E\89¹\90º\82Ì\92x\89\84\8e\9e\8aÔ\82ð\95â\90³\82Å\82«\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+\81E\83^\83u\83I\81[\83_\81[\82ª\82ß\82¿\82á\82­\82¿\82á\82¾\82Á\82½\82Ì\82ð\8fC\90³\81B\r
+\81E\83\89\83\93\83^\83C\83\80\83\89\83C\83u\83\89\83\8a\82ð\93¯\8d«\81B\r
+\r
+2008/08/25  mod 10k1\r
+\81Emod 10 \82ð\89ü\91¢\81B\r
+\81EAAC \82Ì Demux \8b@\94\\82ð\95\9c\8a\88\81B\r
+  AAC Demux \8e\9e\82É\82Í\81A\83t\83@\83C\83\8b\96¼\82É\92x\89\84\8e\9e\8aÔ\82ð\93ü\82ê\82é\82æ\82¤\82É\95Ï\8dX\81B\r
+  \81iDGIndex \82È\82Ç\82Æ\93¯\82\8c`\8e®\81B\81j\r
+\81EWin2k\81iWinXP \82Å\83r\83W\83\85\83A\83\8b\83X\83^\83C\83\8b off \82Ì\8fê\8d\87\82à\81H\81j\82Å\81A\83h\83\8d\83b\83v\83_\83E\83\93\r
+  \83R\83\93\83{\83{\83b\83N\83X\82ª 1\8ds\82µ\82©\95\\8e¦\82³\82ê\82È\82¢\82Ì\82ð\8fC\90³\81B\r
+\81E\83o\83b\83`\83\8a\83X\83g\82Ì\95\\8e¦\95\9d\82ð\8ag\91å\81B\r
+\81E\83t\83@\83C\83\8b\83I\81[\83v\83\93\83_\83C\83A\83\8d\83O\82Ì\83T\83C\83Y\82ð\89Â\95Ï\82É\90Ý\92è\81B\r
+\81E\82»\82Ì\91¼\81AVS2003 \82Å\83R\83\93\83p\83C\83\8b\82Å\82«\82é\82æ\82¤\82É\82·\82é\82½\82ß\82Ì\83\\81[\83X\8fã\82Ì\8fC\90³\82È\82Ç\81B\r
+\r
+\r
+\r
+----------------------------------------------------------------------------\r
+BonTsDemux mod 10 readme\r
+----------------------------------------------------------------------------\r
+\r
+BonTsDemux mod 10 (modified by LxbEvo.FpE)\r
+\r
+TS\83t\83@\83C\83\8b\82ð\81A\92¼\90Ú\95Ê\83t\83@\83C\83\8b\82É\95Ï\8a·\82·\82é\81B\r
+\r
+BonTsDemux\82Å\81AWAV\95Ï\8a·\8e\9e\82ÉVideo Frame\82ÆAudio PTS\82ð\8eg\82Á\82Ä\89¹\90º\82ð \82¸\82ê\82È\82¢\82æ\82¤\82É\95â\8a®\r
+ffmpeg\82É\92¼\90Ú\82Í\82¢\82Ä\82Ý\82é\r
+\r
+\r
+\90Ý\92è\8d\80\96Ú\82Ì\90à\96¾\r
+\r
+       \81ERF64\83T\83|\81[\83g\r
+       \r
+               true \8e\9e 4GB \83I\81[\83o\81[\8e\9e RIFF\8b­\90§ \r
+               false \8e\9e 4GB \83I\81[\83o\81[\8e\9e RF64\81i\8d¡\82Ü\82Å\92Ê\82è\82Ì\93®\8dì\81\r
+\r
+       \81EVideo Frame\95â\8a®\r
+\r
+               \81ETS\83\\81[\83X\82Å\89¹\90º\82Ì\82Ý\82Ì\8bó\8aÔ\82ª\82 \82é\r
+               \81Ebiterr\93\99\82Å\81A\83r\83f\83I or \89¹\90º\83t\83\8c\81[\83\80\82Ì\8c\87\97\8e\82ª\82 \82é\r
+               \8fã\8bL\82ª\82 \82Ä\82Í\82Ü\82éTS\83\\81[\83X\82Å\89¹\82¸\82ê\82ª\94­\90\82·\82é\8fê\8d\87\81A\82±\82ê\82É\83`\83F\83b\83N\82ð\93ü\82ê\82é\82Æ\89ü\91P\82·\82é\82©\82à\81B\r
+               \81¦\82½\82¾\82µ\81A\8c»\8fó\82Å\82Í29.97fps\8c\88\82ß\82¤\82¿\82È\82Ì\82Å\81A\82»\82ê\88È\8aO\82Ì\83\\81[\83X\82¾\82Æ\8bt\82É\82¸\82ê\82Ä\82µ\82Ü\82¢\82Ü\82·\81B\r
+\r
+\r
+FFMPEG\8eg\97p\8e\9e\82Ì\92\8d\88Ó\8e\96\8d\80\r
+       \81E\8b­\90§5.1ch\8fo\97Í\82¾\82Æ\82Ù\82Æ\82ñ\82Ç\82Ì\83P\81[\83X\82Å\83G\83\89\81[\82É\82È\82è\82Ü\82·\81B\r
+       \81Elocalhost:1234\82ðBonTsDemux\91¤\82Å\8eg\97p\82µ\82Ü\82·\81B\r
+       \81E\93ü\97Í(-i)\81A\8fo\97Í\83t\83@\83C\83\8b\82Ì\8ew\92è\82Í\82µ\82È\82¢\82Å\82­\82¾\82³\82¢\81B\r
+\r
+\r
+\83R\83}\83\93\83h\83\89\83C\83\93\82©\82ç\82Ì\8cÄ\82Ñ\8fo\82µ\8ed\97l\r
+       \97á: bontsdemux -i "test.ts" -o "test" -encode "Demux(m2v)" -start -quit\r
+\r
+       \83R\83}\83\93\83h\8eí\97Þ\r
+       -i [\83t\83@\83C\83\8b\96¼]         \93ü\97Í\83t\83@\83C\83\8b(ts)\82Ì\90Ý\92è\r
+       -o [\83t\83@\83C\83\8b\96¼]         \8fo\97Í\83t\83@\83C\83\8b\82Ì\90Ý\92è\81B\8ag\92£\8eq\82Í\8e©\93®\82Å\95t\82­\8ed\97l\82È\82Ì\82Å\81A\82Â\82¯\82È\82¢\82±\82Æ\82ð\90\84\8f§\r
+       -srv [\83T\81[\83r\83X\94Ô\8d\86]     \83T\81[\83r\83X\94Ô\8d\86\82Ì\91I\91ð(10\90i\90\94\92l)\r
+       -es [0-2]                       \89¹\90ºES\82Ì\91I\91ð(0:\83T\81[\83r\83X\82É\88Ë\91¶ 1-2:2-3\94Ô\96Ú\82É\91\8dÝ\82·\82é\89¹\90º(\82È\82¢\8fê\8d\87\82Í0\82Æ\93¯\82\90U\82é\95\91\82¢\82ð\82·\82é)\r
+       -encode [\8eí\97Þ]          [\8eí\97Þ]\97á\81F      \8ew\92è\82È\82µ        \81cDemux(m2v+wav)\r
+                                                                       Demux(wav)      \81c\89¹\90º\82Ì\82Ý\r
+                                                                       Demux(m2v)      \81c\89f\91\9c\82Ì\82Ý\r
+                                                                       MPG2PS          \81cMPG2PS\8c`\8e®\82Å\8fo\97Í(cap_sts_sea.ini\82Å\82Ì\90Ý\92è\8d\80\96Ú)\r
+                                                                       WMV8            \81cWMV8(cap_sts_sea.ini\82Å\82Ì\90Ý\92è\8d\80\96Ú)\r
+                                                                        \81F\r
+       -sound [\95û\8e®(0-4)]      0:Stereo(\8eå+\95\9b)\r
+                                               1:\8eå\89¹\90º\r
+                                               2:\95\9b\89¹\90º\r
+                                               3:\8b­\90§5.1ch\r
+                                               4:\8b­\90§5.1ch(Split)\r
+       -rf64                           wav RF64\83T\83|\81[\83g\r
+       -vf                                     Video Frame\95â\8a®\97L\8cø\r
+       -start                          \8e©\93®\82Å\8aJ\8en\r
+       -quit                           \8e©\93®\82Å\8fI\97¹\r
+\r
+----------------------------------------------------------------------------------------\r
+mod 10\r
+       qE.77T.ink\8e\81\82ÌWavWriter \82Ì RIFF \8b­\90§\91Î\89\9e\94Å\r
+       Video Frame\95â\8a® \82ð\81A\83I\83v\83V\83\87\83\93\88µ\82¢\82É\95Ï\8dX\r
+\r
+mod 9.1\r
+       \95\9b\89¹\90º\82ª\91I\91ð\82Å\82«\82Ä\82¢\82È\82©\82Á\82½\95s\8bï\8d\87\82ð\8fC\90³\r
+\r
+mod 9\r
+       \83R\83}\83\93\83h\83\89\83C\83\93\83I\83v\83V\83\87\83\93\82É\91Î\89\9e\r
+       \89¹\90º\8fo\97Í\95û\8e®\82Å\81A\8eå\89¹\90º,\95\9b\89¹\90º\82Ì\91I\91ð\82ª\8fo\97\88\82È\82©\82Á\82½\95s\8bï\8d\87\82ð\8fC\90³(mod 8\82Å\82Ì\83G\83\93\83o\83O)\r
+       \83t\83@\83C\83\8b\96¼\82ª\92·\82·\82¬\82é\82Æ\81AD&D\8e\9e\82É\97\8e\82¿\82Ä\82¢\82½\95s\8bï\8d\87\82ð\8fC\90³\r
+       RF64\8fo\97Í\82ð\91I\91ð\89Â\94\\82É\82µ\82½\r
+       cap_sts_sea.ini\83t\83@\83C\83\8b\82Å\81A\8ag\92£\8eq\82Ì\8ew\92è\82ð\89Â\94\\82Æ\82µ\82½\r
+       \r
+mod 8\r
+       5.1ch\8fo\97Í\8e\9e\82Ì\83`\83\83\83\93\83l\83\8b\83A\83T\83C\83\93\83o\83O\8fC\90³\r
+       qE.77T.ink\8e\81\82ÌRF64\83t\83H\81[\83}\83b\83g\91Î\89\9e\r
+               \81¨4GB \82ð\92´\82¦\82é\82Æ\8e©\93®\93I\82É RF64 \83t\83H\81[\83}\83b\83g\82É\82È\82é\81B\r
+               \81¨5.1ch Split\83\82\81[\83h\r
+                       \81E\83`\83\83\83\93\83l\83\8b\96\88\82É 1ch Wav \8f\91\82«\8fo\82µ\83N\83\89\83X\81B\r
+                       \81E\93n\82³\82ê\82½\83t\83@\83C\83\8b\96¼\82É\91Î\82µ\82Ä\81A\83`\83\83\83\93\83l\83\8b\82Ì\83T\83t\83B\83b\83N\83X\82ð\95t\82¯\82Ä\8fo\97Í\82·\82é\81B\r
+                       \81E4GB \82ð\92´\82¦\82é\82Æ\8e©\93®\93I\82É RF64 \83t\83H\81[\83}\83b\83g\82É\82È\82é\81B\r
+\r
+mod 7\r
+       File\8fo\97Í\8e\9e\82É\81AGOP\82Ì\83T\83C\83Y\82ª\91å\82«\82¢\82Æ\8f\91\82«\82±\82Ý\83G\83\89\81[\82ð\82¨\82±\82µ\82Ä\82¢\82½\95s\8bï\8d\87\82ð\8fC\90³\r
+       ffmpeg\82ª\88Ù\8fí\8fI\97¹\82µ\82½\82Æ\82«\82É\83n\83\93\83O\83A\83b\83v\82µ\82Ä\82¢\82½\82Ì\82ð\8fC\90³\r
+       demux\8e\9e\82É\89¹\90º\95â\90³\82ð\8ds\82Á\82½\8dÛ\81A\88Ù\8fí\8fI\97¹\82·\82é\95s\8bï\8d\87\82ð\8fC\90³\r
+       \82»\82Ì\91¼\81A\8d×\82©\82¢\82Æ\82±\82ë\82ð\8fC\90³\r
+       \r
+mod 6b2\r
+       Meru\8e\81\82Ì\83T\81[\83r\83X\91I\91ð\82ð\91g\82Ý\8d\9e\82Ý(\93®\8dì\82 \82Ü\82è\8c©\82ê\82Ä\82¢\82È\82¢\81B)\r
+       PTS\82Ì\82È\82¢\83p\83P\83b\83g\82ª\82«\82½\82Æ\82«\82É\81A\8b­\90§\8fI\97¹\82·\82é\95s\8bï\8d\87\82ð\8fC\90³\r
+       \83r\83f\83I\8fo\97Í\83t\83@\83C\83\8b\82Ì\83G\83f\83B\83b\83g\83{\83b\83N\83X\82É\81A\8ag\92£\8eq\82ð\95\\8e¦\82µ\82È\82¢\82æ\82¤\82É\8fC\90³\r
+       \8ag\92£\8eq\82ðm2v,wav,mpg,mp4,avi\82©\82ç\8e©\93®\82Å\91I\91ð\82·\82é\8b@\94\\r
+\r
+mod 6b\r
+       5.1 DownMix\82Ì\8cW\90\94\8aÔ\88á\82¢\82ð\8fC\90³\r
+       qE.77T.ink\8e\81\82Ì\8b­\90§5.1ch\8fo\97Í\82ð\91g\82Ý\8d\9e\82Ý(TS\83\\81[\83X\82ª\82È\82¢\82½\82ß\81A\93®\8dì\96¢\8c\9f\8fØ)\r
+       Audio ES \91I\91ð\8b@\94\\92Ç\89Á\r
+       \83o\83b\83`\8f\88\97\9d\8b@\94\\92Ç\89Á\r
+       D&D\8b@\94\\92Ç\89Á\r
+       \89¹\90º\91I\91ð(\8eå\81A\95\9b\89¹)\92Ç\89Á\r
+       WAV\8fo\97Í\82Ì\82Ý\81AM2V\8fo\97Í\82Ì\82Ý\91I\91ð\8b@\94\\92Ç\89Á\r
+       \89¹\82¸\82ê\95â\90³\8fC\90³(\83X\83g\83\8a\81[\83\80\93r\92\86\82Å\82à\81A200ms\88È\8fã\8bó\94\92\82ª\82 \82é\8fê\8d\87\82ÍNULL\82Å\88ê\8bC\82É\96\84\82ß\82Ä\82Ý\82é)\r
+\r
+mod 5\r
+       ffmpeg\82É\92¼\90Ú\82Í\82¢\82Ä\82Ý\82é\83e\83X\83g\r
+       ffmpeg\82Ö\82Ì\83p\83\89\83\81\81[\83^\82Í\81Acap_sts_sea.ini\82Å\92\80\8e\9f\95Ï\8dX\82µ\82Ä\82­\82¾\82³\82¢\81B\r
+               \81¨\93ü\97Í(-i)\81A\8fo\97Í\83t\83@\83C\83\8b\82Ì\8ew\92è\82Í\82µ\82È\82¢\82Å\82­\82¾\82³\82¢\81B\r
+               \81¨2-pass\82Í\8fo\97\88\82Ü\82¹\82ñ(\8ed\97l)\81B\r
+               \81¨\95t\91®\82Ìffmpeg.exe\82Í\81A rev.12910 Pentium4\8dÅ\93K\89»\94Å\82Å\82·\81B(\93ü\8eè\8c³\81Fhttp://blog.k-tai-douga.com/)\r
+       \82Ü\82½\81A\8d¡\89ñ\82Ì\83o\81[\83W\83\87\83\93\82æ\82è\81Awav\93f\82«\8fo\82µ\90ê\97p\82É\82È\82Á\82Ä\82¢\82Ü\82·\81B(\89¹\90º\82Í\8b­\90§2ch\90ê\97p)\r
+\r
+mod 4\r
+       mod 3\82Å\83R\83~\83b\83g\83~\83X\82ª\82 \82Á\82½\82Ì\82Å\8fC\90³\r
+       \81{\91½\8f­\89ü\97Ç\r
+\r
+mod 3\r
+       \93r\92\86\82Å\83`\83\83\83\93\83l\83\8b\82ð\95Ï\82¦\82Ä\82à\81A\82 \82é\92ö\93x\93¯\8aú\82Å\82«\82é\82æ\82¤\82É\82µ\82½(\8e\84\82Ì\8eÀ\97Í\82Å\82Í\81A\82±\82ê\82ª\8cÀ\8aE)\r
+       \83G\83\89\81[\82Å\94j\8aü\82·\82é\82µ\82©\82È\82¢\89¹\90º\83t\83\8c\81[\83\80\82ª\82 \82Á\82½\8fê\8d\87\81A\88È\91O\82Ì\83I\81[\83f\83B\83I\83T\83C\83Y\95ª0\8fo\97Í\82·\82é\82æ\82¤\82É\82µ\82Ä\82Ý\82½\81B\r
+       (\8cø\89Ê\82Í\82 \82Á\82½\82ç\82¢\82¢\82È\92ö\93x)\r
+\r
+\r
+\r
+----------------------------------------------------------------------------\r
+original readme\r
+----------------------------------------------------------------------------\r
+\r
+\r
+\81| BonTsDemux Ver.1.10 \81|\r
+\r
+\r
+\82P\81D\8aT\97v\r
+\81@\81@\81EBon\83V\83\8a\81[\83Y\82ÌMPEG2-TS\8f\88\97\9d\83G\83\93\83W\83\93\81uBonTsEngine\81v\82ð\8eg\97p\82µ\82½\83T\83\93\83v\83\8b\83v\83\8d\83O\83\89\83\80\82Å\82·\81B\r
+\81@\81@\81ETS\83t\83@\83C\83\8b\82©\82ç\89f\91\9c(m2v)\82Æ\89¹\90º(aac/wav)\82ð\95ª\97£\82µ\82Ä\83t\83@\83C\83\8b\82É\8fo\97Í\82µ\82Ü\82·\81B\r
+\81@\81@\81EB-CAS\83J\81[\83h\82ª\90Ú\91±\82³\82ê\82Ä\82¢\82é\8fê\8d\87\82Í\83X\83N\83\89\83\93\83u\83\8b\82³\82ê\82½TS\83t\83@\83C\83\8b\82Ì\93Ç\82Ý\8d\9e\82Ý\82ª\89Â\94\\82Å\82·\81B\r
+\81@\81@\81E\83}\83\8b\83`\83`\83\83\83\93\83l\83\8b\82Ì\8fê\8d\87\82ÍPAT\82Å\8dÅ\8f\89\82Ì\83T\81[\83r\83X\82É\91®\82·\82é\83X\83g\83\8a\81[\83\80\82ª\95ª\97£\82³\82ê\82Ü\82·\81B\r
+\81@\81@\81EAAC\83f\83R\81[\83h\82ð\8eg\97p\82·\82é\8fê\8d\87\82Í\8fí\82É2ch\82É\83_\83E\83\93\83R\83\93\83o\81[\83g/\83A\83b\83v\83R\83\93\83o\81[\83g\82³\82ê\82Ü\82·\81B\r
+\r
+\81@\81@\81¦\96{\83\\83t\83g\83E\83F\83A\82Ì\93®\8dì\82É\82Í\81uMicrosoft Visual C++ 2005 SP1 \8dÄ\94Ð\95z\89Â\94\\83p\83b\83P\81[\83W\81v\82ª\95K\97v\82Å\82·\81B\r
+\81@\81@\81@\81@http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=200b2fd9-ae1a-4a14-984d-389c36f85647\r
+\r
+\r
+\82Q\81D\92\8d\88Ó\8e\96\8d\80\r
+\81@\81@\81EB-CAS\83J\81[\83h\82ð\8b\96\89Â\82³\82ê\82½\8b@\8aí\88È\8aO\82Å\8eg\97p\82·\82é\82±\82Æ\82ÍB-CAS\83J\81[\83h\82Ì\8c_\96ñ\96ñ\8a¼\82É\92ï\90G\82·\82é\89Â\94\\90«\82ª\82 \82é\r
+\81@\81@\81@\82½\82ß\81A\96{\83\\83t\83g\83E\83F\83A\82Í\8e©\8cÈ\82Ì\90Ó\94C\82É\82¨\82¢\82Ä\8eg\97p\82µ\82Ä\89º\82³\82¢\81B\r
+\81@\81@\81E\96{\83\\83t\83g\83E\83F\83A\82Í\89º\8bL\81u\8cö\8aJ\8bK\8ai\81v\82Ì\8bZ\8fp\8fî\95ñ\82É\8aî\82Ã\82«\81u\90³\8bK\82Ì\8eè\96@\81v\82ð\97p\82¢\82é\82æ\82¤\8eÀ\91\95\82³\82ê\82Ä\82¢\82Ü\82·\81B\r
+\81@\81@\81@\8f\83\90\88\82É\8bZ\8fp\93I\82È\8c\9f\8fØ\82ð\96Ú\93I\82Æ\82µ\82½\83T\83\93\83v\83\8b\83v\83\8d\83O\83\89\83\80\82Å\82 \82è\81A\91æ\8eO\8eÒ\82Ì\92m\93I\8dà\8eY\8c \82ð\90N\8aQ\82·\82é\89Â\94\\90«\82Ì\r
+\81@\81@\81@\82 \82é\96Ú\93I\82É\8eg\97p\82³\82ê\82é\82±\82Æ\82ð\8dì\8eÒ\82Í\88ê\90Ø\88Ó\90}\82µ\82Ä\82¨\82ç\82¸\81A\82Ü\82½\82±\82ê\82ç\82Ì\8ds\88×\82ð\8bÖ\8e~\82µ\82Ü\82·\81B\r
+\81@\81@\81E\96{\83\\83t\83g\83E\83F\83A\82Í\90³\8bK\82É\83\89\83C\83Z\83\93\83X\82³\82ê\82½B-CAS\83J\81[\83h\82ð\97p\82¢\82é\82±\82Æ\82É\82æ\82è\95\9c\8d\86\82ð\8ds\82¢\82Ü\82·\81B\r
+\81@\81@\81E\96{\83\\83t\83g\83E\83F\83A\92P\91Ì\82Å\82Í\82¢\82©\82È\82é\92\98\8dì\95¨\82Ì\8bZ\8fp\93I\95Û\8cì\8eè\92i\82à\89ñ\94ð\82·\82é\82±\82Æ\82Í\82Å\82«\82Ü\82¹\82ñ\81B\r
+\81@\81@\81E\96{\83\\83t\83g\83E\83F\83A\82Í\81u\83t\83\8a\81[\83\\83t\83g\81v\82Å\82·\81B\r
+\81@\81@\81E\96{\83\\83t\83g\83E\83F\83A\82ÍARIB\8bK\8ai\82É\93K\8d\87\82·\82é\82±\82Æ\82ð\95Û\8fá\82µ\82Ä\82¨\82ç\82¸\81A\82¢\82©\82È\82é\8eí\95Ê\82Ì\90»\95i\82É\82à\8aY\93\96\82µ\82Ü\82¹\82ñ\81B\r
+\81@\81@\81E\96{\83\\83t\83g\83E\83F\83A\82ð\8eg\97p\82µ\82½\8c\8b\89Ê\94­\90\82µ\82½\82¢\82©\82È\82é\91¹\8aQ\82à\8dì\8eÒ\82Í\90Ó\94C\82ð\95\89\82¤\82±\82Æ\82Í\82Å\82«\82Ü\82¹\82ñ\81B\r
+\81@\81@\81E\96{\83T\83\93\83v\83\8b\83v\83\8d\83O\83\89\83\80\82Ì\83\\81[\83X\83R\81[\83h\82Ì\8eæ\82è\88µ\82¢\82ÍGPL\82É\8f]\82¤\82±\82Æ\82Æ\82µ\82Ü\82·\81B\r
+\r
+\81@\81@\82±\82ê\82ç\82É\93¯\88Ó\92¸\82¯\82é\8fê\8d\87\82É\82Ì\82Ý\81A\96{\83\\83t\83g\83E\83F\83A\82Ì\8eg\97p\82ð\8b\96\89Â\92v\82µ\82Ü\82·\81B\r
+\r
+\r
+\82R\81D\83\89\83C\83Z\83\93\83X\82É\82Â\82¢\82Ä\r
+\81@\81@\81E\96{\83p\83b\83P\81[\83W\82É\8aÜ\82Ü\82ê\82é\91S\82Ä\82Ì\83\\81[\83X\83R\81[\83h\81A\83o\83C\83i\83\8a\82É\82Â\82¢\82Ä\92\98\8dì\8c \82Í\88ê\90Ø\8eå\92£\82µ\82Ü\82¹\82ñ\81B\r
+\81@\81@\81E\83I\83\8a\83W\83i\83\8b\82Ì\82Ü\82Ü\96\94\82Í\89ü\95Ï\82µ\81A\8ae\8e©\82Ì\83\\83t\83g\83E\83F\83A\82É\8e©\97R\82É\93Y\95t\81A\91g\82Ý\8d\9e\82Þ\82±\82Æ\82ª\82Å\82«\82Ü\82·\81B\r
+\81@\81@\81E\92A\82µGPL\82É\8f]\82¤\82±\82Æ\82ð\97v\8b\81\82µ\82Ü\82·\82Ì\82Å\82±\82ê\82ç\82ð\8ds\82¤\8fê\8d\87\82Í\83\\81[\83X\83R\81[\83h\82Ì\8aJ\8e¦\82ª\95K\90{\82Æ\82È\82è\82Ü\82·\81B\r
+\81@\81@\81E\82±\82Ì\82Æ\82«\96{\83\\83t\83g\83E\83F\83A\82Ì\92\98\8dì\8c \95\\8e¦\82ð\8ds\82¤\82©\82Ç\82¤\82©\82Í\94C\88Ó\82Å\82·\81B\r
+\81@\81@\81E\96{\83\\83t\83g\83E\83F\83A\82ÍFAAD2\82Ì\83\89\83C\83u\83\89\83\8a\94Å\83o\83C\83i\83\8a\82ð\8eg\97p\82µ\82Ä\82¢\82Ü\82·\81B\r
+\r
+\81@\81@\81@"Code from FAAD2 is copyright (c) Nero AG, www.nero.com"\r
+\r
+\81@\81@\81E\83r\83\8b\83h\82É\95K\97v\82È\8aÂ\8b«\r
+\81@\81@\81@- Microsoft Visual Studio 2005 \88È\8fã\81@\81¦MFC\82ª\95K\97v\r
+\81@\81@\81@- Microsoft Windows SDK v6.0 \88È\8fã\r
+\r
+\r
+\82S\81D\8eQ\8dl\95\8c£\r
+\81@\81@\81EARIB STD-B10\r
+\81@\81@\81EARIB STD-B24\r
+\81@\81@\81EARIB STD-B25\r
+\81@\81@\81EARIB STD-B32\r
+\81@\81@\81EISO/IEC 11172-3\r
+\81@\81@\81EISO/IEC 13818-1\r
+\81@\81@\81EISO/IEC 13818-2\r
+\81@\81@\81EISO/IEC 13818-7\r
+\r
+\81@\81@\81E\82Ü\82é\82à\90»\8dì\8f\8a\81uARIB STD-B25 \8ed\97l\8am\94F\83e\83X\83g\83v\83\8d\83O\83\89\83\80\81v\r
+\81@\81@\81EMeru\8e\81\81uBonTsEngine\89ü\91¢\94Å\81v\r
+\81@\81@\81EMeru\8e\81\81uCapUSB M-Edition\81v\r
+\81@\81@\81E\8dì\8eÒ\95s\96¾\81uMpeg2-TS\82Ì\83X\83g\83\8a\81[\83\80\82©\82ç\83f\81[\83^\95ú\91\97\8fî\95ñ\82ð\92\8a\8fo\82·\82é\83e\83X\83g\81v\r
+\81@\81@\81EMicrosoft DirectX 9.0\81uPSI \83p\81[\83T\81\83t\83B\83\8b\83\83T\83\93\83v\83\8b\81v\r
+\r
+\r
+\82T\81D\83T\83|\81[\83g\81A\98A\97\8d\90æ\r
+\81@\81@\81@\98A\97\8d\90æ\81@\81@\81F\81@\8ag\92£\83c\81[\83\8b\92\86\82Ì\90l\81@\81@nakanohito@2sen.dip.jp\r
+\81@\81@\81@\8cö\8e®\83T\83C\83g\81F\81@http://2sen.dip.jp/friio/\r
+\r
+\82U\81D\8dX\90V\97\9a\97ð\r
+\81@Ver.1.10 \81E\89f\91\9c\82Æ\89¹\90º\82Ì\8aJ\8en\88Ê\92u\82ð\93¯\8aú\82³\82¹\82é\8b@\94\\82ð\92Ç\89Á\81B\r
+\81@\81@\81@\81@\81\81E\89¹\90º\8fo\97Í\83t\83@\83C\83\8b\96¼\82ª\94½\89f\82³\82ê\82È\82©\82Á\82½\95s\8bï\8d\87\8fC\90³\81B\r
+\r
+\81@Ver.1.00 \81E\8f\89\89ñ\83\8a\83\8a\81[\83X\r
diff --git a/dist/trunk/tstools/BonTsDemux/BonTsDemuxLib.dll b/dist/trunk/tstools/BonTsDemux/BonTsDemuxLib.dll
new file mode 100755 (executable)
index 0000000..11278c7
Binary files /dev/null and b/dist/trunk/tstools/BonTsDemux/BonTsDemuxLib.dll differ
diff --git a/dist/trunk/tstools/BonTsDemux/src.zip b/dist/trunk/tstools/BonTsDemux/src.zip
new file mode 100755 (executable)
index 0000000..a7893cd
Binary files /dev/null and b/dist/trunk/tstools/BonTsDemux/src.zip differ
diff --git a/dist/trunk/tstools/Makefile b/dist/trunk/tstools/Makefile
new file mode 100755 (executable)
index 0000000..a067cb2
--- /dev/null
@@ -0,0 +1,34 @@
+PREFIX = /usr/local/share
+MAJOR = 0
+MINOR = 9
+REVISION = 10
+VER = $(MAJOR).$(MINOR).$(REVISION)
+
+DEST = $(PREFIX)/rec10/tstools
+
+all: 
+       cd epgdump;make all
+       cd tunerec;make
+clean:
+       cd epgdump;make clean
+install: 
+       if ! [ -d $(DEST) ]; then mkdir -p $(DEST) ;fi
+       if [ -f $(DEST)/BonTsDemux.exe ]; then rm $(DEST)/BonTsDemux.exe ;fi
+       if [ -f $(DEST)/BonTsDemuxLib.dll ]; then rm $(DEST)/BonTsDemuxLib.dll ;fi
+       cd BonTsDemux;cp ./*.* $(DEST)/
+       if [ -f $(DEST)/jTsSplitter.jar ]; then rm $(DEST)/jTsSplitter.jar ;fi
+       cd jTsSplitter;cp ./*.* $(DEST)/
+       #cd cfr2tc;cp ./cfr2tc.exe $(DEST)/
+       #cd DtsEdit;cp ./DtsEdit.exe $(DEST)/
+       #cd xvfb-run;cp ./xvfb-run $(DEST)/
+       #cd caption2ass;cp ./Caption2Ass.exe $(DEST)/
+       #cd caption2ass;cp ./Caption.dll $(DEST)/
+       #chmod +x $(DEST)/xvfb-run
+       cd epgdump;make install
+       cd tunerec;install -m755 ./tunerec /usr/local/bin/
+       if [ -f ./neroAacEnc ]; then install -m755 ./neroAacEnc /usr/local/bin/ ;fi
+uninstall:
+       rm -rf $(DEST)
+       if [ -f /usr/local/bin/neroAacEnc ]; then rm /usr/local/bin/neroAacEnc ;fi
+       rm -rf /usr/local/bin/tunerec
+       cd epgdump;make uninstall
diff --git a/dist/trunk/tstools/epgdump/Makefile b/dist/trunk/tstools/epgdump/Makefile
new file mode 100755 (executable)
index 0000000..53be5ba
--- /dev/null
@@ -0,0 +1,31 @@
+PREFIX         = /usr/local
+TARGETS        = epgdump
+OBJ_TARGETS    = epgdump.o aribstr.o eit.o ts.o util.o sdt.o
+HEDDERDEPEND   = eit.h sdt.h aribstr.h ts.h util.h
+
+LANG           = C
+CC             = gcc
+
+#CFLAGS                = -std=c99 -O2 -Wall -g
+CFLAGS         = -std=c99 -O2 -Wall -ggdb
+
+LIBS           = 
+
+.c.o:                  ${CC} ${CFLAGS} -c $<
+
+all:                   ${TARGETS}
+
+${TARGETS}:            ${OBJ_TARGETS}
+                       ${CC} ${CFLAGS} ${OBJ_TARGETS} -o $@ ${LDFLAGS} ${LIBS}
+
+${OBJ_TARGETS}:        ${HEDDERDEPEND}
+
+clean:
+                       rm -f core ${TARGETS} *.o
+
+install:               ${TARGETS}
+                       install -m755 ${TARGETS} ${PREFIX}/bin
+
+uninstall:             ${TARGETS}
+                       rm ${PREFIX}/bin/${TARGETS}
+
diff --git a/dist/trunk/tstools/epgdump/aribstr.c b/dist/trunk/tstools/epgdump/aribstr.c
new file mode 100755 (executable)
index 0000000..1e736ea
--- /dev/null
@@ -0,0 +1,599 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <iconv.h>
+
+#include "aribstr.h"
+
+#define CODE_UNKNOWN           0       // ÉÔÌÀ¤Ê¥°¥é¥Õ¥£¥Ã¥¯¥»¥Ã¥È(ÈóÂбþ)
+#define CODE_KANJI             1       // Kanji
+#define CODE_ALPHANUMERIC      2       // Alphanumeric
+#define CODE_HIRAGANA          3       // Hiragana
+#define CODE_KATAKANA          4       // Katakana
+#define CODE_MOSAIC_A          5       // Mosaic A
+#define CODE_MOSAIC_B          6       // Mosaic B
+#define CODE_MOSAIC_C          7       // Mosaic C
+#define CODE_MOSAIC_D          8       // Mosaic D
+#define CODE_PROP_ALPHANUMERIC         9       // Proportional Alphanumeric
+#define CODE_PROP_HIRAGANA     10      // Proportional Hiragana
+#define CODE_PROP_KATAKANA     11      // Proportional Katakana
+#define CODE_JIS_X0201_KATAKANA 12     // JIS X 0201 Katakana
+#define CODE_JIS_KANJI_PLANE_1         13      // JIS compatible Kanji Plane 1
+#define CODE_JIS_KANJI_PLANE_2         14      // JIS compatible Kanji Plane 2
+#define CODE_ADDITIONAL_SYMBOLS        15      // Additional symbols
+
+
+#define TCHAR char
+#define BYTE  char
+#define WORD  int
+#define DWORD int
+#define bool  int
+#define true  1
+#define false 0
+#define TEXT(a) a
+#define _T(a) a
+#define CODE_SET int
+
+static int m_CodeG[4];
+static int *m_pLockingGL;
+static int *m_pLockingGR;
+static int *m_pSingleGL;
+       
+static BYTE m_byEscSeqCount;
+static BYTE m_byEscSeqIndex;
+static bool m_bIsEscSeqDrcs;
+
+
+static const DWORD AribToStringInternal(TCHAR *lpszDst, const BYTE *pSrcData, const DWORD dwSrcLen);
+static const DWORD ProcessCharCode(TCHAR *lpszDst, const WORD wCode, const CODE_SET CodeSet);
+
+static const DWORD PutKanjiChar(TCHAR *lpszDst, const WORD wCode);
+static const DWORD PutAlphanumericChar(TCHAR *lpszDst, const WORD wCode);
+static const DWORD PutHiraganaChar(TCHAR *lpszDst, const WORD wCode);
+static const DWORD PutKatakanaChar(TCHAR *lpszDst, const WORD wCode);
+static const DWORD PutJisKatakanaChar(TCHAR *lpszDst, const WORD wCode);
+static const DWORD PutSymbolsChar(TCHAR *lpszDst, const WORD wCode);
+
+static void ProcessEscapeSeq(const BYTE byCode);
+
+static void LockingShiftGL(const BYTE byIndexG);
+static void LockingShiftGR(const BYTE byIndexG);
+static void SingleShiftGL(const BYTE byIndexG);
+
+static const bool DesignationGSET(const BYTE byIndexG, const BYTE byCode);
+static const bool DesignationDRCS(const BYTE byIndexG, const BYTE byCode);
+
+static WORD convertjis(DWORD);
+
+static const bool abCharSizeTable[] =
+{
+       false,  // CODE_UNKNOWN                                 ÉÔÌÀ¤Ê¥°¥é¥Õ¥£¥Ã¥¯¥»¥Ã¥È(ÈóÂбþ)
+       true,   // CODE_KANJI                                   Kanji
+       false,  // CODE_ALPHANUMERIC                    Alphanumeric
+       false,  // CODE_HIRAGANA                                Hiragana
+       false,  // CODE_KATAKANA                                Katakana
+       false,  // CODE_MOSAIC_A                                Mosaic A
+       false,  // CODE_MOSAIC_B                                Mosaic B
+       false,  // CODE_MOSAIC_C                                Mosaic C
+       false,  // CODE_MOSAIC_D                                Mosaic D
+       false,  // CODE_PROP_ALPHANUMERIC               Proportional Alphanumeric
+       false,  // CODE_PROP_HIRAGANA                   Proportional Hiragana
+       false,  // CODE_PROP_KATAKANA                   Proportional Katakana
+       false,  // CODE_JIS_X0201_KATAKANA              JIS X 0201 Katakana
+       true,   // CODE_JIS_KANJI_PLANE_1               JIS compatible Kanji Plane 1
+       true,   // CODE_JIS_KANJI_PLANE_2               JIS compatible Kanji Plane 2
+       true    // CODE_ADDITIONAL_SYMBOLS              Additional symbols
+};
+
+int AribToString(
+       char *lpszDst, 
+       const char *pSrcData, 
+       const int dwSrcLen) {
+  
+       return AribToStringInternal(lpszDst, pSrcData, dwSrcLen);
+}
+
+
+const DWORD AribToStringInternal(TCHAR *lpszDst, 
+                                                                const BYTE *pSrcData, const DWORD dwSrcLen)
+{
+       if(!pSrcData || !dwSrcLen || !lpszDst)return 0UL;
+  
+       DWORD dwSrcPos = 0UL;
+       DWORD dwDstLen = 0UL;
+       int   dwSrcData;
+  
+       // ¾õÂÖ½é´üÀßÄê
+       m_byEscSeqCount = 0U;
+       m_pSingleGL = NULL;
+
+       m_CodeG[0] = CODE_KANJI;
+       m_CodeG[1] = CODE_ALPHANUMERIC;
+       m_CodeG[2] = CODE_HIRAGANA;
+       m_CodeG[3] = CODE_KATAKANA;
+
+       m_pLockingGL = &m_CodeG[0];
+       m_pLockingGR = &m_CodeG[2];
+
+       while(dwSrcPos < dwSrcLen){
+               dwSrcData = pSrcData[dwSrcPos] & 0xFF;
+
+               if(!m_byEscSeqCount){
+      
+                       // GL/GRÎΰè
+                       if((dwSrcData >= 0x21U) && (dwSrcData <= 0x7EU)){
+                               // GLÎΰè
+                               const CODE_SET CurCodeSet = (m_pSingleGL)? *m_pSingleGL : *m_pLockingGL;
+                               m_pSingleGL = NULL;
+                               
+                               if(abCharSizeTable[CurCodeSet]){
+                                       // 2¥Ð¥¤¥È¥³¡¼¥É
+                                       if((dwSrcLen - dwSrcPos) < 2UL)break;
+                                       
+                                       dwDstLen += ProcessCharCode(&lpszDst[dwDstLen], ((WORD)pSrcData[dwSrcPos + 0] << 8) | (WORD)pSrcData[dwSrcPos + 1], CurCodeSet);
+                                       dwSrcPos++;
+                               }
+                               else{
+                                       // 1¥Ð¥¤¥È¥³¡¼¥É
+                                       dwDstLen += ProcessCharCode(&lpszDst[dwDstLen], (WORD)dwSrcData, CurCodeSet);
+                               }
+                       }
+                       else if((dwSrcData >= 0xA1U) && (dwSrcData <= 0xFEU)){
+                               // GRÎΰè
+                               const CODE_SET CurCodeSet = *m_pLockingGR;
+                               
+                               if(abCharSizeTable[CurCodeSet]){
+                                       // 2¥Ð¥¤¥È¥³¡¼¥É
+                                       if((dwSrcLen - dwSrcPos) < 2UL)break;
+                                       
+                                       dwDstLen += ProcessCharCode(&lpszDst[dwDstLen], ((WORD)(pSrcData[dwSrcPos + 0] & 0x7FU) << 8) | (WORD)(pSrcData[dwSrcPos + 1] & 0x7FU), CurCodeSet);
+                                       dwSrcPos++;
+                               }
+                               else{
+                                       // 1¥Ð¥¤¥È¥³¡¼¥É
+                                       dwDstLen += ProcessCharCode(&lpszDst[dwDstLen], (WORD)(dwSrcData & 0x7FU), CurCodeSet);
+                               }
+                       }
+                       else{
+                               // À©¸æ¥³¡¼¥É
+                               switch(dwSrcData){
+                               case 0x0FU      : LockingShiftGL(0U);                           break;  // LS0
+                               case 0x0EU      : LockingShiftGL(1U);                           break;  // LS1
+                               case 0x19U      : SingleShiftGL(2U);                            break;  // SS2
+                               case 0x1DU      : SingleShiftGL(3U);                            break;  // SS3
+                               case 0x1BU      : m_byEscSeqCount = 1U;                         break;  // ESC
+                               case 0x20U      :
+                               case 0xA0U      : lpszDst[dwDstLen++] = TEXT(' ');      break;  // SP
+                               default         : break;        // ÈóÂбþ
+                               }
+                       }
+               }
+               else{
+                       // ¥¨¥¹¥±¡¼¥×¥·¡¼¥±¥ó¥¹½èÍý
+                       ProcessEscapeSeq(dwSrcData);
+               }
+               
+               dwSrcPos++;
+       }
+
+       // ½ªÃ¼Ê¸»ú
+       lpszDst[dwDstLen] = TEXT('\0');
+
+       return dwDstLen;
+}
+
+const DWORD ProcessCharCode(TCHAR *lpszDst, const WORD wCode, const CODE_SET CodeSet)
+{
+       switch(CodeSet){
+       case CODE_KANJI :
+       case CODE_JIS_KANJI_PLANE_1 :
+       case CODE_JIS_KANJI_PLANE_2 :
+               // ´Á»ú¥³¡¼¥É½ÐÎÏ
+               return PutKanjiChar(lpszDst, wCode);
+
+       case CODE_ALPHANUMERIC :
+       case CODE_PROP_ALPHANUMERIC :
+               // ±Ñ¿ô»ú¥³¡¼¥É½ÐÎÏ
+               return PutAlphanumericChar(lpszDst, wCode);
+
+       case CODE_HIRAGANA :
+       case CODE_PROP_HIRAGANA :
+               // ¤Ò¤é¤¬¤Ê¥³¡¼¥É½ÐÎÏ
+               return PutHiraganaChar(lpszDst, wCode);
+
+       case CODE_PROP_KATAKANA :
+       case CODE_KATAKANA :
+               // ¥«¥¿¥«¥Ê¥³¡¼¥É½ÐÎÏ
+               return PutKatakanaChar(lpszDst, wCode);
+
+       case CODE_JIS_X0201_KATAKANA :
+               // JIS¥«¥¿¥«¥Ê¥³¡¼¥É½ÐÎÏ
+               return PutJisKatakanaChar(lpszDst, wCode);
+#if 1
+       case CODE_ADDITIONAL_SYMBOLS :
+               // Äɲå·¥ó¥Ü¥ë¥³¡¼¥É½ÐÎÏ
+               return PutSymbolsChar(lpszDst, wCode);
+#endif
+       default :
+               return 0UL;
+       }
+}
+
+const DWORD PutKanjiChar(TCHAR *lpszDst, const WORD wCode)
+{
+       // JIS¢ªShift-JIS´Á»ú¥³¡¼¥ÉÊÑ´¹
+       const WORD wShiftJIS = convertjis(wCode);
+
+#ifdef _UNICODE
+       // Shift-JIS ¢ª UNICODE
+       const char szShiftJIS[3] = {(char)(wShiftJIS >> 8), (char)(wShiftJIS & 0x00FFU), '\0'};
+       ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, szShiftJIS, 2, lpszDst, 2);
+
+       return 1UL;
+#else
+       // Shift-JIS ¢ª Shift-JIS
+       lpszDst[0] = (wShiftJIS >> 8) & 0xFF;
+       lpszDst[1] = (char)(wShiftJIS & 0x00FFU);
+  
+       return 2UL;
+#endif
+}
+
+const DWORD PutAlphanumericChar(TCHAR *lpszDst, const WORD wCode)
+{
+       // ±Ñ¿ô»úʸ»ú¥³¡¼¥ÉÊÑ´¹
+       static const TCHAR *acAlphanumericTable = 
+               TEXT("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡")
+               TEXT("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡")
+               TEXT("¡¡¡ª¡É¡ô¡ð¡ó¡õ¡Ç¡Ê¡Ë¡ö¡Ü¡¤¡Ý¡¥¡¿")
+               TEXT("£°£±£²£³£´£µ£¶£·£¸£¹¡§¡¨¡ã¡á¡ä¡©")
+               TEXT("¡÷£Á£Â£Ã£Ä£Å£Æ£Ç£È£É£Ê£Ë£Ì£Í£Î£Ï")
+               TEXT("£Ð£Ñ£Ò£Ó£Ô£Õ£Ö£×£Ø£Ù£Ú¡Î¡ï¡Ï¡°¡²")
+               TEXT("¡¡£á£â£ã£ä£å£æ£ç£è£é£ì£ë£ì£í£î£ï")
+               TEXT("£ð£ñ£ò£ó£ô£õ£ö£÷£ø£ù£ú¡Ð¡Ã¡Ñ¡±¡¡");
+
+#ifdef _UNICODE
+       lpszDst[0] = acAlphanumericTable[wCode];
+
+       return 1UL;
+#else
+       lpszDst[0] = acAlphanumericTable[wCode * 2U + 0U];
+       lpszDst[1] = acAlphanumericTable[wCode * 2U + 1U];
+
+       return 2UL;
+#endif
+}
+
+const DWORD PutHiraganaChar(TCHAR *lpszDst, const WORD wCode)
+{
+       // ¤Ò¤é¤¬¤Êʸ»ú¥³¡¼¥ÉÊÑ´¹
+       static const TCHAR *acHiraganaTable = 
+               TEXT("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡")
+               TEXT("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡")
+               TEXT("¡¡¤¡¤¢¤£¤¤¤¥¤¦¤§¤¨¤©¤ª¤«¤¬¤­¤®¤¯")
+               TEXT("¤°¤±¤²¤³¤´¤µ¤¶¤·¤¸¤¹¤º¤»¤¼¤½¤¾¤¿")
+               TEXT("¤À¤Á¤Â¤Ã¤Ä¤Å¤Æ¤Ç¤È¤É¤Ê¤Ë¤Ì¤Í¤Î¤Ï")
+               TEXT("¤Ð¤Ñ¤Ò¤Ó¤Ô¤Õ¤Ö¤×¤Ø¤Ù¤Ú¤Û¤Ü¤Ý¤Þ¤ß")
+               TEXT("¤à¤á¤â¤ã¤ä¤å¤æ¤ç¤è¤é¤ê¤ë¤ì¤í¤î¤ï")
+               TEXT("¤ð¤ñ¤ò¤ó¡¡¡¡¡¡¡µ¡¶¡¼¡£¡Ö¡×¡¢¡¦¡¡");
+       
+#ifdef _UNICODE
+       lpszDst[0] = acHiraganaTable[wCode];
+
+       return 1UL;
+#else
+       lpszDst[0] = acHiraganaTable[wCode * 2U + 0U];
+       lpszDst[1] = acHiraganaTable[wCode * 2U + 1U];
+
+       return 2UL;
+#endif
+}
+
+const DWORD PutKatakanaChar(TCHAR *lpszDst, const WORD wCode)
+{
+       // ¥«¥¿¥«¥Ê±Ñ¿ô»úʸ»ú¥³¡¼¥ÉÊÑ´¹
+       static const TCHAR *acKatakanaTable = 
+               TEXT("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡")
+               TEXT("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡")
+               TEXT("¡¡¥¡¥¢¥£¥¤¥¥¥¦¥§¥¨¥©¥ª¥«¥¬¥­¥®¥¯")
+               TEXT("¥°¥±¥²¥³¥´¥µ¥¶¥·¥¸¥¹¥º¥»¥¼¥½¥¾¥¿")
+               TEXT("¥À¥Á¥Â¥Ã¥Ä¥Å¥Æ¥Ç¥È¥É¥Ê¥Ë¥Ì¥Í¥Î¥Ï")
+               TEXT("¥Ð¥Ñ¥Ò¥Ó¥Ô¥Õ¥Ö¥×¥Ø¥Ù¥Ú¥Û¥Ü¥Ý¥Þ¥ß")
+               TEXT("¥à¥á¥â¥ã¥ä¥å¥æ¥ç¥è¥é¥ê¥ë¥ì¥í¥î¥ï")
+               TEXT("¥ð¥ñ¥ò¥ó¥ô¥õ¥ö¡³¡´¡¼¡£¡Ö¡×¡¢¡¦¡¡");
+       
+#ifdef _UNICODE
+       lpszDst[0] = acKatakanaTable[wCode];
+
+       return 1UL;
+#else
+       lpszDst[0] = acKatakanaTable[wCode * 2U + 0U];
+       lpszDst[1] = acKatakanaTable[wCode * 2U + 1U];
+
+       return 2UL;
+#endif
+}
+
+const DWORD PutJisKatakanaChar(TCHAR *lpszDst, const WORD wCode)
+{
+       // JIS¥«¥¿¥«¥Êʸ»ú¥³¡¼¥ÉÊÑ´¹
+       static const TCHAR *acJisKatakanaTable = 
+               TEXT("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡")
+               TEXT("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡")
+               TEXT("¡¡¡£¡Ö¡×¡¢¡¦¥ò¥¡¥£¥¥¥§¥©¥ã¥å¥ç¥Ã")
+               TEXT("¡¼¥¢¥¤¥¦¥¨¥ª¥«¥­¥¯¥±¥³¥µ¥·¥¹¥»¥½")
+               TEXT("¥¿¥Á¥Ä¥Æ¥È¥Ê¥Ë¥Ì¥Í¥Î¥Ï¥Ò¥Õ¥Ø¥Û¥Þ")
+               TEXT("¥ß¥à¥á¥â¥ä¥æ¥è¥é¥ê¥ë¥ì¥í¥ï¥ó¡«¡¬")
+               TEXT("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡")
+               TEXT("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡");
+       
+#ifdef _UNICODE
+       lpszDst[0] = acJisKatakanaTable[wCode];
+
+       return 1UL;
+#else
+       lpszDst[0] = acJisKatakanaTable[wCode * 2U + 0U];
+       lpszDst[1] = acJisKatakanaTable[wCode * 2U + 1U];
+
+       return 2UL;
+#endif
+}
+
+const DWORD PutSymbolsChar(TCHAR *lpszDst, const WORD wCode)
+{
+       // Äɲå·¥ó¥Ü¥ëʸ»ú¥³¡¼¥ÉÊÑ´¹(¤È¤ê¤¢¤¨¤ºÉ¬Íפ½¤¦¤Ê¤â¤Î¤À¤±)
+       static const TCHAR *aszSymbolsTable1[] =
+               {
+                       _T("[HV]"),             _T("[SD]"),             _T("[£Ð]"),             _T("[£×]"),             _T("[MV]"),             _T("[¼ê]"),             _T("[»ú]"),             _T("[ÁÐ]"),                     // 0x7A50 - 0x7A57      90/48 - 90/55
+                       _T("[¥Ç]"),             _T("[£Ó]"),             _T("[Æó]"),             _T("[¿]"),             _T("[²ò]"),             _T("[SS]"),             _T("[£Â]"),             _T("[£Î]"),                     // 0x7A58 - 0x7A5F      90/56 - 90/63
+                       _T("¢£"),               _T("¡ü"),               _T("[Å·]"),             _T("[¸ò]"),             _T("[±Ç]"),             _T("[̵]"),             _T("[ÎÁ]"),             _T("[ǯÎðÀ©¸Â]"),       // 0x7A60 - 0x7A67      90/64 - 90/71
+                       _T("[Á°]"),             _T("[¸å]"),             _T("[ºÆ]"),             _T("[¿·]"),             _T("[½é]"),             _T("[½ª]"),             _T("[À¸]"),             _T("[ÈÎ]"),                     // 0x7A68 - 0x7A6F      90/72 - 90/79
+                       _T("[À¼]"),             _T("[¿á]"),             _T("[PPV]"),    _T("(Èë)"),             _T("¤Û¤«")                                                                                                                      // 0x7A70 - 0x7A74      90/80 - 90/84
+               };
+
+       static const TCHAR *aszSymbolsTable2[] =
+               {
+                       _T("¢ª"),               _T("¢«"),               _T("¢¬"),               _T("¢­"),               _T("¡ü"),               _T("¡û"),               _T("ǯ"),               _T("·î"),                       // 0x7C21 - 0x7C28      92/01 - 92/08
+                       _T("Æü"),               _T("±ß"),               _T("­Ö"),               _T("ΩÊý£í"),   _T("­Ñ"),               _T("Ê¿Êý­Ñ"),   _T("ΩÊý­Ñ"),   _T("£°."),                      // 0x7C29 - 0x7C30      92/09 - 92/16
+                       _T("£±."),              _T("£²."),              _T("£³."),              _T("£´."),              _T("£µ."),              _T("£¶."),              _T("£·."),              _T("£¸."),                      // 0x7C31 - 0x7C38      92/17 - 92/24
+                       _T("£¹."),              _T("»á"),               _T("Éû"),               _T("¸µ"),               _T("¸Î"),               _T("Á°"),               _T("¿·"),               _T("£°,"),                      // 0x7C39 - 0x7C40      92/25 - 92/32
+                       _T("£±,"),              _T("£²,"),              _T("£³,"),              _T("£´,"),              _T("£µ,"),              _T("£¶,"),              _T("£·,"),              _T("£¸,"),                      // 0x7C41 - 0x7C48      92/33 - 92/40
+                       _T("£¹,"),              _T("(¼Ò)"),             _T("(ºâ)"),             _T("(Í­)"),             _T("(³ô)"),             _T("(Âå)"),             _T("(Ìä)"),             _T("¡ä"),                       // 0x7C49 - 0x7C50      92/41 - 92/48
+                       _T("¡ã"),               _T("¡Ú"),               _T("¡Û"),               _T("¡þ"),               _T("^2"),               _T("^3"),               _T("(CD)"),             _T("(vn)"),                     // 0x7C51 - 0x7C58      92/49 - 92/56
+                       _T("(ob)"),             _T("(cb)"),             _T("(ce"),              _T("mb)"),              _T("(hp)"),             _T("(br)"),             _T("(p)"),              _T("(s)"),                      // 0x7C59 - 0x7C60      92/57 - 92/64
+                       _T("(ms)"),             _T("(t)"),              _T("(bs)"),             _T("(b)"),              _T("(tb)"),             _T("(tp)"),             _T("(ds)"),             _T("(ag)"),                     // 0x7C61 - 0x7C68      92/65 - 92/72
+                       _T("(eg)"),             _T("(vo)"),             _T("(fl)"),             _T("(ke"),              _T("y)"),               _T("(sa"),              _T("x)"),               _T("(sy"),                      // 0x7C69 - 0x7C70      92/73 - 92/80
+                       _T("n)"),               _T("(or"),              _T("g)"),               _T("(pe"),              _T("r)"),               _T("(R)"),              _T("(C)"),              _T("(ä·)"),                     // 0x7C71 - 0x7C78      92/81 - 92/88
+                       _T("DJ"),               _T("[±é]"),             _T("Fax")                                                                                                                                                                                       // 0x7C79 - 0x7C7B      92/89 - 92/91
+               };
+
+       static const TCHAR *aszSymbolsTable3[] =
+               {
+                       _T("(·î)"),             _T("(²Ð)"),             _T("(¿å)"),             _T("(ÌÚ)"),             _T("(¶â)"),             _T("(ÅÚ)"),             _T("(Æü)"),             _T("(½Ë)"),                     // 0x7D21 - 0x7D28      93/01 - 93/08
+                       _T("­í"),               _T("­î"),               _T("­ï"),               _T("­ß"),               _T("­â"),               _T("­ä"),               _T("(¢©)"),             _T("¡û"),                       // 0x7D29 - 0x7D30      93/09 - 93/16
+                       _T("¡ÌËÜ¡Í"),   _T("¡Ì»°¡Í"),   _T("¡ÌÆó¡Í"),   _T("¡Ì°Â¡Í"),   _T("¡ÌÅÀ¡Í"),   _T("¡ÌÂÇ¡Í"),   _T("¡ÌÅð¡Í"),   _T("¡Ì¾¡¡Í"),           // 0x7D31 - 0x7D38      93/17 - 93/24
+                       _T("¡ÌÇÔ¡Í"),   _T("¡Ì£Ó¡Í"),   _T("¡ÎÅê¡Ï"),   _T("¡ÎÊá¡Ï"),   _T("¡Î°ì¡Ï"),   _T("¡ÎÆó¡Ï"),   _T("¡Î»°¡Ï"),   _T("¡ÎÍ·¡Ï"),           // 0x7D39 - 0x7D40      93/25 - 93/32
+                       _T("¡Îº¸¡Ï"),   _T("¡ÎÃæ¡Ï"),   _T("¡Î±¦¡Ï"),   _T("¡Î»Ø¡Ï"),   _T("¡ÎÁö¡Ï"),   _T("¡ÎÂÇ¡Ï"),   _T("­È"),               _T("­Ô"),                       // 0x7D41 - 0x7D48      93/33 - 93/40
+                       _T("Hz"),               _T("ha"),               _T("km"),               _T("Ê¿Êýkm"),   _T("hPa"),              _T("¡¦"),               _T("¡¦"),               _T("1/2"),                      // 0x7D49 - 0x7D50      93/41 - 93/48
+                       _T("0/3"),              _T("1/3"),              _T("2/3"),              _T("1/4"),              _T("3/4"),              _T("1/5"),              _T("2/5"),              _T("3/5"),                      // 0x7D51 - 0x7D58      93/49 - 93/56
+                       _T("4/5"),              _T("1/6"),              _T("5/6"),              _T("1/7"),              _T("1/8"),              _T("1/9"),              _T("1/10"),             _T("À²¤ì"),                     // 0x7D59 - 0x7D60      93/57 - 93/64
+                       _T("ÆÞ¤ê"),             _T("±«"),               _T("Àã"),               _T("¢¤"),               _T("¢¥"),               _T("¢¦"),               _T("¢§"),               _T("¢¡"),                       // 0x7D61 - 0x7D68      93/65 - 93/72
+                       _T("¡¦"),               _T("¡¦"),               _T("¡¦"),               _T("¡þ"),               _T("¡ý"),               _T("!!"),               _T("!?"),               _T("ÆÞ/À²"),            // 0x7D69 - 0x7D70      93/73 - 93/80
+                       _T("±«"),               _T("±«"),               _T("Àã"),               _T("ÂçÀã"),             _T("Íë"),               _T("Í뱫"),             _T("¡¡"),               _T("¡¦"),                       // 0x7D71 - 0x7D78      93/81 - 93/88
+                       _T("¡¦"),               _T("¢ö"),               _T("­ä")                                                                                                                                                                                        // 0x7D79 - 0x7D7B      93/89 - 93/91
+               };
+
+       static const TCHAR *aszSymbolsTable4[] =
+               {
+                       _T("­µ"),               _T("­¶"),               _T("­·"),               _T("­¸"),               _T("­¹"),               _T("­º"),               _T("­»"),               _T("­¼"),                       // 0x7E21 - 0x7E28      94/01 - 94/08
+                       _T("­½"),               _T("­¾"),               _T("XI"),               _T("X­¶"),              _T("­±"),               _T("­²"),               _T("­³"),               _T("­´"),                       // 0x7E29 - 0x7E30      94/09 - 94/16
+                       _T("(1)"),              _T("(2)"),              _T("(3)"),              _T("(4)"),              _T("(5)"),              _T("(6)"),              _T("(7)"),              _T("(8)"),                      // 0x7E31 - 0x7E38      94/17 - 94/24
+                       _T("(9)"),              _T("(10)"),             _T("(11)"),             _T("(12)"),             _T("(21)"),             _T("(22)"),             _T("(23)"),             _T("(24)"),                     // 0x7E39 - 0x7E40      94/25 - 94/32
+                       _T("(A)"),              _T("(B)"),              _T("(C)"),              _T("(D)"),              _T("(E)"),              _T("(F)"),              _T("(G)"),              _T("(H)"),                      // 0x7E41 - 0x7E48      94/33 - 94/40
+                       _T("(I)"),              _T("(J)"),              _T("(K)"),              _T("(L)"),              _T("(M)"),              _T("(N)"),              _T("(O)"),              _T("(P)"),                      // 0x7E49 - 0x7E50      94/41 - 94/48
+                       _T("(Q)"),              _T("(R)"),              _T("(S)"),              _T("(T)"),              _T("(U)"),              _T("(V)"),              _T("(W)"),              _T("(X)"),                      // 0x7E51 - 0x7E58      94/49 - 94/56
+                       _T("(Y)"),              _T("(Z)"),              _T("(25)"),             _T("(26)"),             _T("(27)"),             _T("(28)"),             _T("(29)"),             _T("(30)"),                     // 0x7E59 - 0x7E60      94/57 - 94/64
+                       _T("­¡"),               _T("­¢"),               _T("­£"),               _T("­¤"),               _T("­¥"),               _T("­¦"),               _T("­§"),               _T("­¨"),                       // 0x7E61 - 0x7E68      94/65 - 94/72
+                       _T("­©"),               _T("­ª"),               _T("­«"),               _T("­¬"),               _T("­­"),               _T("­®"),               _T("­¯"),               _T("­°"),                       // 0x7E69 - 0x7E70      94/73 - 94/80
+                       _T("­¡"),               _T("­¢"),               _T("­£"),               _T("­¤"),               _T("­¥"),               _T("­¦"),               _T("­§"),               _T("­¨"),                       // 0x7E71 - 0x7E78      94/81 - 94/88
+                       _T("­©"),               _T("­ª"),               _T("­«"),               _T("­¬"),               _T("(31)")                                                                                                                      // 0x7E79 - 0x7E7D      94/89 - 94/93
+               };
+
+       // ¥·¥ó¥Ü¥ë¤òÊÑ´¹¤¹¤ë
+       if((wCode >= 0x7A50U) && (wCode <= 0x7A74U)){
+               strcpy(lpszDst, aszSymbolsTable1[wCode - 0x7A50U]);
+       }
+       else if((wCode >= 0x7C21U) && (wCode <= 0x7C7BU)){
+               strcpy(lpszDst, aszSymbolsTable2[wCode - 0x7C21U]);
+       }
+       else if((wCode >= 0x7D21U) && (wCode <= 0x7D7BU)){
+               strcpy(lpszDst, aszSymbolsTable3[wCode - 0x7D21U]);
+       }
+       else if((wCode >= 0x7E21U) && (wCode <= 0x7E7DU)){
+               strcpy(lpszDst, aszSymbolsTable4[wCode - 0x7E21U]);
+       }
+       else{
+               strcpy(lpszDst, TEXT("¡¦"));
+       }
+
+       return strlen(lpszDst);
+}
+
+void ProcessEscapeSeq(const BYTE byCode)
+{
+       // ¥¨¥¹¥±¡¼¥×¥·¡¼¥±¥ó¥¹½èÍý
+       switch(m_byEscSeqCount){
+               // 1¥Ð¥¤¥ÈÌÜ
+       case 1U :
+               switch(byCode){
+                       // Invocation of code elements
+               case 0x6EU      : LockingShiftGL(2U);   m_byEscSeqCount = 0U;   return;         // LS2
+               case 0x6FU      : LockingShiftGL(3U);   m_byEscSeqCount = 0U;   return;         // LS3
+               case 0x7EU      : LockingShiftGR(1U);   m_byEscSeqCount = 0U;   return;         // LS1R
+               case 0x7DU      : LockingShiftGR(2U);   m_byEscSeqCount = 0U;   return;         // LS2R
+               case 0x7CU      : LockingShiftGR(3U);   m_byEscSeqCount = 0U;   return;         // LS3R
+
+                       // Designation of graphic sets
+               case 0x24U      :       
+               case 0x28U      : m_byEscSeqIndex = 0U;         break;
+               case 0x29U      : m_byEscSeqIndex = 1U;         break;
+               case 0x2AU      : m_byEscSeqIndex = 2U;         break;
+               case 0x2BU      : m_byEscSeqIndex = 3U;         break;
+               default         : m_byEscSeqCount = 0U;         return;         // ¥¨¥é¡¼
+               }
+               break;
+
+               // 2¥Ð¥¤¥ÈÌÜ
+       case 2U :
+               if(DesignationGSET(m_byEscSeqIndex, byCode)){
+                       m_byEscSeqCount = 0U;
+                       return;
+               }
+                       
+               switch(byCode){
+               case 0x20       : m_bIsEscSeqDrcs = true;       break;
+               case 0x28       : m_bIsEscSeqDrcs = true;       m_byEscSeqIndex = 0U;   break;
+               case 0x29       : m_bIsEscSeqDrcs = false;      m_byEscSeqIndex = 1U;   break;
+               case 0x2A       : m_bIsEscSeqDrcs = false;      m_byEscSeqIndex = 2U;   break;
+               case 0x2B       : m_bIsEscSeqDrcs = false;      m_byEscSeqIndex = 3U;   break;
+               default         : m_byEscSeqCount = 0U;         return;         // ¥¨¥é¡¼
+               }
+               break;
+
+               // 3¥Ð¥¤¥ÈÌÜ
+       case 3U :
+               if(!m_bIsEscSeqDrcs){
+                       if(DesignationGSET(m_byEscSeqIndex, byCode)){
+                               m_byEscSeqCount = 0U;
+                               return;
+                       }
+               }
+               else{
+                       if(DesignationDRCS(m_byEscSeqIndex, byCode)){
+                               m_byEscSeqCount = 0U;
+                               return;
+                       }
+               }
+
+               if(byCode == 0x20U){
+                       m_bIsEscSeqDrcs = true;
+               }
+               else{
+                       // ¥¨¥é¡¼
+                       m_byEscSeqCount = 0U;
+                       return;
+               }
+               break;
+
+               // 4¥Ð¥¤¥ÈÌÜ
+       case 4U :
+               DesignationDRCS(m_byEscSeqIndex, byCode);
+               m_byEscSeqCount = 0U;
+               return;
+       }
+
+       m_byEscSeqCount++;
+}
+
+void LockingShiftGL(const BYTE byIndexG)
+{
+       // LSx
+       m_pLockingGL = &m_CodeG[byIndexG];
+}
+
+void LockingShiftGR(const BYTE byIndexG)
+{
+       // LSxR
+       m_pLockingGR = &m_CodeG[byIndexG];
+}
+
+void SingleShiftGL(const BYTE byIndexG)
+{
+       // SSx
+       m_pSingleGL  = &m_CodeG[byIndexG];
+}
+
+const bool DesignationGSET(const BYTE byIndexG, const BYTE byCode)
+{
+       // G¤Î¥°¥é¥Õ¥£¥Ã¥¯¥»¥Ã¥È¤ò³ä¤êÅö¤Æ¤ë
+       switch(byCode){
+       case 0x42U      : m_CodeG[byIndexG] = CODE_KANJI;                               return true;    // Kanji
+       case 0x4AU      : m_CodeG[byIndexG] = CODE_ALPHANUMERIC;                return true;    // Alphanumeric
+       case 0x30U      : m_CodeG[byIndexG] = CODE_HIRAGANA;                    return true;    // Hiragana
+       case 0x31U      : m_CodeG[byIndexG] = CODE_KATAKANA;                    return true;    // Katakana
+       case 0x32U      : m_CodeG[byIndexG] = CODE_MOSAIC_A;                    return true;    // Mosaic A
+       case 0x33U      : m_CodeG[byIndexG] = CODE_MOSAIC_B;                    return true;    // Mosaic B
+       case 0x34U      : m_CodeG[byIndexG] = CODE_MOSAIC_C;                    return true;    // Mosaic C
+       case 0x35U      : m_CodeG[byIndexG] = CODE_MOSAIC_D;                    return true;    // Mosaic D
+       case 0x36U      : m_CodeG[byIndexG] = CODE_PROP_ALPHANUMERIC;   return true;    // Proportional Alphanumeric
+       case 0x37U      : m_CodeG[byIndexG] = CODE_PROP_HIRAGANA;               return true;    // Proportional Hiragana
+       case 0x38U      : m_CodeG[byIndexG] = CODE_PROP_KATAKANA;               return true;    // Proportional Katakana
+       case 0x49U      : m_CodeG[byIndexG] = CODE_JIS_X0201_KATAKANA;  return true;    // JIS X 0201 Katakana
+       case 0x39U      : m_CodeG[byIndexG] = CODE_JIS_KANJI_PLANE_1;   return true;    // JIS compatible Kanji Plane 1
+       case 0x3AU      : m_CodeG[byIndexG] = CODE_JIS_KANJI_PLANE_2;   return true;    // JIS compatible Kanji Plane 2
+       case 0x3BU      : m_CodeG[byIndexG] = CODE_ADDITIONAL_SYMBOLS;  return true;    // Additional symbols
+       default         : return false;         // ÉÔÌÀ¤Ê¥°¥é¥Õ¥£¥Ã¥¯¥»¥Ã¥È
+       }
+}
+
+const bool DesignationDRCS(const BYTE byIndexG, const BYTE byCode)
+{
+       // DRCS¤Î¥°¥é¥Õ¥£¥Ã¥¯¥»¥Ã¥È¤ò³ä¤êÅö¤Æ¤ë
+       switch(byCode){
+       case 0x40U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-0
+       case 0x41U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-1
+       case 0x42U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-2
+       case 0x43U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-3
+       case 0x44U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-4
+       case 0x45U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-5
+       case 0x46U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-6
+       case 0x47U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-7
+       case 0x48U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-8
+       case 0x49U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-9
+       case 0x4AU      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-10
+       case 0x4BU      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-11
+       case 0x4CU      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-12
+       case 0x4DU      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-13
+       case 0x4EU      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-14
+       case 0x4FU      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // DRCS-15
+       case 0x70U      : m_CodeG[byIndexG] = CODE_UNKNOWN;                             return true;    // Macro
+       default         : return false;         // ÉÔÌÀ¤Ê¥°¥é¥Õ¥£¥Ã¥¯¥»¥Ã¥È
+       }
+}
+
+WORD convertjis(DWORD jiscode) {
+       char code[3];
+       char xcode[4];
+       iconv_t cd;
+  
+       size_t inbyte = 2;
+       size_t outbyte = 4;
+
+       const char *fptr;
+       char *tptr;
+
+       WORD rtn;
+
+       code[0] = jiscode >> 8;
+       code[1] = jiscode & 0xFF;
+       code[3] = '\0';
+
+       /*
+         cd = iconv_open("ISO-2022-JP","UTF-8");
+
+         fptr = code;
+         tptr = xcode;
+         iconv(cd, &fptr, &inbyte, &tptr, &outbyte);
+
+         iconv_close(cd);
+       */
+
+       xcode[0] = code[0] | 0x80;
+       xcode[1] = code[1] | 0x80;
+
+       rtn = ((xcode[0] << 8) & 0xFF00) | (xcode[1] & 0xFF);
+
+       return rtn;
+
+}
diff --git a/dist/trunk/tstools/epgdump/aribstr.h b/dist/trunk/tstools/epgdump/aribstr.h
new file mode 100755 (executable)
index 0000000..6178525
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef ARIBSTR_H
+#define ARIBSTR_H 1
+
+#ifdef __cplusplus
+extern "C"{
+#endif /* __cplusplus */
+
+       int AribToString(char *lpszDst, const char *pSrcData, const int dwSrcLen);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/dist/trunk/tstools/epgdump/eit.c b/dist/trunk/tstools/epgdump/eit.c
new file mode 100755 (executable)
index 0000000..4409434
--- /dev/null
@@ -0,0 +1,678 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "eit.h"
+
+char           *subtitle_cnv_str[] = {
+//     "¡¡Âè",
+//     "¡¼Âè",
+//     "-Âè",
+//     " Âè",
+//     "¡¡¡Ö",
+//     "¡¡¡ô",
+//     "¡Ê",
+//     "¡Ö",
+       NULL
+};
+static void timecmp(int *,int *,int *,
+                                       int, int, int);
+
+int parseEIThead(unsigned char *data, EIThead *h) {
+       int boff = 0;
+
+       memset(h, 0, sizeof(EIThead));
+
+       h->table_id = getBit(data, &boff, 8);
+       h->section_syntax_indicator = getBit(data, &boff, 1);
+       h->reserved_future_use = getBit(data, &boff, 1);
+       h->reserved1 = getBit(data, &boff, 2);
+       h->section_length =getBit(data, &boff,12);
+       h->service_id = getBit(data, &boff, 16);
+       h->reserved2 = getBit(data, &boff, 2);
+       h->version_number = getBit(data, &boff, 5);
+       h->current_next_indicator = getBit(data, &boff, 1);
+       h->section_number = getBit(data, &boff, 8);
+       h->last_section_number = getBit(data, &boff, 8);
+       h->transport_stream_id = getBit(data, &boff, 16);
+       h->original_network_id = getBit(data, &boff, 16);
+       h->segment_last_section_number = getBit(data, &boff, 8);
+       h->last_table_id = getBit(data, &boff, 8);
+  
+       return 14;
+}
+
+int parseEITbody(unsigned char *data, EITbody *b)
+{
+       int boff = 0;
+       int tnum;
+       char buf[4];
+
+       memset(b, 0, sizeof(EITbody));
+
+       b->event_id = getBit(data, &boff, 16);
+
+       memcpy(b->start_time, data + boff / 8, 5);
+       /* b->start_time = getBit(data, &boff, 40); */
+       boff += 40;
+       memcpy(b->duration, data + boff / 8, 3);
+       /* b->duration = getBit(data, &boff, 24); */
+       boff += 24;
+       b->running_status = getBit(data, &boff, 3);
+       b->free_CA_mode = getBit(data, &boff, 1);
+       b->descriptors_loop_length = getBit(data, &boff, 12);
+
+       /* ÆüÉÕÊÑ´¹ */
+       tnum = (b->start_time[0] & 0xFF) << 8 | (b->start_time[1] & 0xFF);
+  
+       b->yy = (tnum - 15078.2) / 365.25;
+       b->mm = ((tnum - 14956.1) - (int)(b->yy * 365.25)) / 30.6001;
+       b->dd = (tnum - 14956) - (int)(b->yy * 365.25) - (int)(b->mm * 30.6001);
+
+       if(b->dd == 0) {
+               printf("aa");
+       }
+
+       if(b->mm == 14 || b->mm == 15) {
+               b->yy += 1;
+               b->mm = b->mm - 1 - (1 * 12);
+       } else {
+               b->mm = b->mm - 1;
+       }
+
+       b->yy += 1900;
+  
+       memset(buf, '\0', sizeof(buf));
+       sprintf(buf, "%x", b->start_time[2]);
+       b->hh = atoi(buf);
+       memset(buf, '\0', sizeof(buf));
+       sprintf(buf, "%x", b->start_time[3]);
+       b->hm = atoi(buf);
+       memset(buf, '\0', sizeof(buf));
+       sprintf(buf, "%x", b->start_time[4]);
+       b->ss = atoi(buf);
+
+       if((b->duration[0] == 0xFF) && (b->duration[1] == 0xFF) && (b->duration[2] == 0xFF)){
+               b->dhh = b->dhm = b->dss = 0;
+       }else{
+               memset(buf, '\0', sizeof(buf));
+       sprintf(buf, "%x", b->duration[0]);
+       b->dhh = atoi(buf);
+               memset(buf, '\0', sizeof(buf));
+       sprintf(buf, "%x", b->duration[1]);
+       b->dhm = atoi(buf);
+               memset(buf, '\0', sizeof(buf));
+       sprintf(buf, "%x", b->duration[2]);
+       b->dss = atoi(buf);
+       }
+       return 12;
+}
+
+int parseSEVTdesc(unsigned char *data, SEVTdesc *desc) {
+       int boff = 0;
+  
+       memset(desc, 0, sizeof(SEVTdesc));
+
+       desc->descriptor_tag = getBit(data, &boff, 8);
+       if((desc->descriptor_tag & 0xFF) != 0x4D) {
+               return -1;
+       }
+       desc->descriptor_length = getBit(data, &boff, 8);
+       memcpy(desc->ISO_639_language_code, data + boff / 8, 3);
+       /* desc->ISO_639_language_code = getBit(data, &boff, 24); */
+       boff += 24;
+       desc->event_name_length = getBit(data, &boff, 8);
+       getStr(desc->event_name, data, &boff, desc->event_name_length);
+       desc->text_length = getBit(data, &boff, 8);
+       getStr(desc->text, data, &boff, desc->text_length);
+
+       return desc->descriptor_length + 2;
+}
+
+int parseContentDesc(unsigned char *data, ContentDesc *desc) {
+       int boff = 0;
+  
+       memset(desc, 0, sizeof(ContentDesc));
+
+       desc->descriptor_tag = getBit(data, &boff, 8);
+       if((desc->descriptor_tag & 0xFF) != 0x54) {
+               return -1;
+       }
+       desc->descriptor_length = getBit(data, &boff, 8);
+       memcpy(desc->content, data+(boff/8), desc->descriptor_length);
+       //getStr(desc->content, data, &boff, desc->descriptor_length);
+       return desc->descriptor_length + 2;
+}
+
+int parseSeriesDesc(unsigned char *data, SeriesDesc *desc) {
+       int boff = 0;
+  
+       memset(desc, 0, sizeof(SeriesDesc));
+
+       desc->descriptor_tag = getBit(data, &boff, 8);
+       if((desc->descriptor_tag & 0xFF) != 0xD5) {
+               return -1;
+       }
+       desc->descriptor_length = getBit(data, &boff, 8);
+       desc->series_id = getBit(data, &boff, 16);
+       desc->repeat_label = getBit(data, &boff, 4);
+       desc->program_pattern = getBit(data, &boff, 3);
+       desc->expire_date_valid_flag = getBit(data, &boff, 1);
+
+       desc->expire_date = getBit(data, &boff, 16);
+       //memcpy(desc->expire_date, data + boff / 8, 2);
+       //boff += 16;
+
+       desc->episode_number = getBit(data, &boff, 12);
+       desc->last_episode_number = getBit(data, &boff, 12);
+
+       getStr(desc->series_name_char, data, &boff, desc->descriptor_length - 8);
+       return desc->descriptor_length + 2;
+}
+
+int parseEEVTDhead(unsigned char *data, EEVTDhead *desc) {
+       int boff = 0;
+  
+       memset(desc, 0, sizeof(EEVTDhead));
+
+       desc->descriptor_tag = getBit(data, &boff, 8);
+       if((desc->descriptor_tag & 0xFF) != 0x4E) {
+               return -1;
+       }
+       desc->descriptor_length = getBit(data, &boff, 8);
+       desc->descriptor_number = getBit(data, &boff, 4);
+       desc->last_descriptor_number = getBit(data, &boff, 4);
+       memcpy(desc->ISO_639_language_code, data + boff / 8, 3);
+       /* desc->ISO_639_language_code = getBit(data, &boff, 24); */
+       boff += 24;
+
+       desc->length_of_items = getBit(data, &boff, 8);
+
+       return 7;
+}
+
+int parseEEVTDitem(unsigned char *data, EEVTDitem *desc) {
+       int boff = 0;
+  
+       memset(desc, 0, sizeof(EEVTDitem));
+
+       desc->item_description_length = getBit(data, &boff, 8);
+       getStr(desc->item_description, data, &boff, desc->item_description_length);
+
+       desc->item_length = getBit(data, &boff, 8);
+//     memcpy(desc->item, data + (boff / 8), desc->item_length);
+       getStr(desc->item, data, &boff, desc->item_length);
+
+       return desc->item_description_length + desc->item_length + 2;
+}
+
+int parseEEVTDtail(unsigned char *data, EEVTDtail *desc) {
+       int boff = 0;
+  
+       memset(desc, 0, sizeof(EEVTDtail));
+
+       desc->text_length = getBit(data, &boff, 8);
+       getStr(desc->text, data, &boff, desc->text_length);
+
+       return desc->text_length + 1;
+}
+
+int checkEEVTDitem(EEVTDitem *save, EEVTDitem *new, int descriptor_number) {
+
+       EEVTDitem swap;
+       int boff = 0;
+       if(new == NULL) {
+               if(save->item_length != 0) {
+                       swap = *save;
+                       getStr(save->item, (unsigned char*)swap.item, &boff, swap.item_length);
+
+
+                        //save->descriptor_number = descriptor_number;
+                        //*new = swap;
+                       //*save = swap;
+                        if (swap.descriptor_number==1){
+//                            printf("descriptor_num %d   typeB\n",swap.descriptor_number);
+                        }
+
+                       return 1;
+               } else {
+
+
+                        //printf("descriptor_num %d   typeC\n",swap.descriptor_number);
+
+
+
+                       return 0;
+               }
+       }
+
+       if(new->item_description_length == 0) {
+               /* Â³¤­ Êݸ */
+               memcpy(save->item + save->item_length, new->item, new->item_length);
+               save->item_length += new->item_length;
+
+
+                if (swap.descriptor_number==1){
+                            printf("descriptor_num %d   typeD\n",swap.descriptor_number);
+                        }
+
+
+               return 0;
+       } else {
+               /* ¥Ö¥ì¡¼¥¯¡£save¤ò°õºþÂоݤˤ¹¤ë¡£save¤ò¥¯¥ê¥¢? */
+               if(save->item_length != 0) {
+                       /* ÂàÈòºÑ¤ß¤¬¤¢¤ê */
+                       swap = *save;
+                       getStr(save->item, (unsigned char*)swap.item, &boff, swap.item_length);
+                       swap = *new;
+                       *new = *save;
+                       *save = swap;
+                       save->descriptor_number = descriptor_number;
+                       
+
+
+
+                        if (swap.descriptor_number==1){
+                            printf("descriptor_num %d   typeE\n",swap.descriptor_number);
+                        }
+                        
+
+               } else {
+                       *save = *new;
+                       save->descriptor_number = descriptor_number;
+
+                        if (swap.descriptor_number==1){
+                            printf("descriptor_num %d   typeF\n",swap.descriptor_number);
+                        }
+
+
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+EIT_CONTROL    *searcheit(EIT_CONTROL *top, int servid, int eventid)
+{
+       EIT_CONTROL     *cur ;
+       cur = top ;
+
+       while(cur != NULL){
+               if((cur->event_id == eventid) && (cur->servid == servid)){
+                       return cur ;
+               }
+
+               cur = cur->next ;
+       }
+       return NULL ;
+}
+void   conv_title_subtitle(EIT_CONTROL *eitptr)
+{
+       int             lp = 0 ;
+       size_t  addsize ;
+       char    *ptr ;
+       char    *newsubtitle ;
+
+       for(lp = 0 ; subtitle_cnv_str[lp] != NULL ; lp++){
+               ptr = strstr(eitptr->title, subtitle_cnv_str[lp]);
+               if(ptr == NULL){
+                       continue ;
+               }
+               // ¥¿¥¤¥È¥ë¤¬¤Ê¤¯¤Ê¤é¤Ê¤¤¤è¤¦¤Ë
+               if(ptr == eitptr->title){
+                       continue ;
+               }
+               newsubtitle = calloc(1, ((strlen(ptr) + 1) + (strlen(eitptr->subtitle) + 1)));
+               memcpy(newsubtitle, ptr, strlen(ptr));
+               newsubtitle[strlen(ptr)] = ' ';
+               *ptr = NULL ;
+               strcat(newsubtitle, eitptr->subtitle);
+               free(eitptr->subtitle);
+               eitptr->subtitle = newsubtitle ;
+               return ;
+       }
+}
+void   enqueue(EIT_CONTROL *top, EIT_CONTROL *eitptr)
+{
+       EIT_CONTROL     *cur ;
+       cur = top ;
+       int             rc ;
+
+       if(top->next == NULL){
+               top->next = eitptr ;
+               eitptr->prev = top ;
+               return ;
+       }
+       cur = top->next ;
+       while(cur != NULL){
+               rc = memcmp(&cur->yy, &eitptr->yy, (sizeof(int) * 3));
+               if(rc == 0){
+                       rc = memcmp(&cur->hh, &eitptr->hh, (sizeof(int) * 3));
+                       if(rc == 0){
+                               free(eitptr->title);
+                               free(eitptr->subtitle);
+                               free(eitptr);
+                               return ;
+                       }
+                       if(rc > 0){
+                               if(cur->prev != 0){
+                                       cur->prev->next = eitptr ;
+                                       eitptr->prev = cur->prev ;
+                               }
+                               cur->prev = eitptr ;
+                               eitptr->next = cur ;
+                               conv_title_subtitle(eitptr);
+                               return ;
+                       }
+               }
+               if(rc > 0){
+                       if(cur->prev != 0){
+                               cur->prev->next = eitptr ;
+                               eitptr->prev = cur->prev ;
+                       }
+                       cur->prev = eitptr ;
+                       eitptr->next = cur ;
+                       conv_title_subtitle(eitptr);
+                       return ;
+               }
+               if(cur->next == NULL){
+                       cur->next = eitptr ;
+                       eitptr->prev = cur ;
+                       conv_title_subtitle(eitptr);
+                       return ;
+               }
+               cur = cur->next ;
+       }
+       return ;
+
+}
+
+void dumpEIT(unsigned char *ptr, int serv_id, int original_network_id, int transport_stream_id, EIT_CONTROL *eittop)
+{
+
+       EIThead  eith;
+       EITbody  eitb;
+       SEVTdesc sevtd;
+
+       EEVTDhead eevthead;
+       EEVTDitem eevtitem;
+       EEVTDtail eevttail;
+
+       EEVTDitem save_eevtitem;
+
+       EIT_CONTROL     *cur ;
+       EIT_CONTROL     *curtmp ;
+
+       int len = 0;
+       int loop_len = 0;
+       int loop_blen = 0;
+       int loop_elen = 0;
+       int str_alen = 0;
+
+       int ehh, emm, ess;
+
+       /* EIT */
+       len = parseEIThead(ptr, &eith); 
+
+       ptr += len;
+       loop_len = eith.section_length - (len - 3 + 4); // 3¤Ï¶¦Ḁ̈إåÀĹ 4¤ÏCRC
+       while(loop_len > 0) {
+               /* Ï¢Â³¤¹¤ë³ÈÄ¥¥¤¥Ù¥ó¥È¤Ï¡¢´Á»ú¥³¡¼¥É¤¬µã¤­Ê̤줷¤Æ
+                  Ê¬³ä¤µ¤ì¤ë¤è¤¦¤À¡£Ï¢Â³¤«¤É¤¦¤«¤Ï¡¢item_description_length¤¬
+                  ÀßÄꤵ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤ÇȽÃǤǤ­¤ë¤è¤¦¤À¡£ */
+               memset(&save_eevtitem, 0, sizeof(EEVTDitem));
+
+               len = parseEITbody(ptr, &eitb);
+               ptr += len;
+               loop_len -= len;
+    
+               /* printf("evtid:%d\n", eitb.event_id); */
+    
+               loop_blen = eitb.descriptors_loop_length;
+               loop_len -= loop_blen;
+               while(loop_blen > 0) {
+
+/*yukikaze-test*/
+                       //printf("desc_tag");
+                       //int itt=getBit(*ptr,0,8);
+                       //printf("%x",itt);
+
+                       len = parseSEVTdesc(ptr, &sevtd);
+                       if(len > 0) {
+
+                               /*
+                                 if(eith.service_id == 19304 && 
+                                 eitb.event_id == 46564) {
+                                 printf("aa");
+                                 }
+                               */
+
+                               ehh = eitb.hh;
+                               emm = eitb.hm;
+                               ess = eitb.ss;
+                               if(eith.service_id != serv_id){
+                                       ptr += len;
+                                       loop_blen -= len;
+                                       continue ;
+                               }
+
+                               timecmp(&ehh, &emm, &ess,
+                                               eitb.dhh, eitb.dhm, eitb.dss);
+                               cur = searcheit(eittop, eith.service_id, eitb.event_id);
+                               if(cur == NULL){
+                                       curtmp = NULL;
+                                       cur = calloc(1, sizeof(EIT_CONTROL));
+                               }
+                               else {
+                                       curtmp = cur;
+                               }
+                               cur->event_id = eitb.event_id ;
+                               cur->servid = eith.service_id ;
+                               cur->title = calloc(1, (strlen(sevtd.event_name) + 1));
+
+                               memcpy(cur->title, sevtd.event_name, strlen(sevtd.event_name));
+                               cur->subtitle = calloc(1, (strlen(sevtd.text) + 1));
+                               memcpy(cur->subtitle, sevtd.text, strlen(sevtd.text));
+                               cur->yy = eitb.yy;
+                               cur->mm = eitb.mm;
+                               cur->dd = eitb.dd;
+                               cur->hh = eitb.hh;
+                               cur->hm = eitb.hm;
+                               cur->ss = eitb.ss;
+                               cur->ehh = eitb.dhh;
+                               cur->emm = eitb.dhm;
+                               cur->ess = eitb.dss ;
+                               cur->table_id = eith.table_id ;
+                               if ( !curtmp ) enqueue(eittop, cur);
+                       } else {
+                               len = parseEEVTDhead(ptr, &eevthead);
+
+                               /*
+                                 if(eith.service_id == 19304 && 
+                                 eitb.event_id == 46564) {
+                                 printf("aa");
+                                 }
+                               */
+
+                               if(len > 0) {
+                                       ptr += len;
+                                       loop_blen -= len;
+
+                                       loop_elen = eevthead.length_of_items;
+                                       loop_len -= loop_elen;
+                                       while(loop_elen > 0) {
+                                               len = parseEEVTDitem(ptr, &eevtitem);
+
+                                               ptr += len;
+                                               loop_elen -= len;
+                                               loop_blen -= len;
+                                                
+                                               if (1||checkEEVTDitem(&save_eevtitem, &eevtitem,
+                                                                                 eevthead.descriptor_number)) {
+#if 0
+                                                       {
+                                                            if (eevtitem.descriptor_number>0){
+                                                                //printf("descriptor_num %d\n",eevtitem.descriptor_number);
+                                                            }
+
+                                                            /* long format */
+                                                            //printf("descriptor_num %d\n",eevtitem.descriptor_number);
+#if 1
+                                                            printf("EEVT,%d,%d,%d,%s,%s\n",
+                                                                               eith.service_id,
+                                                                                       eitb.event_id,
+                                                                                       eevtitem.descriptor_number, // ÂàÈò¹àÌÜ
+                                                                               eevtitem.item_description,
+                                                                               eevtitem.item);
+#endif
+
+                                                       }
+#endif
+                                                       cur = searcheit(eittop, eith.service_id, eitb.event_id);
+                                                       if(cur == NULL){
+                                                               curtmp = NULL;
+                                                               cur = calloc(1, sizeof(EIT_CONTROL));
+                                                       }
+                                                       else {
+                                                               curtmp = cur;
+                                                       }
+
+#if 1
+                                                       if ( cur->desc ) {
+                                                               str_alen = strlen( cur->desc );
+                                                       }
+                                                       else {
+                                                               str_alen = 0;
+                                                       }
+                                                       eevtitem.item_description_length = strlen(eevtitem.item_description);
+                                                       eevtitem.item_length = strlen(eevtitem.item);
+                                                       cur->desc = realloc(cur->desc, str_alen + eevtitem.item_description_length + eevtitem.item_length + 1000);
+                                                       if ( !str_alen ) *cur->desc = '\0';
+
+                                                       if ( eevtitem.item_description_length && !strstr(cur->desc, eevtitem.item_description) ) {
+                                                               strcat(cur->desc, eevtitem.item_description);
+                                                               strcat(cur->desc, "\t");
+                                                       }
+
+                                                       if ( eevtitem.item_length && !strstr(cur->desc, eevtitem.item)  ) {
+                                                               strcat(cur->desc, eevtitem.item);
+                                                               strcat(cur->desc, "\\n");
+                                                       }
+#endif
+                                                       if ( !curtmp ) enqueue(eittop, cur);
+                                               }
+                                       }
+
+                                       len = parseEEVTDtail(ptr, &eevttail);
+#if 0
+                                       { /* long format */
+                                               printf("EEVTt,%d,%d,%d,%s\n", 
+                                                               eith.service_id,
+                                                               eitb.event_id,
+                                                               eevthead.descriptor_number,
+                                                               eevttail.text);
+                                       }
+#endif
+                               } else {
+                                       ContentDesc contentDesc;
+                                       len = parseContentDesc(ptr, &contentDesc);
+                                       if (len > 0) {
+                                               int header_printed = 0;
+                                               for (int i = 0; i < contentDesc.descriptor_length - 1; i+=2) {
+                                                       /*
+                                                       if (0xff == (unsigned char)contentDesc.content[i])
+                                                               continue;
+                                                       */
+#if 0
+                                                       if (!header_printed) {
+                                                               fprintf(out, "Content,%d,%d",
+                                                                       eith.service_id,
+                                                                       eitb.event_id);
+                                                               header_printed = 1;
+                                                       }
+#endif
+
+#if 0
+                                                       fprintf(out, ",%02x%02x", (unsigned char)contentDesc.content[i], (unsigned char)contentDesc.content[i+1]);
+#endif
+                                               }
+                                               if((eith.original_network_id == original_network_id) && (eith.transport_stream_id == transport_stream_id)){
+                                                       cur = searcheit(eittop, eith.service_id, eitb.event_id);
+                                                       if(cur != NULL){
+                                                               cur->content_type = (unsigned char)(contentDesc.content[0] >> 4);
+#if 0
+                                                               fprintf(stdout, "%s:", cur->title);
+                                                               fprintf(stdout, ",%02x%02x", (unsigned char)contentDesc.content[0], (unsigned char)contentDesc.content[1]);
+                                                               fprintf(stdout, ",%02x%02x\n", (unsigned char)contentDesc.content[2], (unsigned char)contentDesc.content[3]);
+#endif
+
+                                                       }
+#if 0
+                                                       if (header_printed) {
+                                                               fprintf(out, "\n");
+                                                       }
+#endif
+                                               }
+                                       } else {
+                                               SeriesDesc seriesDesc;
+                                               len = parseSeriesDesc(ptr, &seriesDesc);
+                                               if (len > 0) {
+#if 0
+                                                       printf("Series,%d,%d,series=%d,repeat=%01x,pattern=%d,expire_valid=%d,expire=%04x,epinum=%d,lastepinum=%d,%s\n",
+                                                               eith.service_id,
+                                                               eitb.event_id,
+                                                               seriesDesc.series_id,
+                                                               seriesDesc.repeat_label,
+                                                               seriesDesc.program_pattern,
+                                                               seriesDesc.expire_date_valid_flag,
+                                                               seriesDesc.expire_date,
+                                                               seriesDesc.episode_number,
+                                                               seriesDesc.last_episode_number,
+                                                               seriesDesc.series_name_char);
+#endif
+                                               } else {
+                                                       len = parseOTHERdesc(ptr);
+                                               }
+                                       }
+                               }
+                       }
+                       ptr += len;
+                       loop_blen -= len;
+               }
+               /* ºÇ¸å¤Î¥Ö¥ì¡¼¥¯¥Á¥§¥Ã¥¯ */
+    
+               if(checkEEVTDitem(&save_eevtitem, NULL, 0)) {
+#if 0
+                       if(mode == 1) { /* long format */
+                               fprintf(out, "EEVT,%d,%d,%d,%s,%s\n", 
+                                               eith.service_id,
+                                               eitb.event_id,
+                                               save_eevtitem.descriptor_number,
+                                               save_eevtitem.item_description,
+                                               save_eevtitem.item);
+                       }
+#endif
+               }
+       }
+
+       return;
+}
+
+void timecmp(int *thh, int *tmm, int *tss,
+                        int dhh, int dmm, int dss) {
+
+       int ama;
+
+       *tss += dss;
+       ama = *tss % 60;
+       *tmm += (*tss / 60);
+       *tss = ama;
+
+       *tmm += dmm;
+       ama   = *tmm % 60;
+       *thh += (*tmm / 60);
+       *tmm  = ama;
+
+       *thh += dhh;
+
+}
diff --git a/dist/trunk/tstools/epgdump/eit.h b/dist/trunk/tstools/epgdump/eit.h
new file mode 100755 (executable)
index 0000000..15f910b
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef EIT_H
+#define EIT_H 1
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+#include "ts_ctl.h"
+
+typedef struct _EIThead {
+       char table_id;
+       int section_syntax_indicator;
+       int reserved_future_use;
+       int reserved1;
+       int section_length;
+       int service_id;
+       int reserved2;
+       int version_number;
+       int current_next_indicator;
+       int section_number;
+       int last_section_number;
+       int transport_stream_id;
+       int original_network_id;
+       int segment_last_section_number;
+       int last_table_id;
+} EIThead;
+
+typedef struct _EITbody {
+       int event_id;
+       char start_time[5];
+       char duration[3];
+       int running_status;
+       int free_CA_mode;
+       int descriptors_loop_length;
+       /* °Ê²¼¤Ï²òÀÏ·ë²ÌÊݸÍÑ */
+       int yy;
+       int mm;
+       int dd;
+       int hh;
+       int hm;
+       int ss;
+       int dhh;
+       int dhm;
+       int dss;
+} EITbody;
+
+typedef struct _SEVTdesc {
+       int  descriptor_tag;
+       int  descriptor_length;
+       char ISO_639_language_code[3];
+       int  event_name_length;
+       char event_name[MAXSECLEN];
+       int  text_length;
+       char text[MAXSECLEN];
+} SEVTdesc;
+
+typedef struct _ContentDesc {
+       int descriptor_tag;
+       int descriptor_length;
+       char content[MAXSECLEN];
+} ContentDesc;
+
+typedef struct _SeriesDesc {
+       int descriptor_tag;
+       int descriptor_length;
+       int series_id;
+       int repeat_label;
+       int program_pattern;
+       int expire_date_valid_flag;
+       int expire_date;
+       int episode_number;
+       int last_episode_number;
+       char series_name_char[MAXSECLEN];
+} SeriesDesc;
+
+typedef struct _EEVTDhead {
+       int  descriptor_tag;
+       int  descriptor_length;
+       int  descriptor_number;
+       int  last_descriptor_number;
+       char ISO_639_language_code[3];
+       int  length_of_items;
+} EEVTDhead;
+
+typedef struct _EEVTDitem {
+       int  item_description_length;
+       char item_description[MAXSECLEN];
+       int  item_length;
+       char item[MAXSECLEN];
+       /* ÂàÈòÍÑ */
+       int  descriptor_number;
+} EEVTDitem;
+
+typedef struct _EEVTDtail {
+       int  text_length;
+       char text[MAXSECLEN];
+} EEVTDtail;
+
+#ifdef __cplusplus
+extern "C"{
+#endif /* __cplusplus */
+
+       int parseEIThead(unsigned char *data, EIThead *h);
+       int parseEITbody(unsigned char *data, EITbody *b);
+       int parseSEVTdesc(unsigned char *data, SEVTdesc *desc) ;
+
+       int parseContentDesc(unsigned char *data, ContentDesc *desc);
+       int parseSeriesDesc(unsigned char *data, SeriesDesc *desc);
+
+       int parseEEVTDhead(unsigned char *data, EEVTDhead *desc) ;
+       int parseEEVTDitem(unsigned char *data, EEVTDitem *desc) ;
+       int parseEEVTDtail(unsigned char *data, EEVTDtail *desc) ;
+
+       void dumpEIT(unsigned char *data, int serv_id, int original_network_id, int transport_stream_id, EIT_CONTROL *eittop);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/dist/trunk/tstools/epgdump/epgdump.c b/dist/trunk/tstools/epgdump/epgdump.c
new file mode 100755 (executable)
index 0000000..046f2b9
--- /dev/null
@@ -0,0 +1,443 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <iconv.h>
+#include <time.h>
+
+#include "ts.h"
+#include "sdt.h"
+#include "eit.h"
+#include "ts_ctl.h"
+
+typedef                struct  _ContentTYPE{
+       char    *japanese ;
+       char    *english ;
+}CONTENT_TYPE;
+
+#define                CAT_COUNT               16
+static  CONTENT_TYPE   ContentCatList[CAT_COUNT] = {
+       { "¥Ë¥å¡¼¥¹¡¦ÊóÆ»", "news" },
+       { "¥¹¥Ý¡¼¥Ä", "sports" },
+       { "¾ðÊó", "information" },
+       { "¥É¥é¥Þ", "drama" },
+       { "²»³Ú", "music" },
+       { "¥Ð¥é¥¨¥Æ¥£", "variety" },
+       { "±Ç²è", "cinema" },
+       { "¥¢¥Ë¥á¡¦Æû£", "anime" },
+       { "¥É¥­¥å¥á¥ó¥¿¥ê¡¼¡¦¶µÍÜ", "documentary" },
+       { "±é·à", "stage" },
+       { "¼ñÌ£¡¦¼ÂÍÑ", "hobby" },
+       { "Ê¡»ã", "etc" },                      //Ê¡»ã
+       { "ͽÈ÷", "etc" }, //ͽÈ÷
+       { "ͽÈ÷", "etc" }, //ͽÈ÷
+       { "ͽÈ÷", "etc" }, //ͽÈ÷
+       { "¤½¤Î¾", "etc" } //¤½¤Î¾
+};
+
+SVT_CONTROL    *svttop = NULL;
+#define                SECCOUNT        4
+char   title[1024];
+char   subtitle[1024];
+char   desc[102400] = {0};
+char   Category[1024];
+char   ServiceName[1024];
+iconv_t        cd ;
+
+void   xmlspecialchars(char *str)
+{
+       strrep(str, "&", "&amp;");
+       strrep(str, "'", "&apos;");
+       strrep(str, "\"", "&quot;");
+       strrep(str, "<", "&lt;");
+       strrep(str, ">", "&gt;");
+}
+
+
+
+void   GetSDT(FILE *infile, SVT_CONTROL *svttop, SECcache *secs, int count)
+{
+       SECcache  *bsecs;
+
+       while((bsecs = readTS(infile, secs, count)) != NULL) {
+               /* SDT */
+               if((bsecs->pid & 0xFF) == 0x11) {
+                       dumpSDT(bsecs->buf, svttop);
+               }
+       }
+}
+void   GetSDT_chout(FILE *infile, SVT_CONTROL *svttop, SECcache *secs, int count,STATION *station, int * station_count,char *header)
+{
+       SECcache  *bsecs;
+
+       while((bsecs = readTS(infile, secs, count)) != NULL) {
+               /* SDT */
+               if((bsecs->pid & 0xFF) == 0x11) {
+                       dumpSDT_chout(bsecs->buf,svttop,station,station_count,header);
+               }
+       }
+}
+void   GetEIT(FILE *infile, FILE *outfile, STATION *psta, SECcache *secs, int count)
+{
+       SECcache  *bsecs;
+       EIT_CONTROL     *eitcur ;
+       EIT_CONTROL     *eitnext ;
+       EIT_CONTROL     *eittop = NULL;
+       char    *outptr ;
+       char    *inptr ;
+       size_t  ilen;
+       size_t  olen;
+       time_t  l_time ;
+       time_t  end_time ;
+       struct  tm      tl ;
+       struct  tm      *endtl ;
+       char    cendtime[32];
+       char    cstarttime[32];
+
+       eittop = calloc(1, sizeof(EIT_CONTROL));
+       eitcur = eittop ;
+       fseek(infile, 0, SEEK_SET);
+       while((bsecs = readTS(infile, secs, SECCOUNT)) != NULL) {
+               /* EIT */
+               if((bsecs->pid & 0xFF) == 0x12) {
+                       dumpEIT(bsecs->buf, psta->svId, psta->onId, psta->tsId, eittop);
+               }else if((bsecs->pid & 0xFF) == 0x26) {
+                       dumpEIT(bsecs->buf, psta->svId, psta->onId, psta->tsId, eittop);
+               }else if((bsecs->pid & 0xFF) == 0x27) {
+                       dumpEIT(bsecs->buf, psta->svId, psta->onId, psta->tsId, eittop);
+               }
+       }
+       eitcur = eittop ;
+       while(eitcur != NULL){
+               if(!eitcur->servid){
+                       eitcur = eitcur->next ;
+                       continue ;
+               }
+               if(eitcur->content_type > CAT_COUNT){
+                       eitcur->content_type = CAT_COUNT -1 ;
+               }
+               outptr = title ;
+               memset(title, '\0', sizeof(title));
+               ilen = strlen(eitcur->title);
+               olen = sizeof(title);
+               inptr = eitcur->title;
+               iconv(cd, &inptr, &ilen, &outptr, &olen);
+               xmlspecialchars(title);
+
+               memset(subtitle, '\0', sizeof(subtitle));
+               ilen = strlen(eitcur->subtitle);
+               olen = sizeof(subtitle);
+               outptr = subtitle ;
+               inptr = eitcur->subtitle;
+               iconv(cd, &inptr, &ilen, &outptr, &olen);
+               xmlspecialchars(subtitle);
+
+               memset(desc, '\0', sizeof(desc));
+               if ( eitcur->desc ) {
+                       ilen = strlen(eitcur->desc);
+                       olen = sizeof(desc);
+                       outptr = desc ;
+                       inptr = eitcur->desc;
+                       iconv(cd, &inptr, &ilen, &outptr, &olen);
+                       xmlspecialchars(desc);
+               }
+
+               memset(Category, '\0', sizeof(Category));
+               ilen = strlen(ContentCatList[eitcur->content_type].japanese);
+               olen = sizeof(Category);
+               outptr = Category ;
+               inptr = ContentCatList[eitcur->content_type].japanese;
+               iconv(cd, &inptr, &ilen, &outptr, &olen);
+               xmlspecialchars(Category);
+
+               tl.tm_sec = eitcur->ss ;
+               tl.tm_min = eitcur->hm ;
+               tl.tm_hour = eitcur->hh ;
+               tl.tm_mday = eitcur->dd ;
+               tl.tm_mon = (eitcur->mm - 1);
+               tl.tm_year = (eitcur->yy - 1900);
+               tl.tm_wday = 0;
+               tl.tm_isdst = 0;
+               tl.tm_yday = 0;
+               l_time = mktime(&tl);
+               if((eitcur->ehh == 0) && (eitcur->emm == 0) && (eitcur->ess == 0)){
+                       (void)time(&l_time);
+                       end_time = l_time + (60 * 5);           // £µÊ¬¸å¤ËÀßÄê
+               endtl = localtime(&end_time);
+               }else{
+                       end_time = l_time + eitcur->ehh * 3600 + eitcur->emm * 60 + eitcur->ess;
+                       endtl = localtime(&end_time);
+               }
+               memset(cendtime, '\0', sizeof(cendtime));
+               memset(cstarttime, '\0', sizeof(cstarttime));
+               strftime(cendtime, (sizeof(cendtime) - 1), "%Y%m%d%H%M%S", endtl);
+               strftime(cstarttime, (sizeof(cstarttime) - 1), "%Y%m%d%H%M%S", &tl);
+#if 1
+               fprintf(outfile, "  <programme start=\"%s +0900\" stop=\"%s +0900\" channel=\"%s\">\n", 
+                               cstarttime, cendtime, psta->ontv);
+               fprintf(outfile, "    <title lang=\"ja_JP\">%s</title>\n", title);
+               fprintf(outfile, "    <desc lang=\"ja_JP\">%s</desc>\n", subtitle);
+               fprintf(outfile, "    <longdesc lang=\"ja_JP\">%s</longdesc>\n", desc);
+               fprintf(outfile, "    <category lang=\"ja_JP\">%s</category>\n", Category);
+//             fprintf(outfile, "    <category lang=\"en\">%s</category>\n", ContentCatList[eitcur->content_type].english);
+               fprintf(outfile, "  </programme>\n");
+#else
+               fprintf(outfile, "(%x:%x:%x)%s,%s,%s,%s,%s,%s\n",
+                                       eitcur->servid, eitcur->table_id, eitcur->event_id,
+                                       cstarttime, cendtime,
+                                       title, subtitle,
+                                       Category,
+                                       ContentCatList[eitcur->content_type].english);
+#endif
+#if 0
+               fprintf(outfile, "(%x:%x)%04d/%02d/%02d,%02d:%02d:%02d,%02d:%02d:%02d,%s,%s,%s,%s\n",
+                                       eitcur->table_id, eitcur->event_id,
+                                       eitcur->yy, eitcur->mm, eitcur->dd,
+                                       eitcur->hh, eitcur->hm, eitcur->ss,
+                                       eitcur->ehh, eitcur->emm, eitcur->ess,
+                                       eitcur->title, eitcur->subtitle,
+                                       ContentCatList[eitcur->content_type].japanese,
+                                       ContentCatList[eitcur->content_type].english);
+#endif
+               eitnext = eitcur->next ;
+               free(eitcur->title);
+               free(eitcur->subtitle);
+               free(eitcur);
+               eitcur = eitnext ;
+       }
+       free(eittop);
+       eittop = NULL;
+}
+void checkSta_BS(STATION **station,int *stalength){
+       STATION *statmp;
+       int chl[90];
+       int chlt=0;
+       int stal=0;
+       STATION * statin= *station;
+       statmp=malloc(sizeof(STATION)*2);
+       for (int i=0;i<*stalength;i++){
+               int noidinchl=1;
+               for (int j=0;j<chlt;j++){
+                       if (chl[j]==statin[i].svId || statin[i].svId >= 290){
+                               noidinchl=0;
+                       }
+               }
+               if (noidinchl==1){
+                       statmp=realloc(statmp,(stal+1)*sizeof(STATION));
+                       statmp[stal]=statin[i];
+                       //memcpy(statmp[stal-1],station[i],sizeof(STATION));
+                       chl[chlt]=statin[i].svId;
+                       chlt++;
+                       stal++;
+               }
+       }
+       //*station=realloc(station,(stal+1)*sizeof(STATION));
+       //memcpy(*station,statmp,(stal+1)*sizeof(STATION));
+       *station=statmp;
+       *stalength=stal;
+       //memcpy(statin,statmp,chlt*sizeof(STATION));
+       //free(statmp);
+       return;
+}
+
+void checkSta(STATION **station,int *stalength){
+       STATION *statmp;
+       int chl[90];
+       int chlt=0;
+       int stal=0;
+       STATION * statin= *station;
+       statmp=malloc(sizeof(STATION)*2);
+       for (int i=0;i<*stalength;i++){
+               int noidinchl=1;
+               for (int j=0;j<chlt;j++){
+                       if (chl[j]==statin[i].svId){
+                               noidinchl=0;
+                       }
+               }
+               if (noidinchl==1){
+                       statmp=realloc(statmp,(stal+1)*sizeof(STATION));
+                       statmp[stal]=statin[i];
+                       //memcpy(statmp[stal-1],station[i],sizeof(STATION));
+                       chl[chlt]=statin[i].svId;
+                       chlt++;
+                       stal++;
+               }       
+       }
+       sleep(1);
+       *station=statmp;
+       *stalength=stal;//¤³¤³¤¤¤é¤¬²ø¤·¤¤
+       //memcpy(statin,statmp,chlt*sizeof(STATION));
+       //free(statmp);
+       return;
+}
+int main(int argc, char *argv[])
+{
+
+       FILE *infile = stdin;
+       FILE *outfile = stdout;
+       int             arg_maxcount = 1 ;
+       char    *arg_onTV ;
+       int   mode = 1;
+       int             staCount ;
+       int   eitcnt;
+       char *file;
+       int   inclose = 0;
+       int   outclose = 0;
+       int             flag = 0 ;
+       int     outputhtml = 1;
+       SVT_CONTROL     *svtcur ;
+       SVT_CONTROL     *svtsave ;
+       char    *outptr ;
+       char    *inptr ;
+       size_t  ilen;
+       size_t  olen;
+       SECcache   secs[SECCOUNT];
+       int rtn;
+       int             lp ;
+       STATION *pStas ;
+       int             act ;
+
+       /* ¶½Ì£¤Î¤¢¤ëpid¤ò»ØÄê */
+       memset(secs, 0,  sizeof(SECcache) * SECCOUNT);
+       secs[0].pid = 0x11;
+       secs[1].pid = 0x12;
+       secs[2].pid = 0x26;
+       secs[3].pid = 0x27;
+
+       if(argc == 4){
+               arg_onTV = argv[1];
+               file = argv[2];
+               if(strcmp(file, "-")) {
+                       infile = fopen(file, "r");
+                       inclose = 1;
+               }
+               if(strcmp(argv[3], "-")) {
+                       outfile = fopen(argv[3], "w+");
+                       outclose = 1;
+               }
+       }else{
+               fprintf(stdout, "Usage : %s /BS <tsFile> <outfile>\n", argv[0]);
+               fprintf(stdout, "Usage : %s <ontvcode> <tsFile> <outfile>\n", argv[0]);
+               fprintf(stdout, "ontvcode ¥Á¥ã¥ó¥Í¥ë¼±Ê̻ҡ£****.ontvjapan.com ¤Ê¤É\n");
+               fprintf(stdout, "/BS      BS¥â¡¼¥É¡£°ì¤Ä¤ÎTS¤«¤éBSÁ´¶É¤Î¥Ç¡¼¥¿¤òÆɤ߹þ¤ß¤Þ¤¹¡£\n");
+               fprintf(stdout, "/CS      CS¥â¡¼¥É¡£°ì¤Ä¤ÎTS¤«¤éÊ£¿ô¶É¤Î¥Ç¡¼¥¿¤òÆɤ߹þ¤ß¤Þ¤¹¡£\n");
+               return 0;
+       }
+
+       if(strcmp(arg_onTV, "/BS") == 0){
+               STATION *sta=malloc(sizeof(STATION)*2);
+               int sta_count = 0;
+               svttop = calloc(1, sizeof(SVT_CONTROL));
+               char *head="BS";
+               GetSDT_chout(infile, svttop, secs, SECCOUNT,&sta, &sta_count,head);
+               checkSta_BS(&sta,&sta_count);
+               //if (sta_count) 
+               //printf("Station count: %d\n1st ontv=%s,name=%s\n",sta_count, sta[0].ontv, sta[0].name);
+               pStas = sta;
+               staCount = sta_count;// sizeof(pStas) / sizeof (STATION);
+               act = 0 ;
+               outputhtml=1;
+       }else if(strcmp(arg_onTV, "/CS") == 0){
+               STATION *sta=NULL;
+               int sta_count = 0;
+               svttop = calloc(1, sizeof(SVT_CONTROL));
+               char *head="CS";
+               GetSDT_chout(infile, svttop, secs, SECCOUNT,&sta, &sta_count,head);
+               checkSta(&sta,&sta_count);
+               //if (sta_count) 
+               //printf("Station count: %d\n1st ontv=%s,name=%s\n",sta_count, sta[0].ontv, sta[0].name);
+               pStas = sta;
+               staCount = sta_count;
+               //staCount=sizeof(pStas) / sizeof (STATION);
+               act = 0 ;
+               outputhtml=1;
+       }else if(strcmp(arg_onTV, "/TEST") == 0){
+               STATION *sta=NULL;
+               int sta_count = 0;
+               svttop = calloc(1, sizeof(SVT_CONTROL));
+               char *head="TEST";
+               GetSDT_chout(infile, svttop, secs, SECCOUNT,&sta, &sta_count,head);
+               checkSta(&sta,&sta_count);
+               //if (sta_count) 
+               //printf("Station count: %d\n1st ontv=%s,name=%s\n",sta_count, sta[0].ontv, sta[0].name);
+               pStas = sta;
+               staCount = sta_count;// sizeof(pStas) / sizeof (STATION);
+               act = 0 ;
+               outputhtml=1;
+       }else{
+               /*act = 1 ;
+               svttop = calloc(1, sizeof(SVT_CONTROL));
+               GetSDT(infile, svttop, secs, SECCOUNT);
+               svtcur = svttop->next ; //ÀèƬ
+               if(svtcur == NULL){
+                       free(svttop);
+                       return ;
+               }
+
+               pStas = calloc(1, sizeof(STATION));
+               pStas->tsId = svtcur->transport_stream_id ;
+               pStas->onId = svtcur->original_network_id ;
+               pStas->svId = svtcur->event_id ;
+               pStas->ontv = arg_onTV ;
+               pStas->name = svtcur->servicename ;
+               staCount = 1;*/
+               ///Êѹ¹¸å
+               STATION *sta=NULL;
+               int sta_count = 0;
+               svttop = calloc(1, sizeof(SVT_CONTROL));
+               //char *head=arg_onTV;
+               GetSDT_chout(infile, svttop, secs, SECCOUNT,&sta, &sta_count,arg_onTV);
+               checkSta(&sta,&sta_count);
+               //if (sta_count) 
+               //printf("Station count: %d\n1st ontv=%s,name=%s\n",sta_count, sta[0].ontv, sta[0].name);
+               pStas = sta;
+               staCount = sta_count;// sizeof(pStas) / sizeof (STATION);
+               act = 0 ;
+               outputhtml=1;
+       }
+       if (outputhtml == 1){
+               fprintf(outfile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+               fprintf(outfile, "<!DOCTYPE tv SYSTEM \"xmltv.dtd\">\n\n");
+               fprintf(outfile, "<tv generator-info-name=\"tsEPG2xml\" generator-info-url=\"http://localhost/\">\n");
+
+               cd = iconv_open("UTF-8", "EUC-JP");
+               for(lp = 0 ; lp < staCount ; lp++){
+                       memset(ServiceName, '\0', sizeof(ServiceName));
+                       ilen = strlen(pStas[lp].name);
+                       olen = sizeof(ServiceName);
+                       outptr = ServiceName ;
+                       inptr = pStas[lp].name ;
+                       iconv(cd, &inptr, &ilen, &outptr, &olen);
+                       xmlspecialchars(ServiceName);
+
+                       fprintf(outfile, "  <channel id=\"%s\">\n", pStas[lp].ontv);
+                       fprintf(outfile, "    <display-name lang=\"ja_JP\">%s</display-name>\n", ServiceName);
+                       fprintf(outfile, "  </channel>\n");
+               }
+               for(lp = 0 ; lp < staCount ; lp++){
+                       GetEIT(infile, outfile, &pStas[lp], secs, SECCOUNT);
+               }
+               fprintf(outfile, "</tv>\n");
+               if(inclose) {
+                       fclose(infile);
+               }
+
+               if(outclose) {
+                       fclose(outfile);
+               }
+               iconv_close(cd);
+               if(act){
+                       free(pStas);
+                       svtcur = svttop ;       //ÀèƬ
+                       while(svtcur != NULL){
+                               svtsave = svtcur->next ;
+                               free(svtcur);
+                               svtcur = svtsave ;
+                       }
+               }
+       }else{
+               
+       }
+       return 0;
+}
diff --git a/dist/trunk/tstools/epgdump/epgdump_segfault_fix_patch(last).txt b/dist/trunk/tstools/epgdump/epgdump_segfault_fix_patch(last).txt
new file mode 100755 (executable)
index 0000000..e402651
--- /dev/null
@@ -0,0 +1,30 @@
+diff -Nur epgdumpr2_orig/ts.c epgdumpr2/ts.c
+--- epgdumpr2_orig/ts.c        2009-03-15 21:35:57.000000000 +0900
++++ epgdumpr2/ts.c     2009-07-19 18:38:17.000000000 +0900
+@@ -202,6 +202,11 @@
+                       pk.payloadlen -= 1;
+               }
+               memset(pk.payload, 0xFF, sizeof(pk.payload));
++#if 1 /* 07/07/2009 add: */
++              if( pk.payloadlen > sizeof(pk.payload) ){
++                      continue;
++              }
++#endif
+               memcpy(pk.payload, payptr, pk.payloadlen);
+     
+               /*
+@@ -307,6 +312,14 @@
+ int checkcrc(SECcache *secs) {
++#if 1 /* 07/07/2009 add: °Û¾ï¾õÂÖ²óÈò¤Î¤¿¤á */
++      /* ¥»¥¯¥·¥ç¥óºÇÂçŤòĶ¤¨¤ë¤³¤È¤Ê¤É¤¢¤êÆÀ¤Ê¤¤¤Ï¤º¤À¤¬... */
++      if( secs->seclen > MAXSECLEN ){
++              /* ¤è¤¯Ê¬¤«¤é¤ó¤Î¤ÇÇË´þ¤·¤Æ¤ä¤ë */
++              return 0;
++      }
++#endif
++
+       /* ¥»¥¯¥·¥ç¥ó¤Î½ª¤ê¤ËÃÖ¤«¤ì¤ë4¥Ð¥¤¥È¤ÎCRC32¤Ï¡¢
+          CRC·×»»¤Î·ë²Ì0¤Ë¤Ê¤ë¤è¤¦¤ËÀßÄꤵ¤ì¤ë¡£
+          Ãͤ¬È¯À¸¤·¤¿¾ì¹ç¤Ï¡¢¥¨¥é¡¼¤Ê¤Î¤ÇÂоݳ°¤Ë¤¹¤ë */
diff --git a/dist/trunk/tstools/epgdump/patch2ch b/dist/trunk/tstools/epgdump/patch2ch
new file mode 100755 (executable)
index 0000000..e9bd2c7
--- /dev/null
@@ -0,0 +1,18 @@
+begin-base64 644 t1.uuc
+H4sIAFTfZkoAA+2TTU8TQRjHe91+ikm80G63ndltu1AiqSFwUg568dY0223Z
+AG2zu01AwocBnzVESSCgVkBLAwQq1cIJD8YYExOEkphAvBpnaA1WkRPBg88v
+m3nb5+U//+yaxVymNFZMOWYumy6NuqmsNZ4qpl1jOOyOu74rgXLi0aiYmR7X
+WnOMnp2LdVTXfYypGo3TmM5UH2XxmE59hF5N+8spOW7aJsSXL+RKxrB1SZxp
+O9ch6HrJWNksUYZKNjFbX4Ktpgq2lYu4Ttg4Pzvb+hVFuShMUintUaimsBhR
+WUKLJWJ6mP6EyLSHUr8sy7+Va6fpCushrDuhdSfYn2nJJFFUqobiRBYTYySZ
+9BNJkooj4WJ6YrSQzoyaeaLcJKxXnE+JYcwcc0y36zwkROj44GCIONYDs5D9
+5UUg0OuXb1hZwqRIkFA9wh8hi6QzmQQJRvyyJFnZLtLZre+CQiQwKYIlo5B3
+rXzJ7BW7KV7czHOP26qM4kSHKr4ounaoszyXRAQiJxI8c0CjunBAY9yB6JkD
+fmLlXWIMm8aIYRtd9wb6jTTfkaBjGk6ATPKIv99r4X3la+Xb+v7iae0EGrAG
+n1pX5aHeqjfvlb0D73Rle/1gcxlONp/DLDRhCWqwA69hBo62qnwFsAsrUIW5
+cDjcyhY+ie5KHx9bNt25dZ8ruz0w1HaHN4AvML8zB0/gEE557+3t+tPvUIYt
++AzNtuG26ZbsPKHCwnMHZe5Hh0BovHoMR1Df2OfVjqEZ9fY88GrQ6L/br6mw
+Oz3DM7iPfFt+t7oKjXJz8Q2FOhff5CoeQb36cfMInonc6Yet2I23MFebr77g
+itYqx8sHooo36x1Ov+RZXO36XuXD0gKvsdxS+69/XwRBEARBEARBEARBEARB
+EARBEARBEARBEOQ/5wfnyBSoACgAAA==
+==== 
diff --git a/dist/trunk/tstools/epgdump/patch_r2 b/dist/trunk/tstools/epgdump/patch_r2
new file mode 100755 (executable)
index 0000000..6d59eb9
--- /dev/null
@@ -0,0 +1,145 @@
+diff -rcw epgdumpr2.old/eit.c epgdumpr2/eit.c
+*** epgdumpr2.old/eit.c        2009-03-15 19:02:33.000000000 +0900
+--- epgdumpr2/eit.c    2009-03-24 20:45:25.961750270 +0900
+***************
+*** 6,11 ****
+--- 6,14 ----
+  
+  char         *subtitle_cnv_str[] = {
+       "¡¡Âè",
++      "¡¼Âè",
++      "-Âè",
++      " Âè",
+       "¡¡¡Ö",
+       "¡¡¡ô",
+       "¡Ê",
+***************
+*** 39,45 ****
+       return 14;
+  }
+  
+! int parseEITbody(unsigned char *data, EITbody *b) {
+       int boff = 0;
+       int tnum;
+       char buf[4];
+--- 42,49 ----
+       return 14;
+  }
+  
+! int parseEITbody(unsigned char *data, EITbody *b)
+! {
+       int boff = 0;
+       int tnum;
+       char buf[4];
+***************
+*** 78,97 ****
+  
+       b->yy += 1900;
+    
+       sprintf(buf, "%x", b->start_time[2]);
+       b->hh = atoi(buf);
+       sprintf(buf, "%x", b->start_time[3]);
+       b->hm = atoi(buf);
+       sprintf(buf, "%x", b->start_time[4]);
+       b->ss = atoi(buf);
+  
+       sprintf(buf, "%x", b->duration[0]);
+       b->dhh = atoi(buf);
+       sprintf(buf, "%x", b->duration[1]);
+       b->dhm = atoi(buf);
+       sprintf(buf, "%x", b->duration[2]);
+       b->dss = atoi(buf);
+!   
+       return 12;
+  }
+  
+--- 82,110 ----
+  
+       b->yy += 1900;
+    
++      memset(buf, '\0', sizeof(buf));
+       sprintf(buf, "%x", b->start_time[2]);
+       b->hh = atoi(buf);
++      memset(buf, '\0', sizeof(buf));
+       sprintf(buf, "%x", b->start_time[3]);
+       b->hm = atoi(buf);
++      memset(buf, '\0', sizeof(buf));
+       sprintf(buf, "%x", b->start_time[4]);
+       b->ss = atoi(buf);
+  
++      if((b->duration[0] == 0xFF) && (b->duration[1] == 0xFF) && (b->duration[2] == 0xFF)){
++              b->dhh = b->dhm = b->dss = 0;
++      }else{
++              memset(buf, '\0', sizeof(buf));
+               sprintf(buf, "%x", b->duration[0]);
+               b->dhh = atoi(buf);
++              memset(buf, '\0', sizeof(buf));
+               sprintf(buf, "%x", b->duration[1]);
+               b->dhm = atoi(buf);
++              memset(buf, '\0', sizeof(buf));
+               sprintf(buf, "%x", b->duration[2]);
+               b->dss = atoi(buf);
+!      }
+       return 12;
+  }
+  
+***************
+*** 269,274 ****
+--- 282,291 ----
+               if(ptr == NULL){
+                       continue ;
+               }
++              // ¥¿¥¤¥È¥ë¤¬¤Ê¤¯¤Ê¤é¤Ê¤¤¤è¤¦¤Ë
++              if(ptr == eitptr->title){
++                      continue ;
++              }
+               newsubtitle = calloc(1, ((strlen(ptr) + 1) + (strlen(eitptr->subtitle) + 1)));
+               memcpy(newsubtitle, ptr, strlen(ptr));
+               newsubtitle[strlen(ptr)] = ' ';
+diff -rcw epgdumpr2.old/epgdump.c epgdumpr2/epgdump.c
+*** epgdumpr2.old/epgdump.c    2009-03-15 21:29:33.000000000 +0900
+--- epgdumpr2/epgdump.c        2009-03-24 20:55:30.885022486 +0900
+***************
+*** 177,183 ****
+       char    *inptr ;
+       size_t  ilen;
+       size_t  olen;
+!      time_t  time ;
+       time_t  end_time ;
+       struct  tm      tl ;
+       struct  tm      *endtl ;
+--- 177,183 ----
+       char    *inptr ;
+       size_t  ilen;
+       size_t  olen;
+!      time_t  l_time ;
+       time_t  end_time ;
+       struct  tm      tl ;
+       struct  tm      *endtl ;
+***************
+*** 239,247 ****
+               tl.tm_wday = 0;
+               tl.tm_isdst = 0;
+               tl.tm_yday = 0;
+!              time = mktime(&tl);
+!              end_time = time + eitcur->ehh * 3600 + eitcur->emm * 60 + eitcur->ess;
+               endtl = localtime(&end_time);
+               memset(cendtime, '\0', sizeof(cendtime));
+               memset(cstarttime, '\0', sizeof(cstarttime));
+               strftime(cendtime, (sizeof(cendtime) - 1), "%Y%m%d%H%M%S", endtl);
+--- 239,253 ----
+               tl.tm_wday = 0;
+               tl.tm_isdst = 0;
+               tl.tm_yday = 0;
+!              l_time = mktime(&tl);
+!              if((eitcur->ehh == 0) && (eitcur->emm == 0) && (eitcur->ess == 0)){
+!                      (void)time(&l_time);
+!                      end_time = l_time + (60 * 5);           // £µÊ¬¸å¤ËÀßÄê
+                       endtl = localtime(&end_time);
++              }else{
++                      end_time = l_time + eitcur->ehh * 3600 + eitcur->emm * 60 + eitcur->ess;
++                      endtl = localtime(&end_time);
++              }
+               memset(cendtime, '\0', sizeof(cendtime));
+               memset(cstarttime, '\0', sizeof(cstarttime));
+               strftime(cendtime, (sizeof(cendtime) - 1), "%Y%m%d%H%M%S", endtl);
diff --git a/dist/trunk/tstools/epgdump/readme.txt b/dist/trunk/tstools/epgdump/readme.txt
new file mode 100755 (executable)
index 0000000..7727058
--- /dev/null
@@ -0,0 +1,57 @@
+xmltv-epg
+
+MPEG-TS\82É\8aÜ\82Ü\82ê\82éepg\82ðxml\82Å\8fo\97Í\82·\82é\83v\83\8d\83O\83\89\83\80\82Å\82·\81B
+\81\9fN/E9PqspSk\8e\81\82ªrecfriio Solaris\94Å(http://2sen.dip.jp/cgi-bin/friioup/source/up0737.zip)\82É\8aÜ\82Ü\82ê\82éepgdump\82ð
+Linux\94Å\82ð\89ü\91¢\82µ\82½\82à\82Ì\82ð\83x\81[\83X\82Éxmltv\97p\82Ìxml\83t\83@\83C\83\8b\82ð\8dì\90¬\82µ\82Ü\82·\81B
+
+\82Ü\82½\81A\83^\83C\83g\83\8b\93à\82É\8aÜ\82Ü\82ê\82é
+    "\81@\91æ"\82â\81A"\81@\81u"\81A"\81@\81\94"\81A"\81i"\81A"\81u"\81A\82ð\83T\83u\83^\83C\83g\83\8b\82Æ\82µ\82Ä\88µ\82¤\97l\82É\8fC\90³\82µ\82Ä\82¢\82Ü\82·\81B
+\97á\81F
+
+\83^\83C\83g\83\8b\82ª\81A
+\96¾\93ú\82Ì\82æ\82¢\82¿\81I\81u\82 \82Ì\8e\9e\8cN\82Í\83\8f\83\8b\82©\82Á\82½\81v
+\82Ì\8fê\8d\87
+\96¾\93ú\82Ì\82æ\82¢\82¿\81I\82ª\83^\83C\83g\83\8b\82É\81A\81u\82 \82Ì\8e\9e\8cN\82Í\83\8f\83\8b\82©\82Á\82½\81v\82ª\83T\83u\83^\83C\83g\83\8b\82É\92Ç\89Á\82³\82ê\82Ü\82·\81B
+
+\83T\83u\83^\83C\83g\83\8b\82Æ\82µ\82Ä\88µ\82¤\82à\82Ì\82ð\91\9d\82â\82·\8fê\8d\87\82Í\81Aeit.c\82É\82 \82ésubtitle_cnv_str\82É\92Ç\89Á\82µ\82Ä\82­\82¾\82³\82¢\81B
+
+\8eg\97p\95û\96@\82Í\88È\89º\82Ì\92Ê\82è\82Å\82·\81B
+
+Usage : ./epgdump /BS <tsFile> <outfile>
+Usage : ./epgdump <ontvcode> <tsFile> <outfile>
+ontvcode \83`\83\83\83\93\83l\83\8b\8e¯\95Ê\8eq\81B****.ontvjapan.com \82È\82Ç
+/BS      BS\83\82\81[\83h\81B\88ê\82Â\82ÌTS\82©\82çBS\91S\8bÇ\82Ì\83f\81[\83^\82ð\93Ç\82Ý\8d\9e\82Ý\82Ü\82·\81B
+/CS      CS\83\82\81[\83h\81B\88ê\82Â\82ÌTS\82©\82ç\95¡\90\94\8bÇ\82Ì\83f\81[\83^\82ð\93Ç\82Ý\8d\9e\82Ý\82Ü\82·\81B
+
+make\82·\82é\82Æepgdump\82ª\83r\83\8b\83h\82³\82ê\82Ü\82·\81B
+
+epgdump\83\89\83C\83Z\83\93\83X(Solaris\94Å\82æ\82è\88ø\97p):
+>epgdump\82É\8aÖ\82µ\82Ä\82Í\81ABonTest Ver.1.40\82©\82ç\82»\82Ì\82Ü\82Ü\83\\81[\83X\82ð\8e\9d\82Á\82Ä\82«\82Ä\82¢\82é\95\94\95ª\82à
+>\82 \82é\82½\82ß\81A\82»\82Ì\83\89\83C\83Z\83\93\83X\82É\8f]\82¢\82µ\82Ü\82·\81B
+>BonTest\82ÌReadme.txt\82æ\82è
+>>
+>>\82R\81D\83\89\83C\83Z\83\93\83X\82É\82Â\82¢\82Ä
+>>\81@\81@\81E\96{\83p\83b\83P\81[\83W\82É\8aÜ\82Ü\82ê\82é\91S\82Ä\82Ì\83\\81[\83X\83R\81[\83h\81A\83o\83C\83i\83\8a\82É\82Â\82¢\82Ä\92\98\8dì\8c \82Í\88ê\90Ø\8eå\92£\82µ\82Ü\82¹\82ñ\81B
+>>\81@\81@\81E\83I\83\8a\83W\83i\83\8b\82Ì\82Ü\82Ü\96\94\82Í\89ü\95Ï\82µ\81A\8ae\8e©\82Ì\83\\83t\83g\83E\83F\83A\82É\8e©\97R\82É\93Y\95t\81A\91g\82Ý\8d\9e\82Þ\82±\82Æ\82ª\82Å\82«\82Ü\82·\81B
+>>\81@\81@\81E\92A\82µGPL\82É\8f]\82¤\82±\82Æ\82ð\97v\8b\81\82µ\82Ü\82·\82Ì\82Å\82±\82ê\82ç\82ð\8ds\82¤\8fê\8d\87\82Í\83\\81[\83X\83R\81[\83h\82Ì\8aJ\8e¦\82ª\95K\90{\82Æ\82È\82è\82Ü\82·\81B
+>>\81@\81@\81E\82±\82Ì\82Æ\82«\96{\83\\83t\83g\83E\83F\83A\82Ì\92\98\8dì\8c \95\\8e¦\82ð\8ds\82¤\82©\82Ç\82¤\82©\82Í\94C\88Ó\82Å\82·\81B
+>>\81@\81@\81E\96{\83\\83t\83g\83E\83F\83A\82ÍFAAD2\82Ì\83\89\83C\83u\83\89\83\8a\94Å\83o\83C\83i\83\8a\82ð\8eg\97p\82µ\82Ä\82¢\82Ü\82·\81B
+>>
+>>\81@\81@\81@"Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
+>>
+>>\81@\81@\81E\83r\83\8b\83h\82É\95K\97v\82È\8aÂ\8b«
+>>\81@\81@\81@- Microsoft Visual Studio 2005 \88È\8fã\81@\81¦MFC\82ª\95K\97v
+>>\81@\81@\81@- Microsoft Windows SDK v6.0 \88È\8fã\81@\81@\81¦DirectShow\8aî\92ê\83N\83\89\83X\82Ì\83R\83\93\83p\83C\83\8b\8dÏ\82Ý\83\89\83C\83u\83\89\83\8a\82ª\95K\97v
+>>\81@\81@\81@- Microsoft DirectX 9.0 SDK \88È\8fã
+
+Special Thanks:
+\81ESolaris\94Å\8aJ\94­\8eÒ\82Ì\95û
+\81E\8ag\92£\83c\81[\83\8b\92\86\82Ì\90l
+\81E\81\9fN/E9PqspSk\8e\81
+\81EARIB(\8e\91\97¿\82Ì\96³\97¿\83_\83E\83\93\83\8d\81[\83h\82É\91Î\82µ\82Ä)
+
+\93®\8dì\8am\94F\8aÂ\8b«:
+  Debian GNU/Linux sid
+  Linux 2.6.27.19 SMP PREEMPT x86_64
+
+tomy \81\9fCfWlfzSGyg
diff --git a/dist/trunk/tstools/epgdump/sdt.c b/dist/trunk/tstools/epgdump/sdt.c
new file mode 100755 (executable)
index 0000000..ed005c6
--- /dev/null
@@ -0,0 +1,278 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sdt.h"
+#include "ts_ctl.h"
+
+int parseSDThead(unsigned char *data, SDThead *h) {
+       int boff = 0;
+
+       memset(h, 0, sizeof(SDThead));
+
+       boff = 0;
+       h->table_id = getBit(data, &boff, 8);
+       h->section_syntax_indicator = getBit(data, &boff, 1);
+       h->reserved_future_use1 = getBit(data, &boff, 1);
+       h->reserved1 = getBit(data, &boff, 2);
+       h->section_length = getBit(data, &boff, 12);
+       h->transport_stream_id = getBit(data, &boff, 16);
+       h->reserved2 = getBit(data, &boff, 2);
+       h->version_number = getBit(data, &boff, 5);
+       h->current_next_indicator = getBit(data, &boff, 1);
+       h->section_number = getBit(data, &boff, 8);
+       h->last_section_number = getBit(data, &boff, 8);
+       h->original_network_id = getBit(data, &boff, 16);
+       h->reserved_future_use2 = getBit(data, &boff, 8);
+
+       return 11;
+}
+
+int parseSDTbody(unsigned char *data, SDTbody *b) {
+       int boff = 0;
+
+       memset(b, 0, sizeof(SDTbody));
+
+       b->service_id = getBit(data, &boff, 16);
+       b->reserved_future_use1 = getBit(data, &boff, 3);
+       b->EIT_user_defined_flags = getBit(data, &boff, 3);
+       b->EIT_schedule_flag = getBit(data, &boff, 1);
+       b->EIT_present_following_flag = getBit(data, &boff, 1);
+       b->running_status = getBit(data, &boff, 3);
+       b->free_CA_mode = getBit(data, &boff, 1);
+       b->descriptors_loop_length = getBit(data, &boff, 12);
+
+       return 5;
+}
+
+int parseSVCdesc(unsigned char *data, SVCdesc *desc) {//0x48\82Ì\83T\81[\83r\83X\8bL\8fq\8eq\81A\95ú\91\97\8bÇ\82Ì\96¼\91O\82È\82Ç\82ª\93ü\82Á\82Ä\82¢\82é\82æ\82¤
+       int boff = 0;
+  
+       memset(desc, 0, sizeof(SVCdesc));
+
+       desc->descriptor_tag = getBit(data, &boff, 8);
+       desc->descriptor_length = getBit(data, &boff, 8);
+       desc->service_type = getBit(data, &boff, 8);
+       desc->service_provider_name_length = getBit(data, &boff, 8);
+       getStr(desc->service_provider_name, data, &boff, desc->service_provider_name_length);
+       desc->service_name_length = getBit(data, &boff, 8);
+       getStr(desc->service_name, data, &boff, desc->service_name_length);
+
+       return desc->descriptor_length + 2;
+}
+int            serachid(SVT_CONTROL *top, int service_id)
+{
+       SVT_CONTROL     *cur = top ;
+       while(cur != NULL){
+               if(cur->event_id == service_id){
+                       return 1 ;
+               }
+               cur = cur->next ;
+       }
+       return 0 ;
+}
+
+void   enqueue_sdt(SVT_CONTROL *top, SVT_CONTROL *sdtptr)
+{
+       SVT_CONTROL     *cur ;
+       if(top->next == NULL){
+               top->next = sdtptr ;
+               top->prev = top ;
+               return ;
+       }
+       cur = top->next ;
+       while(cur != NULL){
+               if(sdtptr->event_id < cur->event_id){
+                       if(cur->prev != NULL){
+                               cur->prev->next = sdtptr ;
+                               sdtptr->prev = cur->prev ;
+                       }
+                       cur->prev = sdtptr ;
+                       sdtptr->next = cur ;
+                       return ;
+               }
+               if(cur->next == NULL){
+                       cur->next = sdtptr ;
+                       sdtptr->prev = cur ;
+                       return ;
+               }
+               cur = cur->next ;
+       }
+       return ;
+
+}
+
+void dumpSDT(unsigned char *ptr, SVT_CONTROL *top)
+{
+
+       SDThead  sdth;
+       SDTbody  sdtb;
+       SVCdesc  desc;
+       SVT_CONTROL     *svtptr ;
+       int             rc ;
+
+       int len = 0;
+       int loop_len = 0;
+
+       /* SDT */
+       len = parseSDThead(ptr, &sdth); 
+       ptr += len;
+       loop_len = sdth.section_length - (len - 3 + 4); // 3¤Ï¶¦Ḁ̈إåÀĹ 4¤ÏCRC
+       while(loop_len > 0) {
+               len = parseSDTbody(ptr, &sdtb);
+               ptr += len;
+               loop_len -= len;
+               parseSVCdesc(ptr, &desc);
+
+               rc = serachid(top, sdtb.service_id);
+               if(rc == 0){
+                       svtptr = calloc(1, sizeof(SVT_CONTROL));
+                       svtptr->event_id = sdtb.service_id;
+                       svtptr->original_network_id = sdth.original_network_id;
+                       svtptr->transport_stream_id = sdth.transport_stream_id;
+                       svtptr->event_id = sdtb.service_id;
+                       memcpy(svtptr->servicename, desc.service_name, strlen(desc.service_name));
+                       enqueue_sdt(top, svtptr);
+#if 0
+                       printf("STATION=%s,%d,%d,%d,%d\n",
+                               desc.service_name,sdtb.service_id,sdth.transport_stream_id,
+                               sdth.original_network_id,sdtb.service_id);
+#endif
+#if 0
+                       printf("SDT=%s,%d,%x,%x,%x,%x,%x,%x,%x\n",
+                               desc.service_name, sdtb.service_id, sdtb.reserved_future_use1,
+                               sdtb.EIT_user_defined_flags, sdtb.EIT_schedule_flag, sdtb.EIT_present_following_flag,
+                               sdtb.running_status, sdtb.free_CA_mode, sdtb.descriptors_loop_length);
+/*
+0x01:\83f\83W\83^\83\8bTV\83T\81[\83r\83X
+0xA5:\83v\83\8d\83\82\81[\83V\83\87\83\93\89f\91\9c\83T\81[\83r\83X
+0x0C:\83f\81[\83^\83T\81[\83r\83X
+ */
+                       printf("SDT=(%x:%x)%s,%d,%d,%d,%d,%d(%d,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x)\n",
+                                       sdth.table_id, desc.service_type, 
+                                       desc.service_name, sdtb.service_id,
+                                       desc.descriptor_tag, desc.descriptor_length, desc.service_type,
+                                       desc.service_provider_name_length, desc.service_name_length,
+                                       sdth.table_id, sdth.section_syntax_indicator, sdth.reserved_future_use1,
+                                       sdth.reserved1, sdth.section_length, sdth.transport_stream_id,
+                                       sdth.reserved2, sdth.version_number, sdth.current_next_indicator,
+                                       sdth.section_number, sdth.last_section_number, sdth.original_network_id,
+                                       sdth.reserved_future_use2);
+#endif
+               }
+
+               ptr += sdtb.descriptors_loop_length;
+               loop_len -= sdtb.descriptors_loop_length;
+       }
+  
+       return;
+}
+void dumpSDT_chout(unsigned char *ptr, SVT_CONTROL *top,STATION **station, int * station_count,char *ontvheader)
+{
+
+       SDThead  sdth;
+       SDTbody  sdtb;
+       SVCdesc  desc;
+       SVT_CONTROL     *svtptr ;
+       STATION * pStation = *station;
+       int             rc ;
+
+       int len = 0;
+       int loop_len = 0;
+       char sid[80];
+       int stationi=*station_count;
+       /* SDT */
+       len = parseSDThead(ptr, &sdth); 
+       ptr += len;
+       loop_len = sdth.section_length - (len - 3 + 4); // 3¤Ï¶¦Ḁ̈إåÀĹ 4¤ÏCRC
+       while(loop_len > 0) {
+               len = parseSDTbody(ptr, &sdtb);
+               ptr += len;
+               loop_len -= len;
+               parseSVCdesc(ptr, &desc);
+               rc = serachid(top, sdtb.service_id);
+               if(rc == 0){
+                       svtptr = calloc(1, sizeof(SVT_CONTROL));
+                       svtptr->event_id = sdtb.service_id;
+                       svtptr->original_network_id = sdth.original_network_id;
+                       svtptr->transport_stream_id = sdth.transport_stream_id;
+                       svtptr->event_id = sdtb.service_id;
+                       memcpy(svtptr->servicename, desc.service_name, strlen(desc.service_name));
+                       if (desc.service_type == 1){
+                               enqueue_sdt(top, svtptr);
+                               pStation = realloc(pStation,(stationi+1)*sizeof(STATION));
+                               if (!pStation) printf( "Realloc returned NULL!!! stationi = %d\n", stationi);
+                               //char sidt[32];
+                               //char *tt="_";
+                               //sprintf(sidt, "%d", sdtb.service_id ); //ontv\83t\83H\81[\83}\83b\83g\82æ\82­\82í\82©\82ç\82È\82¢
+                               //STATION stt={NULL,NULL,sdth.transport_stream_id,
+                               //      sdth.original_network_id,sdtb.service_id};
+                               //\88È\89º\82É\93W\8aJ\82µ\82½
+                               //strcpy(sid,ontvheader);
+                               //strcat(sid,tt);
+                               //strcat(sid,sidt);
+                               sprintf(sid, "%s_%d", ontvheader, sdtb.service_id );
+                               pStation[stationi].name = malloc( strlen(desc.service_name) + 1 );
+                               pStation[stationi].ontv = malloc( strlen(sid) + 1 );
+                               pStation[stationi].tsId = sdth.transport_stream_id;
+                               pStation[stationi].onId = sdth.original_network_id;
+                               pStation[stationi].svId = sdtb.service_id;
+
+                               strcpy(pStation[stationi].name, desc.service_name);
+                               strcpy(pStation[stationi].ontv, sid);
+                               
+                               //printf("%s\n",sttt.name);
+                               //printf("%s\n",pStation[stationi].name);
+                               //printf( "iii %d \n", stationi);
+                               stationi++;
+                       
+                       //sprintf(*lastservicename, "%s", "lastservice2" );
+#if 0
+                       printf("STATION=%s,%d,%d,%d,%d,%d\n",
+                               desc.service_name,sdtb.service_id,sdth.transport_stream_id,
+                               sdth.original_network_id,sdtb.service_id,desc.service_type);
+#endif
+                       
+                       }
+
+#if 0
+                       printf("STATION=%s,%s,%d,%d,%d\n",
+                               sttt.name,sttt.ontv,sttt.tsId,sttt.onId,sttt.svId
+                               );
+#endif
+#if 0
+                       printf("SDT=%s,%d,%x,%x,%x,%x,%x,%x,%x\n",
+                               desc.service_name, sdtb.service_id, sdtb.reserved_future_use1,
+                               sdtb.EIT_user_defined_flags, sdtb.EIT_schedule_flag, sdtb.EIT_present_following_flag,
+                               sdtb.running_status, sdtb.free_CA_mode, sdtb.descriptors_loop_length);
+/*
+0x01:\83f\83W\83^\83\8bTV\83T\81[\83r\83X
+0xA5:\83v\83\8d\83\82\81[\83V\83\87\83\93\89f\91\9c\83T\81[\83r\83X
+0x0C:\83f\81[\83^\83T\81[\83r\83X
+ */
+
+                       printf("SDT=(%x:%x)%s,%d,%d,%d,%d,%d(%d,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x)\n",
+                                       sdth.table_id, desc.service_type, 
+                                       desc.service_name, sdtb.service_id,
+                                       desc.descriptor_tag, desc.descriptor_length, desc.service_type,
+                                       desc.service_provider_name_length, desc.service_name_length,
+                                       sdth.table_id, sdth.section_syntax_indicator, sdth.reserved_future_use1,
+                                       sdth.reserved1, sdth.section_length, sdth.transport_stream_id,
+                                       sdth.reserved2, sdth.version_number, sdth.current_next_indicator,
+                                       sdth.section_number, sdth.last_section_number, sdth.original_network_id,
+                                       sdth.reserved_future_use2);
+#endif
+               }
+               //ptr += sdtb.descriptors_loop_length;
+               loop_len -= sdtb.descriptors_loop_length;
+               
+               if (loop_len>0){
+                       ptr += sdtb.descriptors_loop_length;
+               }
+               
+       }
+       *station = pStation;
+       *station_count = stationi;
+       //printf("stationi %d -",stationi);//stationi==294\82Å\97\8e\82¿\82é
+       return;
+}
diff --git a/dist/trunk/tstools/epgdump/sdt.h b/dist/trunk/tstools/epgdump/sdt.h
new file mode 100755 (executable)
index 0000000..047e2cb
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef SDT_H
+#define SDT_H 1
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+#include "ts_ctl.h"
+
+typedef struct _SDThead {
+       char table_id;
+       int  section_syntax_indicator;
+       int  reserved_future_use1;
+       int  reserved1;
+       int  section_length;
+       int  transport_stream_id;
+       int  reserved2;
+       int  version_number;
+       int  current_next_indicator;
+       int  section_number;
+       int  last_section_number;
+       int  original_network_id;
+       int  reserved_future_use2;
+} SDThead;
+
+typedef struct _SDTbody {
+       int  service_id;
+       int  reserved_future_use1;
+       int  EIT_user_defined_flags;
+       int  EIT_schedule_flag;
+       int  EIT_present_following_flag;
+       int  running_status;
+       int  free_CA_mode;
+       int  descriptors_loop_length;
+} SDTbody;
+
+typedef struct _SVCdesc {
+       int  descriptor_tag;
+       int  descriptor_length;
+       int  service_type;
+       int  service_provider_name_length;
+       char service_provider_name[MAXSECLEN];
+       int  service_name_length;
+       char service_name[MAXSECLEN];
+} SVCdesc;
+
+typedef struct _TAG_STATION
+{
+       char    *name;
+       char    *ontv;
+       int             tsId;           // OriginalNetworkID
+       int             onId;           // TransportStreamID
+       int             svId;           // ServiceID
+} STATION;
+
+#ifdef __cplusplus
+extern "C"{
+#endif /* __cplusplus */
+
+       int parseSDThead(unsigned char *data, SDThead *h);
+       int parseSDTbody(unsigned char *data, SDTbody *b);
+       int parseSVCdesc(unsigned char *data, SVCdesc *desc);
+       void dumpSDT(unsigned char *data, SVT_CONTROL *top);
+       void dumpSDT_chout(unsigned char *ptr, SVT_CONTROL *top, STATION **station, int * station_count,char *ontvheader);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/dist/trunk/tstools/epgdump/ts.c b/dist/trunk/tstools/epgdump/ts.c
new file mode 100755 (executable)
index 0000000..c6cac1c
--- /dev/null
@@ -0,0 +1,332 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ts.h"
+
+static unsigned int CalcCrc(unsigned int crc, unsigned char *buf, int len);
+static int checkcrc(SECcache *secs);
+
+SECcache *readTS(FILE *in, SECcache secs[], int size) {
+       static int rcount = 0;
+       static int ridx = -1;
+
+       TSpacket pk;
+  
+       unsigned char buf[1024];
+
+       int boff;
+       int len;
+       unsigned char *payptr;
+
+       int inchar;
+       int i;
+
+       /* sync¥Ð¥¤¥È¤Þ¤ÇÆɤßÈô¤Ð¤· */
+       if(rcount == 0) {
+               while((inchar = fgetc(in)) != EOF) {
+                       if((inchar & 0xFF) == 0x47) {
+                               //fseek(in, -1, SEEK_CUR);
+                               ungetc(inchar, in);
+                               break;
+                       }
+               }
+               if(inchar == EOF) {
+                       return NULL;
+               }
+       }
+
+retry:
+  
+       /* Ì᤹¤Ù¤­»Ä¤ê¤¬¤¢¤ë¤«? */
+       if(ridx >= 0 && secs[ridx].cont) {
+               /* ¥Ð¥Ã¥Õ¥¡¥Á¥§¥Ã¥¯ */
+               if((secs[ridx].cur.payload[secs[ridx].curlen] & 0xFF) == 0xFF) {
+                       secs[ridx].cont = 0;
+                       secs[ridx].seclen = 0;
+                       secs[ridx].setlen = 0;
+                       secs[ridx].curlen = 0;
+               } else {
+                       len = secs[ridx].cur.payloadlen - secs[ridx].curlen;
+                       /* Á´ÉôÀßÄêºÑ¤ß¥Á¥§¥Ã¥¯ */
+                       if(len == 0) {
+                               secs[ridx].cont = 0;
+                               secs[ridx].seclen = 0;
+                               secs[ridx].setlen = 0;
+                               secs[ridx].curlen = 0;
+                       } else {
+                               /* ¤³¤³¤Çseclen¤¬¸Ù¤ë¤è¤¦¤ËTSʬ³ä¤µ¤ì¤Æ¤¤¤ë¤Èº¤¤ë¤Ê @@
+                                  if(secs[ridx].pid == 0x12) {
+                                  int check = secs[ridx].cur.payload[secs[ridx].curlen] & 0xFF;
+                                  if(!(check == 0x4E ||
+                                  check == 0x4F ||
+                                  (check >= 0x50 && check <= 0x6F))) {
+                                  secs[ridx].curlen -= 3;
+                                  }
+                                  }
+                               */
+       
+                               boff = 12;
+                               secs[ridx].seclen = getBit(&secs[ridx].cur.payload[secs[ridx].curlen], &boff, 12) + 3; // ¥Ø¥Ã¥À
+       
+                               /*
+                                 if(secs[ridx].seclen == 2334) {
+                                 printf("aa");
+                                 }
+                               */
+       
+                               /* TS¥Ç¡¼¥¿Ä¹-ÀßÄêºÑ¤ß¥Ç¡¼¥¿Ä¹ */
+                               if(secs[ridx].seclen > len) {
+                                       memcpy(secs[ridx].buf, &secs[ridx].cur.payload[secs[ridx].curlen], len);
+                                       secs[ridx].setlen = len;
+                                       secs[ridx].curlen = 0;
+                                       secs[ridx].cont   = 1;
+                                       /* ¼¡¤Î¥ì¥³¡¼¥ÉÆɤ߹þ¤ß */
+                               } else {
+                                       memcpy(secs[ridx].buf, 
+                                                  &secs[ridx].cur.payload[secs[ridx].curlen], secs[ridx].seclen);
+                                       secs[ridx].setlen  = secs[ridx].seclen;
+                                       secs[ridx].curlen += secs[ridx].seclen;
+                                       secs[ridx].cont = 1;
+
+                                       /* CRC¤Î¥Á¥§¥Ã¥¯ */
+                                       if(checkcrc(&(secs[ridx]))) {
+                                               return &(secs[ridx]); /* Ìá¤ë */
+                                       }
+                                       goto retry; /* ¤â¤¦°ì²ó */
+                               }
+                       }
+               }
+       }
+
+       int roffset = 0;
+       while(1) {
+               if(fread(buf+roffset, 188-roffset, 1, in) != 1) {
+                       /* »Ä¤ê¤Î½èÍý? */
+                       return NULL;
+               }
+               roffset = 0;
+               rcount++;
+
+               if((buf[0] & 0xFF) != 0x47) {
+                       /* ºÇ½é¤ÏbufÃæ¤Ë0x47¤¬¤¢¤ë¤«¥Á¥§¥Ã¥¯ */
+                       for(i = 1; i < 188; i++) {
+                               if((buf[i] & 0xFF) == 0x47) {
+                                       break;
+                               }
+                       }
+
+                       if(i < 188) {
+                               /* ¤½¤³¤«¤éºÆÆɤ߹þ¤ß¤·¤ÆÍߤ·¤¤¤Î¤Çseek */
+                               //fseek(in, (188 - i) * -1, SEEK_CUR);
+                               roffset = i;
+                               memmove(buf, buf + i, 188 - i);
+                               continue;
+                       }
+
+                       while((inchar = fgetc(in)) != EOF) {
+                               if((inchar & 0xFF) == 0x47) {
+                                       //fseek(in, -1, SEEK_CUR);
+                                       ungetc(inchar, in);
+                                       break;
+                               }
+                       }
+                       if(inchar == EOF) {
+                               return NULL;
+                       }
+                       continue;
+               }
+
+               /*
+                 if(rcount == 406502) {
+                 printf("aa");
+                 }
+               */
+
+    
+               pk.rcount = rcount;
+    
+               boff = 0;
+               pk.sync = getBit(buf, &boff, 8);
+               pk.transport_error_indicator = getBit(buf, &boff, 1);
+               pk.payload_unit_start_indicator = getBit(buf, &boff, 1);
+               pk.transport_priority = getBit(buf, &boff, 1);
+               pk.pid = getBit(buf, &boff, 13);
+               pk.transport_scrambling_control = getBit(buf, &boff, 2);
+               pk.adaptation_field_control = getBit(buf, &boff, 2);
+               pk.continuity_counter = getBit(buf, &boff, 4);
+
+               /*
+                 adaptation_field_control 2 bslbf
+                 continuity_counter 4 uimsbf
+                 if(adaptation_field_control = = '10' || adaptation_field_control = = '11'){
+                 adaptation_field()
+                 }
+                 ...
+                 adaptation_field() {
+                 adaptation_field_length 8 uimsbf
+                 if (adaptation_field_length > 0) {
+                 discontinuity_indicator....
+
+                 00 Reserved for future use by ISO/IEC
+                 01 No adaptation_field, payload only
+                 10 Adaptation_field only, no payload
+                 11 Adaptation_field followed by payload
+
+               */
+
+               pk.payloadlen = 184;
+
+               if(pk.adaptation_field_control == 2) {
+                       continue;
+               }
+
+               if(pk.adaptation_field_control == 3) {
+                       len = getBit(buf, &boff, 8);
+                       payptr = buf + (boff / 8) + len;
+                       pk.payloadlen -= (len + 1);
+               } else {
+                       payptr = buf + (boff / 8);
+               }
+               if(pk.payloadlen < 0){
+                       continue ;
+               }
+
+               /* 
+                  if the Transport Stream packet carries the first byte of a PSI section, the payload_unit_start_indicator value
+                  shall be '1', indicating that the first byte of the payload of this Transport Stream packet carries the pointer_field.
+               */
+               if(pk.payload_unit_start_indicator == 1) {
+                       /* pointer_field¤Ï¤¤¤é¤Ê¤¤ */
+                       payptr += 1;
+                       pk.payloadlen -= 1;
+               }
+               memset(pk.payload, 0xFF, sizeof(pk.payload));
+#if 1  /* 07/07/2009 add: */
+               if( pk.payloadlen > sizeof(pk.payload) ){
+                       continue;
+               }
+#endif
+               memcpy(pk.payload, payptr, pk.payloadlen);
+    
+               /*
+                 if(pk.rcount == 62) {
+                 printf("62\n");
+                 }
+
+                 if(pk.rcount == 63) {
+                 printf("63\n");
+                 }
+               */
+    
+               /* ¶½Ì£¤Î¤¢¤ëpid¤«³Îǧ */
+               for(int i = 0;i < size; i++) {
+                       if(secs[i].pid == pk.pid) {
+                               secs[i].cur = pk;
+                               /* ÅÓÃæ½èÍýÃ椫ºÇ½é¤«? */
+                               if(!secs[i].cont) {
+                                       /* ºÇ½é ¥»¥¯¥·¥ç¥óŤòÄ´¤Ù¤ë */
+                                       boff = 12;
+                                       secs[i].seclen = getBit(secs[i].cur.payload, &boff, 12) + 3; // ¥Ø¥Ã¥À;
+                                       /*
+                                         if(secs[i].seclen == 2334) {
+                                         printf("aa");
+                                         }
+                                       */
+
+                                       if(secs[i].seclen > secs[i].cur.payloadlen) {
+                                               memcpy(secs[i].buf, secs[i].cur.payload, secs[i].cur.payloadlen);
+                                               secs[i].setlen = secs[i].cur.payloadlen;
+                                               secs[i].cont = 1;
+                                               continue;
+                                       } 
+                                       memcpy(secs[i].buf, secs[i].cur.payload, secs[i].seclen);
+                                       secs[i].setlen = secs[i].seclen;
+                                       secs[i].curlen = secs[i].seclen;
+                                       secs[i].cont = 1;
+                                       ridx = i;
+                                       /* CRC¤Î¥Á¥§¥Ã¥¯ */
+                                       if(checkcrc(&(secs[ridx]))) {
+                                               return &(secs[i]); /* ¼è¤ê¹ç¤¨¤ºÌá¤ë */
+                                       }
+                                       goto retry; /* »Ä¤ê½èÍý¤Ø */
+                               }
+                               /* ¥»¥¯¥·¥ç¥óĹ-ÀßÄêºÑ¤ßĹ */
+                               len = secs[i].seclen - secs[i].setlen;
+                               if(len > secs[i].cur.payloadlen) {
+                                       /* Á´ÂΞÁ÷ */
+                                       memcpy(&secs[i].buf[secs[i].setlen], 
+                                                  secs[i].cur.payload, secs[i].cur.payloadlen);
+                                       secs[i].setlen += secs[i].cur.payloadlen;
+                                       continue;
+                               }
+                               /* ¥»¥¯¥·¥ç¥óŤλĤê¤òÀßÄê */
+                               memcpy(&secs[i].buf[secs[i].setlen], secs[i].cur.payload, len);
+                               secs[i].setlen  = secs[i].seclen;
+                               secs[i].curlen += len;
+                               secs[i].cont    = 1;
+                               ridx = i;
+                               /* CRC¤Î¥Á¥§¥Ã¥¯ */
+                               if(checkcrc(&(secs[ridx]))) {
+                                       return &(secs[i]);
+                               }
+                               goto retry; /* »Ä¤ê½èÍý¤Ø */
+                       }
+               }
+       }
+
+       //return NULL;
+}
+
+/* BonTest/TsStream.cpp¤«¤é¤Î¥Ñ¥¯¥ê */
+unsigned int CalcCrc(unsigned int crc, unsigned char *buf, int len) {
+       unsigned int c = crc;
+       int n;
+
+       static const unsigned int CrcTable[256] = {
+               0x00000000UL, 0x04C11DB7UL, 0x09823B6EUL, 0x0D4326D9UL, 0x130476DCUL, 0x17C56B6BUL, 0x1A864DB2UL, 0x1E475005UL, 0x2608EDB8UL, 0x22C9F00FUL, 0x2F8AD6D6UL, 0x2B4BCB61UL, 0x350C9B64UL, 0x31CD86D3UL, 0x3C8EA00AUL, 0x384FBDBDUL,
+               0x4C11DB70UL, 0x48D0C6C7UL, 0x4593E01EUL, 0x4152FDA9UL, 0x5F15ADACUL, 0x5BD4B01BUL, 0x569796C2UL, 0x52568B75UL, 0x6A1936C8UL, 0x6ED82B7FUL, 0x639B0DA6UL, 0x675A1011UL, 0x791D4014UL, 0x7DDC5DA3UL, 0x709F7B7AUL, 0x745E66CDUL,
+               0x9823B6E0UL, 0x9CE2AB57UL, 0x91A18D8EUL, 0x95609039UL, 0x8B27C03CUL, 0x8FE6DD8BUL, 0x82A5FB52UL, 0x8664E6E5UL, 0xBE2B5B58UL, 0xBAEA46EFUL, 0xB7A96036UL, 0xB3687D81UL, 0xAD2F2D84UL, 0xA9EE3033UL, 0xA4AD16EAUL, 0xA06C0B5DUL,
+               0xD4326D90UL, 0xD0F37027UL, 0xDDB056FEUL, 0xD9714B49UL, 0xC7361B4CUL, 0xC3F706FBUL, 0xCEB42022UL, 0xCA753D95UL, 0xF23A8028UL, 0xF6FB9D9FUL, 0xFBB8BB46UL, 0xFF79A6F1UL, 0xE13EF6F4UL, 0xE5FFEB43UL, 0xE8BCCD9AUL, 0xEC7DD02DUL,
+               0x34867077UL, 0x30476DC0UL, 0x3D044B19UL, 0x39C556AEUL, 0x278206ABUL, 0x23431B1CUL, 0x2E003DC5UL, 0x2AC12072UL, 0x128E9DCFUL, 0x164F8078UL, 0x1B0CA6A1UL, 0x1FCDBB16UL, 0x018AEB13UL, 0x054BF6A4UL, 0x0808D07DUL, 0x0CC9CDCAUL,
+               0x7897AB07UL, 0x7C56B6B0UL, 0x71159069UL, 0x75D48DDEUL, 0x6B93DDDBUL, 0x6F52C06CUL, 0x6211E6B5UL, 0x66D0FB02UL, 0x5E9F46BFUL, 0x5A5E5B08UL, 0x571D7DD1UL, 0x53DC6066UL, 0x4D9B3063UL, 0x495A2DD4UL, 0x44190B0DUL, 0x40D816BAUL,
+               0xACA5C697UL, 0xA864DB20UL, 0xA527FDF9UL, 0xA1E6E04EUL, 0xBFA1B04BUL, 0xBB60ADFCUL, 0xB6238B25UL, 0xB2E29692UL, 0x8AAD2B2FUL, 0x8E6C3698UL, 0x832F1041UL, 0x87EE0DF6UL, 0x99A95DF3UL, 0x9D684044UL, 0x902B669DUL, 0x94EA7B2AUL,
+               0xE0B41DE7UL, 0xE4750050UL, 0xE9362689UL, 0xEDF73B3EUL, 0xF3B06B3BUL, 0xF771768CUL, 0xFA325055UL, 0xFEF34DE2UL, 0xC6BCF05FUL, 0xC27DEDE8UL, 0xCF3ECB31UL, 0xCBFFD686UL, 0xD5B88683UL, 0xD1799B34UL, 0xDC3ABDEDUL, 0xD8FBA05AUL,
+               0x690CE0EEUL, 0x6DCDFD59UL, 0x608EDB80UL, 0x644FC637UL, 0x7A089632UL, 0x7EC98B85UL, 0x738AAD5CUL, 0x774BB0EBUL, 0x4F040D56UL, 0x4BC510E1UL, 0x46863638UL, 0x42472B8FUL, 0x5C007B8AUL, 0x58C1663DUL, 0x558240E4UL, 0x51435D53UL,
+               0x251D3B9EUL, 0x21DC2629UL, 0x2C9F00F0UL, 0x285E1D47UL, 0x36194D42UL, 0x32D850F5UL, 0x3F9B762CUL, 0x3B5A6B9BUL, 0x0315D626UL, 0x07D4CB91UL, 0x0A97ED48UL, 0x0E56F0FFUL, 0x1011A0FAUL, 0x14D0BD4DUL, 0x19939B94UL, 0x1D528623UL,
+               0xF12F560EUL, 0xF5EE4BB9UL, 0xF8AD6D60UL, 0xFC6C70D7UL, 0xE22B20D2UL, 0xE6EA3D65UL, 0xEBA91BBCUL, 0xEF68060BUL, 0xD727BBB6UL, 0xD3E6A601UL, 0xDEA580D8UL, 0xDA649D6FUL, 0xC423CD6AUL, 0xC0E2D0DDUL, 0xCDA1F604UL, 0xC960EBB3UL,
+               0xBD3E8D7EUL, 0xB9FF90C9UL, 0xB4BCB610UL, 0xB07DABA7UL, 0xAE3AFBA2UL, 0xAAFBE615UL, 0xA7B8C0CCUL, 0xA379DD7BUL, 0x9B3660C6UL, 0x9FF77D71UL, 0x92B45BA8UL, 0x9675461FUL, 0x8832161AUL, 0x8CF30BADUL, 0x81B02D74UL, 0x857130C3UL,
+               0x5D8A9099UL, 0x594B8D2EUL, 0x5408ABF7UL, 0x50C9B640UL, 0x4E8EE645UL, 0x4A4FFBF2UL, 0x470CDD2BUL, 0x43CDC09CUL, 0x7B827D21UL, 0x7F436096UL, 0x7200464FUL, 0x76C15BF8UL, 0x68860BFDUL, 0x6C47164AUL, 0x61043093UL, 0x65C52D24UL,
+               0x119B4BE9UL, 0x155A565EUL, 0x18197087UL, 0x1CD86D30UL, 0x029F3D35UL, 0x065E2082UL, 0x0B1D065BUL, 0x0FDC1BECUL, 0x3793A651UL, 0x3352BBE6UL, 0x3E119D3FUL, 0x3AD08088UL, 0x2497D08DUL, 0x2056CD3AUL, 0x2D15EBE3UL, 0x29D4F654UL,
+               0xC5A92679UL, 0xC1683BCEUL, 0xCC2B1D17UL, 0xC8EA00A0UL, 0xD6AD50A5UL, 0xD26C4D12UL, 0xDF2F6BCBUL, 0xDBEE767CUL, 0xE3A1CBC1UL, 0xE760D676UL, 0xEA23F0AFUL, 0xEEE2ED18UL, 0xF0A5BD1DUL, 0xF464A0AAUL, 0xF9278673UL, 0xFDE69BC4UL,
+               0x89B8FD09UL, 0x8D79E0BEUL, 0x803AC667UL, 0x84FBDBD0UL, 0x9ABC8BD5UL, 0x9E7D9662UL, 0x933EB0BBUL, 0x97FFAD0CUL, 0xAFB010B1UL, 0xAB710D06UL, 0xA6322BDFUL, 0xA2F33668UL, 0xBCB4666DUL, 0xB8757BDAUL, 0xB5365D03UL, 0xB1F740B4UL
+       };              
+
+       for (n = 0; n < len; n++) {
+               c = (c << 8) ^ CrcTable[((((c >> 24) & 0xFF) ^ buf[n]) & 0XFF)];
+       }
+
+       return c;
+}
+
+
+int checkcrc(SECcache *secs) {
+
+#if 1  /* 07/07/2009 add: °Û¾ï¾õÂÖ²óÈò¤Î¤¿¤á */
+       /* ¥»¥¯¥·¥ç¥óºÇÂçŤòĶ¤¨¤ë¤³¤È¤Ê¤É¤¢¤êÆÀ¤Ê¤¤¤Ï¤º¤À¤¬... */
+       if( secs->seclen > MAXSECLEN ){
+               /* ¤è¤¯Ê¬¤«¤é¤ó¤Î¤ÇÇË´þ¤·¤Æ¤ä¤ë */
+               return 0;
+       }
+#endif
+
+       /* ¥»¥¯¥·¥ç¥ó¤Î½ª¤ê¤ËÃÖ¤«¤ì¤ë4¥Ð¥¤¥È¤ÎCRC32¤Ï¡¢
+          CRC·×»»¤Î·ë²Ì0¤Ë¤Ê¤ë¤è¤¦¤ËÀßÄꤵ¤ì¤ë¡£
+          Ãͤ¬È¯À¸¤·¤¿¾ì¹ç¤Ï¡¢¥¨¥é¡¼¤Ê¤Î¤ÇÂоݳ°¤Ë¤¹¤ë */
+       if(CalcCrc(0xffffffffU, secs->buf, secs->seclen)) {
+//             fprintf(stderr, "tblid:0x%x CRC error\n", secs->buf[0]);
+               return 0;
+       }
+       return 1;
+}
+
diff --git a/dist/trunk/tstools/epgdump/ts.h b/dist/trunk/tstools/epgdump/ts.h
new file mode 100755 (executable)
index 0000000..da39812
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef TS_H
+#define TS_H 1
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+#define TSPAYLOADMAX 184
+
+typedef struct _TSpacket { 
+       char     sync;
+       int      transport_error_indicator;
+       int      payload_unit_start_indicator;
+       int      transport_priority;
+       int      pid;
+       int      transport_scrambling_control;
+       int      adaptation_field_control;
+       int      continuity_counter;
+       int      adaptation_field;
+       unsigned char payload[TSPAYLOADMAX];
+       int      payloadlen;
+       int      rcount;
+} TSpacket;
+
+typedef struct _SECcache { 
+       int      pid;
+       unsigned char buf[MAXSECLEN];
+       int      seclen;
+       int      setlen;
+       TSpacket cur;
+       int      curlen;
+       int      cont;
+} SECcache;
+
+#ifdef __cplusplus
+extern "C"{
+#endif /* __cplusplus */
+
+       SECcache *readTS(FILE *in, SECcache secs[], int secscount);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/dist/trunk/tstools/epgdump/ts_ctl.h b/dist/trunk/tstools/epgdump/ts_ctl.h
new file mode 100755 (executable)
index 0000000..1d74dd0
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef        __TS_CONTROL_H__
+#define        __TS_CONTROL_H__
+
+#include       "util.h"
+
+typedef        struct  _SVT_CONTROL    SVT_CONTROL;
+struct _SVT_CONTROL{
+       SVT_CONTROL     *next ;
+       SVT_CONTROL     *prev ;
+       int             event_id ;                      // ¥¤¥Ù¥ó¥ÈID
+       int             original_network_id ;                   // OriginalNetworkID
+       int             transport_stream_id ;                   // TransporrtStreamID
+       char    servicename[MAXSECLEN] ;                // ¥µ¡¼¥Ó¥¹Ì¾
+};
+
+typedef        struct  _EIT_CONTROL    EIT_CONTROL;
+struct _EIT_CONTROL{
+       EIT_CONTROL     *next ;
+       EIT_CONTROL     *prev ;
+       int             table_id ;
+       int             servid ;
+       int             event_id ;                      // ¥¤¥Ù¥ó¥ÈID
+       int             content_type ;          // ¥³¥ó¥Æ¥ó¥È¥¿¥¤¥×
+    int                yy;
+    int                mm;
+    int                dd;
+    int                hh;
+    int                hm;
+       int             ss;
+       int             dhh;
+       int             dhm;
+       int             dss;
+       int             ehh;
+       int             emm;
+       int             ess;
+       char    *title ;                        // ¥¿¥¤¥È¥ë
+       char    *subtitle ;                     // ¥µ¥Ö¥¿¥¤¥È¥ë
+       char    *desc ;                 // Description
+};
+#endif
diff --git a/dist/trunk/tstools/epgdump/util.c b/dist/trunk/tstools/epgdump/util.c
new file mode 100755 (executable)
index 0000000..1dc39bb
--- /dev/null
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "aribstr.h"
+#include "util.h"
+
+int strrep(char *buf, char *mae, char *ato)
+{
+    char *mituke;
+       size_t maelen, atolen;
+                   
+       maelen = strlen(mae);
+       atolen = strlen(ato);
+       if (maelen == 0 || (mituke = strstr(buf, mae)) == NULL) return 0;
+       memmove(mituke + atolen, mituke + maelen, strlen(buf) - (mituke + maelen - buf ) + 1);
+       memcpy(mituke, ato, atolen);
+       return 1;
+}
+int getBit(unsigned char *byte, int *pbit, int gbit) {
+       int pbyte = *pbit / 8;
+       unsigned char *fbyte = byte + pbyte;
+
+       int cutbit = *pbit - (pbyte * 8);
+       int lcutbit = 32 - (cutbit + gbit);
+
+       unsigned char tbuf[4]; /* int¤ÎºÇÂç32bit */
+       unsigned int tnum;
+
+       memcpy(tbuf, fbyte, sizeof(unsigned char) * 4);
+
+       /* ÀèƬ¥Ð¥¤¥È¤«¤éÉÔÍ×bit¤ò¥«¥Ã¥È */
+       tbuf[0] = tbuf[0] << cutbit;
+       tbuf[0] = tbuf[0] >> cutbit;
+
+       /* int¤Ë¤·¤Æ¤·¤Þ¤¦ */
+       tnum = tbuf[0] << 24 | tbuf[1] << 16 | tbuf[2] << 8 | tbuf[3];
+
+       /* ¸å¤í¤ÎÉÔÍץХ¤¥È¤ò¥«¥Ã¥È */
+       tnum = tnum >> lcutbit;
+
+       *pbit += gbit;
+
+       return tnum;
+  
+}
+
+void getStr(char *tostr, unsigned char *byte, int *pbit, int len) {
+       char str[MAXSECLEN];
+       int pbyte = *pbit / 8;
+       unsigned char *fbyte = byte + pbyte;
+
+       memset(str, 0, sizeof(char) * MAXSECLEN);
+       memcpy(str, fbyte, len);
+
+       *pbit += (len * 8);
+  
+       AribToString(tostr, str, len);
+
+       return;
+  
+}
+
+int parseOTHERdesc(unsigned char *data) {
+       int boff = 0;
+       int descriptor_tag;
+       int descriptor_length;
+
+       descriptor_tag = getBit(data, &boff, 8);
+       descriptor_length = getBit(data, &boff, 8);
+
+       /* printf("other desc_tag:0x%x\n", descriptor_tag); */
+
+       return descriptor_length + 2;
+}
+
diff --git a/dist/trunk/tstools/epgdump/util.h b/dist/trunk/tstools/epgdump/util.h
new file mode 100755 (executable)
index 0000000..483f624
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef UTIL_H
+#define UTILH 1
+
+#define MAXSECLEN 4096
+
+#ifdef __cplusplus
+extern "C"{
+#endif /* __cplusplus */
+
+       int   getBit(unsigned char *byte, int *pbit, int gbit);
+       void  getStr(char *tostr, unsigned char *byte, int *pbit, int len);
+       int   parseOTHERdesc(unsigned char *data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/dist/trunk/tstools/epgdump/xmldata.c b/dist/trunk/tstools/epgdump/xmldata.c
new file mode 100755 (executable)
index 0000000..56e087b
--- /dev/null
@@ -0,0 +1,93 @@
+static STATION bsSta[] = {
+       { "NHK BS1", "3001.ontvjapan.com", 16625, 4, 101},
+       { "NHK BS2", "3002.ontvjapan.com", 16625, 4, 102},
+       { "NHK BSh", "3003.ontvjapan.com", 16626, 4, 103},
+       { "BSÆü¥Æ¥ì", "3004.ontvjapan.com", 16592, 4, 141},
+       { "BSÄ«Æü", "3005.ontvjapan.com", 16400, 4, 151},
+       { "BS-i", "3006.ontvjapan.com", 16401, 4, 161},
+       { "BS¥¸¥ã¥Ñ¥ó", "3007.ontvjapan.com", 16433, 4, 171},
+       { "BS¥Õ¥¸", "3008.ontvjapan.com", 16593, 4, 181},
+       { "WOWOW", "3009.ontvjapan.com", 16432, 4, 191},
+       { "WOWOW2", "3010.ontvjapan.com", 16432, 4, 192},
+       { "WOWOW3", "3011.ontvjapan.com", 16432, 4, 193},
+       { "BS11", "3013.ontvjapan.com", 16528, 4, 211},
+       { "TwellV", "3014.ontvjapan.com", 16530, 4, 222},
+};
+
+static int bsStaCount = sizeof(bsSta) / sizeof (STATION);
+
+
+
+static STATION csSta[] = {
+       { "¥¹¥¿¡¼£ã£è¥×¥é¥¹", "1002.ontvjapan.com", 24608, 6, 237},
+       { "ÆüËܱDzèÀìÌç£ã£è£È£Ä", "1086.ontvjapan.com", 24608, 6, 239},
+       { "¥Õ¥¸¥Æ¥ì¥Ó£Ã£Ó£È£Ä", "306ch.epgdata.ontvjapan", 24608, 6, 306},
+       { "¥·¥ç¥Ã¥×¥Á¥ã¥ó¥Í¥ë", "1059.ontvjapan.com", 24704, 6, 55},
+       { "¥¶¡¦¥·¥Í¥Þ", "1217.ontvjapan.com", 24736, 6, 228},
+       { "¥¹¥«¥Á¥ã¥ó£È£Ä£¸£°£°", "800ch.epgdata.ontvjapan", 24736, 6, 800},
+       { "¥¹¥«¥Á¥ã¥ó£¸£°£±", "801ch.epgdata.ontvjapan", 24736, 6, 801},
+       { "¥¹¥«¥Á¥ã¥ó£¸£°£²", "802ch.epgdata.ontvjapan", 24736, 6, 802},
+       { "£å£²¥×¥í¥â", "100ch.epgdata.ontvjapan", 28736, 7, 100},
+       { "¥¤¥ó¥¿¡¼¥í¡¼¥«¥ë£Ô£Ö", "194ch.epgdata.ontvjapan", 28736, 7, 194},
+       { "£Ê¥¹¥Ý¡¼¥Ä¡¡£Å£Ó£Ð£Î", "1025.ontvjapan.com", 28736, 7, 256},
+       { "£Æ£Ï£Ø", "1016.ontvjapan.com", 28736, 7, 312},
+       { "¥¹¥Ú¡¼¥¹¥·¥ã¥ï¡¼£Ô£Ö", "1018.ontvjapan.com", 28736, 7, 322},
+       { "¥«¡¼¥È¥¥¡¼¥ó¡¡¥Í¥Ã¥È", "1046.ontvjapan.com", 28736, 7, 331},
+       { "¥È¥¥¡¼¥ó¡¦¥Ç¥£¥º¥Ë¡¼", "1213.ontvjapan.com", 28736, 7, 334},
+       { "Åì±Ç¥Á¥ã¥ó¥Í¥ë", "1010.ontvjapan.com", 28768, 7, 221},
+       { "±ÒÀ±·à¾ì", "1005.ontvjapan.com", 28768, 7, 222},
+       { "¥Á¥ã¥ó¥Í¥ë£Î£Å£Ã£Ï", "1008.ontvjapan.com", 28768, 7, 223},
+       { "Íβè¡ú¥·¥Í¥Õ¥£¥ë", "1009.ontvjapan.com", 28768, 7, 224},
+       { "¥¹¥¿¡¼¡¦¥¯¥é¥·¥Ã¥¯", "1003.ontvjapan.com", 28768, 7, 238},
+       { "»þÂå·àÀìÌç¥Á¥ã¥ó¥Í¥ë", "1133.ontvjapan.com", 28768, 7, 292},
+       { "¥¹¡¼¥Ñ¡¼¥É¥é¥Þ", "1006.ontvjapan.com", 28768, 7, 310},
+       { "£Á£Ø£Î", "1014.ontvjapan.com", 28768, 7, 311},
+       { "¥Ê¥·¥ç¥¸¥ª¥Á¥ã¥ó¥Í¥ë", "1204.ontvjapan.com", 28768, 7, 343},
+       { "¥ï¥ó¥Æ¥ó¥Ý¡¼¥¿¥ë", "110ch.epgdata.ontvjapan", 28864, 7, 110},
+       { "¥´¥ë¥Õ¥Á¥ã¥ó¥Í¥ë", "1028.ontvjapan.com", 28864, 7, 260},
+       { "¥Æ¥ìÄ«¥Á¥ã¥ó¥Í¥ë", "1092.ontvjapan.com", 28864, 7, 303},
+       { "£Í£Ô£Ö", "1019.ontvjapan.com", 28864, 7, 323},
+       { "¥ß¥å¡¼¥¸¥Ã¥¯¡¦¥¨¥¢", "1024.ontvjapan.com", 28864, 7, 324},
+       { "Ä«Æü¥Ë¥å¡¼¥¹¥¿¡¼", "1067.ontvjapan.com", 28864, 7, 352},
+       { "£Â£Â£Ã¥ï¡¼¥ë¥É", "1070.ontvjapan.com", 28864, 7, 353},
+       { "£Ã£Î£Î£ê", "1069.ontvjapan.com", 28864, 7, 354},
+       { "¥¸¥ã¥¹¥È¡¦¥¢¥¤", "361ch.epgdata.ontvjapan", 28864, 7, 361},
+       { "£Ê¥¹¥Ý¡¼¥Ä¡¡£±", "1041.ontvjapan.com", 28896, 7, 251},
+       { "£Ê¥¹¥Ý¡¼¥Ä¡¡£²", "1042.ontvjapan.com", 28896, 7, 252},
+       { "£Ê¥¹¥Ý¡¼¥Ä£Ð£ì£õ£ó£È", "1043.ontvjapan.com", 28896, 7, 253},
+       { "£Ç£Á£Ï£Ò£Á", "1026.ontvjapan.com", 28896, 7, 254},
+       { "£ó£ë£ù¡¦£Á¥¹¥Ý¡¼¥Ä¡Ü", "1040.ontvjapan.com", 28896, 7, 255},
+       { "ÊõÄÍ¥×¥í¥â¥Á¥ã¥ó¥Í¥ë", "101ch.epgdata.ontvjapan", 28928, 7, 101},
+       { "£Ó£Ë£Ù¡¦£Ó£Ô£Á£Ç£Å", "1207.ontvjapan.com", 28928, 7, 290},
+       { "¥Á¥ã¥ó¥Í¥ë¶ä²Ï", "305ch.epgdata.ontvjapan", 28928, 7, 305},
+       { "£Á£Ô-£Ø", "1201.ontvjapan.com", 28928, 7, 333},
+       { "¥Ò¥¹¥È¥ê¡¼¥Á¥ã¥ó¥Í¥ë", "1050.ontvjapan.com", 28928, 7, 342},
+       { "¥¹¥«¥Á¥ã¥ó£¸£°£³", "803ch.epgdata.ontvjapan", 28928, 7, 803},
+       { "¥¹¥«¥Á¥ã¥ó£¸£°£´", "804ch.epgdata.ontvjapan", 28928, 7, 804},
+       { "¥à¡¼¥Ó¡¼¥×¥é¥¹£È£Ä", "1007.ontvjapan.com", 28960, 7, 240},
+       { "¥´¥ë¥Õ¥Í¥Ã¥È¥ï¡¼¥¯", "1027.ontvjapan.com", 28960, 7, 262},
+       { "£Ì£á£Ì£á¡¡£È£Ä", "1074.ontvjapan.com", 28960, 7, 314},
+       { "¥Õ¥¸¥Æ¥ì¥Ó£·£³£¹", "1073.ontvjapan.com", 28992, 7, 258},
+       { "¥Õ¥¸¥Æ¥ì¥Ó£·£²£±", "1072.ontvjapan.com", 28992, 7, 302},
+       { "¥¢¥Ë¥Þ¥Ã¥¯¥¹", "1047.ontvjapan.com", 28992, 7, 332},
+       { "¥Ç¥£¥¹¥«¥Ð¥ê¡¼", "1062.ontvjapan.com", 28992, 7, 340},
+       { "¥¢¥Ë¥Þ¥ë¥×¥é¥Í¥Ã¥È", "1193.ontvjapan.com", 28992, 7, 341},
+       { "£Ã-£Ô£Â£Ó¥¦¥¨¥ë¥«¥à", "160ch.epgdata.ontvjapan", 29024, 7, 160},
+       { "£Ñ£Ö£Ã", "1120.ontvjapan.com", 29024, 7, 161},
+       { "¥×¥é¥¤¥à£³£¶£µ¡¥£Ô£Ö", "185ch.epgdata.ontvjapan", 29024, 7, 185},
+       { "¥Õ¥¡¥ß¥ê¡¼·à¾ì", "1015.ontvjapan.com", 29024, 7, 293},
+       { "£Ô£Â£Ó¥Á¥ã¥ó¥Í¥ë", "3201.ontvjapan.com", 29024, 7, 301},
+       { "¥Ç¥£¥º¥Ë¡¼¥Á¥ã¥ó¥Í¥ë", "1090.ontvjapan.com", 29024, 7, 304},
+       { "MUSIC ON! TV", "1022.ontvjapan.com", 29024, 7, 325},
+       { "¥­¥Ã¥º¥¹¥Æ¡¼¥·¥ç¥ó", "1045.ontvjapan.com", 29024, 7, 330},
+       { "£Ô£Â£Ó¥Ë¥å¡¼¥¹¥Ð¡¼¥É", "1076.ontvjapan.com", 29024, 7, 351},
+       { "£Ã£ÓÆüËÜÈÖÁÈ¥¬¥¤¥É", "147ch.epgdata.ontvjapan", 29056, 7, 147},
+       { "Æü¥Æ¥ì£Ç¡Ü", "1068.ontvjapan.com", 29056, 7, 257},
+       { "fashion TV", "5004.ontvjapan.com", 29056, 7, 291},
+       { "Æü¥Æ¥ì¥×¥é¥¹", "300ch.epgdata.ontvjapan", 29056, 7, 300},
+       { "¥¨¥³¥ß¥å¡¼¥¸¥Ã¥¯£Ô£Ö", "1023.ontvjapan.com", 29056, 7, 320},
+       { "Music Japan TV", "1208.ontvjapan.com", 29056, 7, 321},
+       { "Æü¥Æ¥ì£Î£Å£×£Ó£²£´", "2002.ontvjapan.com", 29056, 7, 350},
+};
+
+static int csStaCount = sizeof(csSta) / sizeof (STATION);
diff --git a/dist/trunk/tstools/jTsSplitter/jTsSplitter.jar b/dist/trunk/tstools/jTsSplitter/jTsSplitter.jar
new file mode 100755 (executable)
index 0000000..1553fe9
Binary files /dev/null and b/dist/trunk/tstools/jTsSplitter/jTsSplitter.jar differ
diff --git a/dist/trunk/tstools/tunerec/Makefile b/dist/trunk/tstools/tunerec/Makefile
new file mode 100755 (executable)
index 0000000..4d5310d
--- /dev/null
@@ -0,0 +1,36 @@
+PREFIX          = /usr/local
+TARGETS = tunerec
+#OBJ_TARGETS     = 
+#HEDDERDEPEND    = eit.h sdt.h aribstr.h ts.h util.h
+
+LANG            = C
+CC              = gcc
+
+#CFLAGS         = -std=c99 -O2 -Wall -g
+CFLAGS          = -std=c99 -O2 -Wall -ggdb
+
+LIBS            =
+
+.c.o:                   ${CC} ${CFLAGS} -c $<
+
+all:                    ${TARGETS}
+
+
+tunerec:               tunerec.c
+                       ${CC} ${CFLAGS} -o ${TARGETS} tunerec.c
+
+clean:
+                       rm -f core ${TARGETS} *.o
+
+install:                ${TARGETS}
+                       install -m755 ${TARGETS} ${PREFIX}/bin
+
+uninstall:              ${TARGETS}
+                       rm ${PREFIX}/bin/${TARGETS}
+
+
+
+#tune: tune.c
+#      gcc -O2 -Wall -I../dvb-pt1/linux/include -o tunerec tune.c
+
+
diff --git a/dist/trunk/tstools/tunerec/README.ja b/dist/trunk/tstools/tunerec/README.ja
new file mode 100755 (executable)
index 0000000..01b2426
--- /dev/null
@@ -0,0 +1,169 @@
+DVB PT1 ドライバ用tuneプログラム(rec10用改変版)
+
+2012-01-08版
+
+このプログラムはDVB PT1付属のtuneプログラムを、
+rec10にて使いやすいように改変を行った物です。
+
+変更点
+チャンネルリストを無効化、周波数およびtsIDの指定で動作するようにしました。
+
+使い方
+$ ./tune <DVBアダプタ番号> <周波数> [tsid(省略可)]
+
+ライセンス
+>7. 使用上の注意
+>
+>このソフトウェアは、 sourceforge.jp で開発されている独自仕様のドライバ
+>を改竄し v4l-dvb の仕様に合わせようとしているものです。これは単に AS
+>IS で提供しているもので、開発途上であり、完全に無保証です。テストプログ
+>ラムは MIT ライセンスで提供します。
+
+gn64_jp(gn64@rec10.org)
+
+DVB PT1 ドライバ
+
+2009-03-07 版
+
+1. このドキュメントについて
+
+このドキュメントは DVB ベース の PT1 ドライバのチェックアウト、コンパイ
+ル、インストールおよびテスト方法を説明するものです。
+
+
+2. ドライバのチェックアウト
+
+DVB ベースの PT1 ドライバのソースコードは現在 mercurial で管理されてい
+ます。開発マシンに mercurial をインストールした上で、次のコマンドでチェッ
+クアウトしてください。
+
+       $ hg clone http://bitbucket.org/hiranotaka/dvb-pt1/
+
+一度チェックアウトを行うと二度めからは dvb-pt1 ディレクトリにて次のコマ
+ンドを実行することで更新することができます。ただし次の更新は 3 月下旬以
+降の予定です。
+
+              $ hg pull && hg update
+
+詳しくは mercurial のマニュアルや bitbucket.org のマニュアルを参照して
+ください。
+
+
+3. ドライバのコンパイル
+
+ターゲットとなるカーネルと同じバージョンのカーネルヘッダまたはソースが
+必要です。 linux-headers-$(uname -r) パッケージなどで入手してください。
+準備ができたら、v4l ディレクトリ下に .config という名前のファイルを作成
+し、
+
+       CONFIG_DVB_CORE=m
+       CONFIG_DVB_PT1=m
+
+のように記述します。後は、 /lib/modules/$(uname -r)/source または
+/lib/modules/$(uname -r)/build にカーネルヘッダまたはソースが展開されて
+いる場合、同じ v4l ディレクトリにて、
+
+$ make
+
+するだけで OK です。うまくいけば dvb-core.ko と pt1_drv.ko という二つの
+モジュールができるはずです。
+
+なお、カーネルヘッダやソースが違うディレクトリに展開されている場合は、
+SRCDIR オプションが必要です。
+
+
+4. ドライバのロード
+
+コンパイルでできた 2 つのモジュールを順にロードします。
+
+       $ sudo insmod dvb-core.ko
+       $ sudo insmod pt1_drv.ko
+
+無事ロードされると次のようになるはずです。
+
+       $ dmesg
+       ...
+       DVB: registering new adapter (pt1-pci)
+       DVB: registering adapter 0 frontend 0 (VA1J5JF8007 ISDB-S)...
+       DVB: registering new adapter (pt1-pci)
+       DVB: registering adapter 1 frontend 0 (VA1J5JF8007 ISDB-T)...
+       DVB: registering new adapter (pt1-pci)
+       DVB: registering adapter 2 frontend 0 (VA1J5JF8007 ISDB-S)...
+       DVB: registering new adapter (pt1-pci)
+       DVB: registering adapter 3 frontend 0 (VA1J5JF8007 ISDB-T)...
+       pt1_thread run
+
+現在、一部のマシンで DMA 領域の確保に失敗する事象が確認されています。こ
+の場合、デバッグ用のスタックトレースなどとともに、次のように表示されま
+す。
+
+       $ dmesg
+       ...
+       PT1:DMA ALLOC ERROR
+       pt1-pci: probe of 0000:01:0a.0 failed with error -5
+
+これは特に 32 ビットマシンにおいて貴重な LOWMEM 領域(DMA 可能な領域で、
+最大でも 756 MB)にその 1/6 にあたる 128 MB もの巨大な領域を確保している
+ためと考えられます。うまい対処方法があれば教えて下さい。
+
+
+5. テストプログラムのビルド
+
+簡単なテストプログラムを用意しました。先ほどチェックアウトした dvb-pt1
+と同じ階層にこの README.ja を含むディレクトリを移動します。別の言い方を
+すると、このディレクトリから見てドライバが ../dvb-pt1 の位置に来るよう
+にします。その状態で
+
+       $ make
+
+してください。
+
+
+6. テストプログラムの実行
+
+チャンネルを設定するには、
+
+       $ ./tune <DVBアダプタ番号> <リモコンキーID>
+
+とします。設定がうまくいけば
+
+       Successfully tuned to NHK東京 総合 .
+
+などと表示されます。
+
+       Failed to tune to NHK BS-1 (status 03).
+
+などと表示された場合は、ステータスによって次の原因が考えられます。
+
+       00: PLL に問題がある
+       01: 指定された周波数に信号がない
+       03: 他の TS-ID の信号はあるが、指定された TS-ID のものはない
+
+DVB アダプタ番号は、他にアダプタが無い場合、チューナ 0 の ISDB-S が 0
+、チューナ 0 の ISDB-T が 1 、チューナ 1 の ISDB-S が 2 、チューナ 1 の
+ISDB-T が 3 になります。 アダプタが ISDB-T か ISDB-S かは自動判定され、
+ISDB-T であればリモコンキー ID は地上波のものと、 ISDB-S であれば衛星の
+ものと解釈されます。
+
+リモコンキー ID と周波数の対応表は、東京都のものになっています。東京都
+以外では、 tune.c の上部にある対応表の書き換えが必要になります。
+
+テストプログラムを実行したままの状態で、
+
+       $ cat /dev/dvb/adapter1/dvr > dump.ts
+
+などとすれば録画できます(例はアダプタ番号 1 の場合)。また同様に
+
+       $ b25 -v 0 /dev/dvb/adapter1/dvr /dev/stdout | \
+               mplayer -cache 8192 -
+
+とすればリアルタイムで視聴できると思います。ただしリアルタイム視聴には
+それなりの CPU 性能が求められます。
+
+
+7. 使用上の注意
+
+このソフトウェアは、 sourceforge.jp で開発されている独自仕様のドライバ
+を改竄し v4l-dvb の仕様に合わせようとしているものです。これは単に AS
+IS で提供しているもので、開発途上であり、完全に無保証です。テストプログ
+ラムは MIT ライセンスで提供します。
diff --git a/dist/trunk/tstools/tunerec/tunerec.c b/dist/trunk/tstools/tunerec/tunerec.c
new file mode 100755 (executable)
index 0000000..a42c146
--- /dev/null
@@ -0,0 +1,191 @@
+#include <linux/dvb/frontend.h>
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/audio.h>
+#include <linux/dvb/version.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct channel {
+       int id;
+       const char *name;
+       unsigned int frequency;
+       unsigned int ts_id;
+};
+static int search(int adapter_nr,struct channel *ch)
+{
+       char file[256];
+       int fd;
+       struct dvb_frontend_info info;
+       struct channel *channel;
+       struct dtv_property prop[3];
+       struct dtv_properties props;
+       int i;
+       fe_status_t status;
+
+       sprintf(file, "/dev/dvb/adapter%d/frontend0", adapter_nr);
+       if ((fd = open(file, (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) {
+               perror("open");
+               return -1;
+       }
+
+       if (ioctl(fd, FE_GET_INFO, &info) < 0) {
+               perror("ioctl FE_GET_INFO");
+               goto out;
+       }
+
+       if (info.type == FE_QPSK) {
+               channel = ch;
+               //channel = lookup_channel(channel_id, isdbs_channels,
+               //                       ARRAY_SIZE(isdbs_channels));
+       } else if (info.type == FE_OFDM) {
+               channel = ch;
+               //channel = lookup_channel(channel_id, isdbt_channels,
+               //                       ARRAY_SIZE(isdbt_channels));
+       } else {
+               fprintf(stderr, "Unknown type of adapter\n");
+               goto out;
+       }
+       if (channel == NULL) {
+               fprintf(stderr, "Unknown id of channel\n");
+               goto out;
+       }
+
+       prop[0].cmd = DTV_FREQUENCY;
+       prop[0].u.data = channel->frequency;
+       prop[1].cmd = DTV_ISDBS_TS_ID;
+       prop[1].u.data = channel->ts_id;
+       prop[2].cmd = DTV_TUNE;
+
+       props.props = prop;
+       props.num = 3;
+
+       if ((ioctl(fd, FE_SET_PROPERTY, &props)) < 0) {
+               perror("ioctl FE_SET_PROPERTY");
+               goto out;
+       }
+
+       for (i = 0; i < 4; i++) {
+               if (ioctl(fd, FE_READ_STATUS, &status) < 0) {
+                       perror("ioctl FE_READ_STATUS");
+                       goto out;
+               }
+               if (status & FE_HAS_LOCK) {
+                       fprintf(stderr, "Successfully tuned to %d(%d) .\n",
+                               channel->frequency,channel->ts_id);
+                       return 0;
+               }
+               usleep(250 * 1000);
+       }
+
+       fprintf(stderr, "Failed to tune to %s (status %02x).\n",
+               channel->name, status);
+
+out:
+       close(fd);
+       return -1;
+}
+
+static int track(int adapter_nr)
+{
+       char file[256];
+       int fd;
+       struct dmx_pes_filter_params filter;
+
+       filter.pid = 0x2000;
+       filter.input = DMX_IN_FRONTEND;
+       filter.output = DMX_OUT_TS_TAP;
+       filter.pes_type =  DMX_PES_VIDEO;
+       filter.flags = DMX_IMMEDIATE_START;
+
+       sprintf(file, "/dev/dvb/adapter%d/demux0", adapter_nr);
+       if ((fd = open(file, O_RDWR)) < 0) {
+               perror("open");
+               return -1;
+       }
+
+
+       if (ioctl(fd, DMX_SET_PES_FILTER, &filter) < 0) {
+               perror("ioctl DMX_SET_PES_FILTER");
+               close(fd);
+               return -1;
+       }
+}
+
+void record(int adapter_nr, char* output, int rectime) {
+       int fin, fout;
+       char input[256];
+       time_t start_time, current_time;
+       char buf[1316];
+       ssize_t rt, wt;
+       int size_remain;
+
+       fout = open(output, (O_WRONLY | O_CREAT | O_TRUNC));
+       if ( fout < 0 ) {
+               printf("output file open failed\n");
+               return;
+       }
+       sprintf(input, "/dev/dvb/adapter%d/dvr0", adapter_nr);
+       start_time = time(NULL);
+       fin = open(input, (O_RDONLY));
+       while ( rt = read(fin, buf, 1316) ) {
+               while ( wt = write(fout, buf, rt) ) {
+                       rt -= wt;
+                       if ( rt == 0 ) break;
+                       if ( wt == 0 ) {
+                               printf("output file write failed\n");
+                               goto error;
+                       }
+               }
+               current_time = time(NULL);
+               if ( current_time - start_time > rectime ) {
+                       break;
+               }
+       }
+
+       error:
+       close(fin);
+       close(fout);
+}
+
+int main(int argc, char *argv[]) {
+       int adapter_nr;
+       int channel_id;
+       int channel_freq;
+       int fd;
+       int ret;
+       int rectime;
+
+       if (argc <= 2) {
+               fprintf(stderr, "Usage: %s adapter_nr freq [tsid]\n", argv[0]);
+               return 1;
+       }
+       struct channel *ch;
+       adapter_nr = strtol(argv[1], NULL, 0);
+       channel_freq = strtol(argv[2], NULL, 10);
+       channel_id=0;
+       if (argc >= 4){
+               channel_id = strtol(argv[3], NULL, 10);
+       }
+       if ( argc >= 5 ) {
+               rectime = atoi(argv[4]);
+       }
+       struct channel ch1 ={0,"",channel_freq,channel_id};
+       ch = &ch1;
+       //struct channel ch;//{   1, "NHK BS-1",          1318000, 0x40f1 }
+       //ch={0,"",argv}
+       fd = search(adapter_nr, ch);
+       if (fd < 0)
+               return 1;
+
+       ret = track(adapter_nr);
+       record(adapter_nr, argv[5], rectime);
+       close(fd);
+
+       return ret < 0;
+}
diff --git a/dist/trunk/www/Makefile.PL b/dist/trunk/www/Makefile.PL
new file mode 100755 (executable)
index 0000000..a1f8943
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/perl
+
+print "UID:$<\n";
+if ( $< ) {
+       print "Please run this script with root.\n";
+       exit;
+}
+
+$distribution = `ls /etc -F | grep \"release\$\\|version\$\"`;
+
+if ( $distribution =~ /redhat|fedora/m ) {
+       print "Your distribution seems to be RedHat/Fedora.\n";
+       $redhat = 1;
+}
+elsif ( $distribution =~ /debian/m ) {
+       print "Your distribution seems to be Debian.\n";
+       $debian = 1;
+}
+
+if ( $redhat ) {
+       my $YUM  = 'perl-DBI perl-Date-Simple perl-DateTime perl-Config-Simple perl-Tie-IxHash perl-SVG perl-XML-Atom perl-List-Compare';
+       my $CPAN = 'CGI::Carp CGI::Minimal MIME::Base64 Time::HiRes Data::Dumper Time::Simple Encode Text::Ngram File::Find Perl6::Slurp List::Util';
+       $CPAN .= 'SVG Text::Ngram Algorithm::Diff';
+       print "Going to install ( YUM )\n";
+       print "$YUM\n";
+       system( "yum install $YUM" );
+       print "Going to install ( CPAN )\n";
+       print "$CPAN\n";
+       system( "cpan $CPAN" );
+}elsif ( $debian ) {
+       my $APT  = 'libdbi-perl libdate-simple-perl libdatetime-perl libmime-base64-perl libconfig-simple-perl libtime-hires-perl libtie-ixhash-perl libsvg-perl libxml-atom-perl liblist-compare-perl libperl6-slurp-perl';
+       my $CPAN = 'CGI::Carp CGI::Minimal Data::Dumper Time::Simple Encode Text::Ngram File::Find List::Util';
+       $CPAN .= 'SVG Text::Ngram Algorithm::Diff';
+       print "Going to install ( APT )\n";
+       print "$APT\n";
+       system( "aptitude install $APT" );
+       print "Going to install ( CPAN )\n";
+       print "$CPAN\n";
+       system( "cpan $CPAN" );
+}else{
+       my $CPAN = 'CGI::Carp DBI Time::Piece Time::Seconds Date::Simple DateTime CGI::Minimal MIME::Base64 Config::Simple ';
+       $CPAN .= 'Time::HiRes Data::Dumper Tie::IxHash Perl6::Slurp Sort::Naturally';
+       $CPAN .= 'SVG Text::Ngram Algorithm::Diff';
+       print "Going to install ( CPAN )\n";
+       print "$CPAN\n";
+       system( "cpan $CPAN" );
+}
+
diff --git a/dist/trunk/www/rectool.pl b/dist/trunk/www/rectool.pl
new file mode 100755 (executable)
index 0000000..bd21231
--- /dev/null
@@ -0,0 +1,2324 @@
+#!/usr/bin/perl
+# -d:SmallProf
+#use Perl6::Slurp;
+#use XML::Simple;
+#use CGI;
+#use CGI::Lite;
+#use Date::Manip;
+#Date_Init("TZ=JST","ConvTZ=JST");
+#use SVG;
+#use KCatch;
+use CGI::Carp qw( fatalsToBrowser );
+use warnings;
+use DBI;
+use Time::Piece;
+use Time::Seconds;
+use Date::Simple;
+use DateTime;
+use CGI;
+use MIME::Base64;
+use Config::Simple;
+use Time::HiRes;
+use Data::Dumper;
+use Tie::IxHash;
+use Perl6::Slurp;
+use Sort::Naturally;
+use Algorithm::Diff qw(LCS);
+#require SVG Time::Simple XML::Atom Encode Text::Ngram List::Compare List::Util
+use utf8;
+#%DB::packages = ( 'main' => 1 );
+
+
+################ バージョン定義 ################
+
+
+my $rectool_version = 101;
+
+
+################ 初期化ここから ################
+
+
+my $tz = DateTime::TimeZone->new( name => 'local' );
+my $hires = Time::HiRes::time();
+
+my $cfg = new Config::Simple;
+if ( -e 'rec10.conf' ) {
+       $cfg->read( 'rec10.conf' );
+}
+elsif ( -e '/etc/rec10.conf' ) {
+       $cfg->read( '/etc/rec10.conf' );
+}
+else { 
+       die 'rec10.confが見つかりません。';
+}
+
+my $sql = $cfg->param( 'db.db' );
+
+if ( $sql eq 'MySQL' ) {
+       my $name = $cfg->param( 'db.mysql_dbname' );
+       my $host = $cfg->param( 'db.mysql_host' );
+       my $port = $cfg->param( 'db.mysql_port' );
+       my $user = $cfg->param( 'db.mysql_user' );
+       my $pass = $cfg->param( 'db.mysql_passwd' );
+       $dbh = DBI->connect("dbi:mysql:$name:$host:$port", $user, $pass, {
+               AutoCommit => 1,
+               RaiseError => 1,
+               mysql_enable_utf8 => 1, # only availavle for MySQL
+       });
+       $dbh->do( 'SET NAMES utf8' );
+}
+
+my $rec10_version = eval {
+       $dbh->selectrow_array( "SELECT version FROM in_status " );
+};
+
+my $HTML;
+
+$HTTP_HEADER = "Content-Type: text/html\n\n";
+$HTML .= <<EOM;
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="ja">
+<head>
+<title>Rec10%HTML_TITLE_OPT%</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<meta http-equiv="Content-Script-Type" content="text/javascript">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<meta name="robots" content="noindex,nofollow,noarchive">
+<link rev="made" href="Rea10">
+<link rel="alternate" type="application/atom+xml" title= "Rec10 Atom Feed" href="./rectool.pl?mode=atom">
+%REFRESH%
+%SCRIPT%
+%CSS%
+</head>
+<body>
+%HTML_HEADER%
+EOM
+
+my ( $user, $pass, $auth );
+( $user, $pass ) = eval {
+       $dbh->selectrow_array( "SELECT webuser, webpass FROM in_settings " );
+};
+
+if ( $user and $pass ) {
+       if ( $ENV{'HTTP_AUTHORIZATION'} ) {
+               my ( $base64 ) = $ENV{'HTTP_AUTHORIZATION'} =~ /Basic\s(.*)/;
+               if ( $base64 eq encode_base64( "$user:$pass" ) ) {
+                       $auth = 1;
+               }
+               else {
+                       $auth = 0;
+               }
+       }
+       else {
+               $auth = 0;
+       }
+}
+else {
+       $auth = 1;
+}
+
+if ( !$auth ) {
+       my ( $base64 ) = $ENV{'REMOTE_USER'} =~ /Basic (.*)/;
+       $HTTP_HEADER = qq {Status: 401 Authorization Required\nWWW-Authenticate: Basic realm="Protected Rec10 $ENV{'HTTP_AUTHORIZATION'}"\n} . $HTTP_HEADER;
+       goto end;
+}
+
+if ( $rec10_version != $rectool_version ) {
+       $HTML .= qq {<div style="font-size: 200%; font-weight: bold; color: red">\n};
+
+       if ( $rec10_version > $rectool_version ) {
+               $HTML .= qq {Rec10本体のバージョンが新しいため、実行できません。<br>\n};
+               $HTML .= qq {rectoolのバージョンアップを行ってください。<br>\n};
+       }
+
+       if ( $rec10_version < $rectool_version ) {
+               $HTML .= qq {Rec10本体のバージョンが古いため、実行できません。<br>\n};
+               $HTML .= qq {Rec10のバージョンアップを行ってください。<br>\n};
+       }
+
+       $HTML .= qq {Rec10のバージョンは$rec10_version 、rectoolのバージョンは$rectool_version です。<br>\n};
+       $HTML .= qq {<a href="http://sourceforge.jp/projects/rec10/">公式ページ</a>\n};
+       goto end;
+}
+
+$q = new CGI;
+%params = $q->Vars;
+$mode = $params{ 'mode' };
+$mode_sub = $params{ 'mode_sub' };
+
+################ %chtxt_chnameの準備 ################
+
+my %chtxt_chname;
+my %chtxt_0_chname;
+tie %chtxt_0_chname, 'Tie::IxHash';
+
+my $ary_ref = $dbh->selectall_arrayref(
+       "SELECT chtxt, chname, ch, bctype FROM epg_ch
+       WHERE visible = 1"
+);
+
+%chtxt_chname = map { $_->[0], $_->[1] } @{$ary_ref};
+
+# NHK BS 1/2/hiをBS/CSから除外(101-103) - by 2011/04
+# te: 地上波、BSのNHK以外
+# bc: BSのNHK、CS
+my @te_ary = grep $_->[0]=~ /^\d|BS_(?!10[1-3])/, @{$ary_ref};
+my @bc_ary = grep $_->[0]!~ /^\d|BS_(?!10[1-3])/, @{$ary_ref};
+
+# teの操作(まとめる)
+foreach my $line ( @te_ary ) {
+       # te xx_yyyy(chtxt) -> xx(ch)
+       if ( $line->[3] =~ /te/ ) {
+               push @{ $chtxt_0_chname{        $line->[2] . '_0'} }, $line->[1];
+       }
+       else {
+               push @{ $chtxt_0_chname{'BS_' . $line->[2]       } }, $line->[1];
+       }
+}
+foreach my $key ( keys %chtxt_0_chname ) {
+       my @chname = @{ $chtxt_0_chname{$key} };
+       if ( @chname >= 2 ) {
+               # 2つ以上ある場合
+               my @tmp = map { my @ary = split //, $_; \@ary } @chname;
+               # 1つ目と2つ目のみ比較
+               # FIXME: すべてを比較するべき
+               $chtxt_0_chname{$key} = join '', LCS( $tmp[0], $tmp[1] );
+       }
+       else {
+               # 1つしかない場合
+               $chtxt_0_chname{$key} = $chname[0];
+       }
+}
+
+# bs/csの操作(そのまま)
+foreach my $line ( @bc_ary ) {
+       $chtxt_0_chname{$line->[0]} = $line->[1];
+}
+undef $ary_ref;
+
+
+################ 定数宣言 ################
+
+
+tie %type, 'Tie::IxHash';
+%type = (
+       'search_everyday'          => '隔日検索',
+       'search_today'             => '当日検索',
+       'reserve_flexible'         => '浮動予約',
+       'reserve_fixed'            => '確定予約',
+
+       'reserve_running'          => '録画途中',
+
+       'convert_b25_ts'           => '解読予約',
+       'convert_b25_ts_running'   => '解読途中',
+       'convert_b25_ts_miss'      => '解読失敗',
+
+       'convert_ts_mp4'           => '縁故予約',
+       'convert_ts_mp4_running'   => '縁故於鯖',
+       'convert_ts_mp4_network'   => '縁故於網',
+       'convert_ts_mp4_finished'  => '縁故完了',
+
+       'convert_avi_mkv'          => '変換旧露',
+       'convert_avi_mp4'          => '変換旧四',
+       'convert_mkv_mp4'          => '変換露四',
+       'convert_mkv_mp4_runnings' => '換途露四',
+
+       'auto_suggest_dec'         => '予測解読',
+       'auto_suggest_enc'         => '予測縁故',
+       'auto_suggest_avi2fp'      => '予測旧四',
+       'auto_suggest_ap2fp'       => '予測露四',
+
+       'move_end'                 => '移動完了',
+);
+
+%type_suggest = (
+       'auto_suggest_dec'    => 'convert_b25_ts',
+       'auto_suggest_enc'    => 'convert_ts_mp4',
+       'auto_suggest_avi2fp' => 'convert_avi_mkv',
+       'auto_suggest_ap2fp'  => 'convert_mp4_mkv',
+);
+
+%color = (
+       'search_everyday'        => '#8B008B',
+       'search_today'           => '#8B008B',
+       'reserve_flexible'       => '#4169E1',
+       'reserve_fixed'          => '#4169E1',
+       'reserve_running'        => '#FF8C00',
+       'convert_b25_ts'         => '#CD5C5C',
+       'convert_b25_ts_running' => '#DC143C',
+       'convert_ts_mp4'         => '#32CD32',
+       'convert_ts_mp4_running' => '#2E8B57',
+       'convert_ts_mp4_network' => '#808000',
+
+       'other'                  => '#A0A0A0',
+);
+
+$type_user_made = "( 'search_everyday', 'search_today', 'reserve_flexible', 'reserve_fixed', 'reserve_running' )";
+
+%category = (
+       'etc'         => 'その他', 
+       'news'        => 'ニュース・報道', 
+       'variety'     => 'バラエティ', 
+       'anime'       => 'アニメ・特撮', 
+       'information' => '情報', 
+       'drama'       => 'ドラマ', 
+       'sports'      => 'スポーツ', 
+       'music'       => '音楽', 
+       'cinema'      => '映画', 
+);
+
+
+################ 初期化ここまで ################
+
+
+################ mode=schedule ################
+
+if ( $mode eq 'schedule' ) {
+
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Schedule Viewer/;
+       #$HTML =~ s|%REFRESH%|<meta http-equiv="refresh" content="300">|;
+       $css = <<EOM;
+               <style type="text/css">
+               td {
+                       white-space: nowrap;
+               }
+               </style>
+EOM
+       $css =~ s/^\t{2}//gm;
+       $HTML =~ s/%CSS%/$css/;
+
+       my $order = $params{ 'order' };
+       my $extra = $params{ 'extra' };
+       if ( $order ne 'id' ) {
+               $order = 'btime';
+       }
+       $reverse_extra = $extra            ? '' : '&amp;extra=1';
+       $forward_order = $order eq 'btime' ? '' : '&amp;order=id';
+
+       my $ary_ref = $dbh->selectall_arrayref(
+               "SELECT id, type, timeline.chtxt, epg_ch.chname, title, btime, etime, opt, deltaday, deltatime, 
+               epgtitle, epgbtime, epgetime, epgexp, epgduplicate, epgchange, counter 
+               FROM timeline 
+               LEFT OUTER JOIN epg_ch ON timeline.chtxt = epg_ch.chtxt 
+               ORDER BY $order"
+               , {Slice=>{}});
+
+       $HTML .= qq {<div style="font-size: 80%; float: left">\n};
+       $HTML .= qq {<form method="get" action="rectool.pl">\n};
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {<input type="hidden" name="mode" value="change">\n};
+       $HTML .= qq {<table summary="rectimetable" border=1 cellspacing=0>\n<tr>\n};
+       $HTML .= qq {<th><a href="rectool.pl?mode=schedule$forward_order$reverse_extra">■</a></th>\n};
+       $HTML .= qq {<th><a href="rectool.pl?mode=schedule&amp;order=id">ID</a></th>\n};
+       $HTML .= qq {<th>タイプ</th>\n};
+       $HTML .= qq {<th>チャンネル</th>\n};
+       $HTML .= qq {<th>タイトル</th>\n};
+       $HTML .= qq {<th><a href="rectool.pl?mode=schedule">開始時刻</a></th>\n};
+       $HTML .= qq {<th>終了時刻</th>\n};
+       $HTML .= qq {<th>録画時間</th>\n};
+       $HTML .= qq {<th>オプション</th>\n};
+       $HTML .= qq {<th>dd</th>\n};
+       $HTML .= qq {<th>dt</th>\n};
+       $HTML .= qq {<th>残り</th>\n};
+       $HTML .= qq {</tr>\n};
+       foreach my $line ( @{ $ary_ref } ) {
+
+               $type = $type{$line->{type}} || $line->{type};
+               if    ( $line->{type} =~ /^search/ ) {
+                       $type = qq {<span style="color: #8B008B">$type</span>};
+                       $line->{deltaday} = qq {<span style="color: #FF0000">空</span>} if ( !$line->{deltaday} && $line->{type} eq 'search_everyday' );
+                       $line->{deltatime} = qq {<span style="color: #FF0000">空</span>} if ( !$line->{deltatime} );
+               }
+               else {
+                       my $color = $color{$line->{type}} ? $color{$line->{type}} : $color{'other'};
+                       $type = qq {<span style="color: $color">$type</span>};
+               }
+               # 地上波の場合、xx_yyyをxx_0に置換する
+               ( $line->{chtxt_0} = $line->{chtxt} ) =~ s/(\d+)_/$1_0/;
+               # chnameが無いとき(移動縁故など)、chtxtを代わりに使う
+               $line->{chname} = 
+                       $line->{chname} || 
+                       $chtxt_0_chname{$line->{chtxt}} || 
+                       $chtxt_0_chname{$line->{chtxt_0}};
+               if ( !$line->{chname} ) {
+                       # chnameが無いとき、リンクを作成しない
+                       $line->{chname} = $line->{chtxt};
+                       $line->{chname_link} = qq {$line->{chname}</a>};
+               }
+               else {
+                       $line->{chname_link} = qq {<a href="rectool.pl?mode=program&amp;chtxt=$line->{chtxt}">$line->{chname}</a>};
+               }
+               $line->{title} = 'タイトルなし' if ( !$line->{title} );
+               $line->{tr_style} = '';
+               $line->{title_2} = '';
+               my $unix_b = str2datetime( $line->{btime} );
+               my $unix_e = str2datetime( $line->{etime} );
+
+               my $btime = $unix_b->strftime( '%Y%m%d%H%M%S' );
+               my $etime = $unix_e->strftime( '%Y%m%d%H%M%S' );
+               if ( $extra and $line->{type} =~ /^search_|^reserve_(?!running)/ ) {
+                       #my @ary = $dbh->selectrow_array(
+                       #       "SELECT title, exp FROM epg_timeline 
+                       #       WHERE channel = '$line->{chname}' 
+                       #       AND start = '$btime' 
+                       #       AND stop  = '$etime' ");
+                       #my @ary = ( $line->{epgtitle}, $line->{epgexp} );
+                       my ( $epgtitle, $epgexp ) = ( $line->{epgtitle}, $line->{epgexp} );
+
+                       if ( $epgtitle ) {
+                               $epgtitle =~ s/無料≫//;
+
+                               if ( $epgtitle ne $line->{title} ) {
+                                       # epgtitleとtitleが一致しない
+                                       # []に囲まれた部分を除去して比較
+                                       my @brackets = $line->{title} =~ /(\[.+\])+/;
+                                       my $epgtitle_nobrackets = $epgtitle;
+                                       my $title_nobrackets = $line->{title};
+                                       if ( @brackets && $epgtitle =~ /(\[.+\])+/ >= @brackets ) {
+                                               foreach ( @brackets ) {
+                                                       $epgtitle_nobrackets =~ s/\Q$_\E//;
+                                               }
+                                       }
+                                       $title_nobrackets =~ s/(\[.+\])+//;
+                                       if ( !scalar $epgtitle_nobrackets =~ s/\Q$title_nobrackets\E// ) {
+                                               # epgtitleにtitleが含まれていない
+                                               my $href  = qq {<a href="rectool.pl?mode=edit&amp;id=$line->{id}&amp;suggest=auto">自動検索</a>};
+                                               $epgtitle = qq {<span style="color: #FF4000">$epgtitle■$href■</span>};
+                                       }
+                                       else {
+                                               # epgtitleにtitleが含まれている
+                                               $epgtitle = $epgtitle_nobrackets;
+                                       }
+                               }
+                               else {
+                                       # epgtitleとtitleが一致している
+                                       $epgtitle = '説明';
+                               }
+
+                               $line->{title_2} = qq {<div style="float: right; cursor: help" title="$epgexp">$epgtitle</div>};
+                       }
+                       else {
+                               # epgtitleがない
+                               my $href    = qq {<a href="rectool.pl?mode=edit&amp;id=$line->{id}&amp;suggest=auto">自動検索</a>};
+                               $line->{title_2}  = qq {<span style="float: right; color: #FF0000">■$href■</span>};
+                               $line->{tr_style} = qq {style="background-color: #A0A0A0"};
+                       }
+               }
+
+               my ( $begin, $end, $diff ) = &str2readable( $unix_b, $unix_e );
+
+               my $hr = '';
+               if ( 
+                       $line->{type} eq 'reserve_running' 
+                               &&
+                       $unix_b->epoch <= time && time <= $unix_e->epoch
+               )
+               {
+                       $percent = int( ( 100 * ( time - $unix_b->epoch ) ) / ( $unix_e->epoch - $unix_b->epoch ) );
+                       $hr .= qq {<hr style="margin: 0 auto 0 0; height: 4px; width: $percent%;};
+                       $hr .= qq { background-color: blue; border: none" title="$percent%">};
+               }
+
+               $line->{title} = qq {<a href="rectool.pl?mode=edit&amp;id=$line->{id}">$line->{title}</a>};
+               #$line->{title} = qq {<div style="float: left">$line->{title}</div>} if ( $line->{title_2} );
+               $HTML .= qq {<tr align="center" $line->{tr_style}>\n};
+               $HTML .= qq {<td><input type="checkbox" name="id" value="$line->{id}"></td>\n};
+               $HTML .= qq {<td>$line->{id}</td>\n};
+               $HTML .= qq {<td>$type</td>\n};
+               $HTML .= qq {<td>$line->{chname_link}</td>\n};
+               $HTML .= qq {<td align="left" style="white-space: normal">$line->{title}$line->{title_2}</td>\n};
+               $HTML .= qq {<td>$begin</td>\n<td>$end</td>\n};
+               $HTML .= qq {<td>$hr$diff</td>\n};
+               $HTML .= qq {<td>$line->{opt}</td>\n<td>$line->{deltaday}</td>\n<td>$line->{deltatime}</td>\n<td>$line->{counter}</td>\n};
+               $HTML .= qq {</tr>\n};
+       }
+       $HTML .= qq {</table>\n};
+       #$HTML .= qq {<input type="submit" name="edit" value="編集(要JS)">\n};
+       $HTML .= qq {<input type="submit" name="delete" value="削除">\n</div>\n</form>\n};
+       goto end;
+}
+
+################ mode=graph ################
+
+if ( $mode eq 'graph' ) {
+
+       my $date = $params{ 'date' };
+
+       if ( $date )
+       {
+               print "Content-Type: image/svg+xml\n\n";
+
+               require SVG;
+               $date = Date::Simple->new( split /-/, $date );
+               $graph_bgn = $date->format('%Y-%m-%d');
+               $graph_end = $date->next->format('%Y-%m-%d');
+               $day = $date->day;
+               $today = $date eq Date::Simple->today() ? 1 : 0;
+
+               $tuner{terrestrial} = 2; #$cfg->param( 'env.te_max' );
+               $tuner{satellite}   = 2; #$cfg->param( 'env.bscs_max' );
+               $tuner{all} = $tuner{terrestrial} + $tuner{satellite};
+               $hours = 24;
+               $width = 30 * $hours;
+
+               $svg = new SVG( width => 820, height => $tuner{all} * 20 + 40 );
+               $svg->rectangle( 'x' => 40, 'y' => 20, 
+                       width => $width + 20, height => $tuner{all} * 20 + 10, 
+                       rx => 15, ry => 15, 
+                       style => { stroke => 'blue', fill => 'white' } );
+               for ( 1..$tuner{terrestrial} ) {
+                       $svg->text( 'x' => 10, 'y' => ( $_ + 1 ) * 20 )
+                               ->cdata( "T$_" );
+               }
+               for ( 1..$tuner{satellite} ) {
+                       $svg->text( 'x' => 10, 'y' => ( $_ + $tuner{terrestrial} + 1 ) * 20 )
+                               ->cdata( "S$_" );
+               }
+               for ( 0..$hours ) {
+                       $svg->text( 'x' => $_ * 30 + 65, 'y' => 15, 
+                               style => { 'text-anchor' => 'middle' } )
+                               ->cdata( sprintf( '%02d', $_ ) ) if ( $_ < $hours );
+                       # $svg->line( ); # can't be used when required
+                       $svg->tag( 'line', x1 => $_ * 30 + 50, x2 => $_ * 30 + 50, y1 => 30, y2 => $tuner{all} * 20 + 20, 
+                               style => { stroke => 'gray' } );
+               }
+               for ( 1..$tuner{all} ) {
+                       $svg->rectangle( 'x' => 50, 'y' => $_ * 20 + 10, width => $width, height => 10 );
+               }
+               if ( $today ) {
+                       require Time::Simple;
+                       my $time = Time::Simple->new();
+                       my $x = ( $time->hours * 60 + $time->minutes ) * 0.5 + 50;
+                       $svg->tag( 'line', x1 => $x, x2 => $x, y1 => 30, y2 => $tuner{all} * 20 + 20, 
+                               style => { stroke => 'red', 'fill-opacity' => '1.0' } );
+               }
+               foreach my $bctype ( 'te%', '_s%' ) {
+                       my $tuner = $bctype eq 'te%' ? $tuner{terrestrial} : $tuner{satellite};
+                       my $ary_ref = $dbh->selectall_arrayref(
+                               "SELECT id, title, timeline.chtxt, btime, etime, opt FROM timeline 
+                               INNER JOIN epg_ch ON timeline.chtxt = epg_ch.chtxt 
+                               WHERE epg_ch.bctype LIKE '$bctype' 
+                               AND type IN $type_user_made 
+                               AND 
+                               (
+                                       '$graph_bgn 00:00' <= btime AND btime <  '$graph_end 00:00'
+                                               OR
+                                       '$graph_bgn 00:00' <  etime AND etime <= '$graph_end 00:00'
+                               )
+                               ORDER BY id"
+                               , {Slice=>{}}
+                       );
+                       foreach my $line ( @{ $ary_ref } ) {
+                               @start = $line->{btime} =~ /(.{4})-(.{2})-(.{2}) (.{2}):(.{2})/;
+                               @stop  = $line->{etime} =~ /(.{4})-(.{2})-(.{2}) (.{2}):(.{2})/;
+                               $start = ( ( $day == $start[2] ? 0 : 24 * 60 ) + $start[3] * 60 + $start[4] ) * 0.5;
+                               $stop  = ( ( $day == $stop [2] ? 0 : 24 * 60 ) + $stop [3] * 60 + $stop [4] ) * 0.5;
+                               $start = 0      if ( $start < 0 || $day > $start[2] ); # 月の変わり目はスルー
+                               $stop  = $width if ( $stop  > $width );
+                               $begin = $line->{btime};
+                               $end   = $line->{etime};
+
+                               my $ary = $dbh->selectall_arrayref( 
+                                       "SELECT id, type, timeline.chtxt, title, btime, etime, opt FROM timeline 
+                                       INNER JOIN epg_ch ON timeline.chtxt = epg_ch.chtxt 
+                                       WHERE epg_ch.bctype LIKE '$bctype' 
+                                       AND type IN $type_user_made 
+                                       AND NOT 
+                                       ( 
+                                               ( etime <= '$begin' ) 
+                                                       OR 
+                                               ( btime >= '$end'   ) 
+                                       ) 
+                                       ORDER BY id" 
+                                       , {Slice=>{}}
+                               );
+                               my @ary = @{$ary};
+                               for ( 0..$tuner - 1 ) {
+                                       my $f = 1;
+                                       my $i = $_;
+                                       for ( 'chtxt', 'btime', 'etime' ) {
+                                               $f = 0 if ( $line->{$_} ne $ary[$i]->{$_} );
+                                       }
+                                       if ( $f ) {
+                                               $slot = $i;
+                                       }
+                               }
+                               my ( $r, $g, $b ) = ( 0, 0, 0 );
+                               $r += 255 if ( $line->{opt} =~ /a/ );
+                               $g += 255 if ( $line->{opt} =~ /H/ );
+                               $b += 255 if ( $line->{opt} =~ /I/ );
+                               if ( $r + $g + $b == 255 * 3 ){
+                                       $r = 0;
+                                       $g = 255;
+                                       $b = 255;
+                               }
+                               if ( $r + $g + $b == 0 ){
+                                       $r = $g = $b = 128;
+                               }
+                               my %escaped = ( '&' => 'amp', '<' => 'lt', '>' => 'gt', '"' => 'quot' );
+                               sub html_escape{
+                                   my $str = shift or return;
+                                   my $result = '';
+                                   $result .= $escaped{$_} ? '&' . $escaped{$_} . ';' : $_
+                                       for (split //, $str);
+                                   $result;
+                               }
+                               $svg->anchor(
+                                       -href  => "rectool.pl?mode=edit&amp;id=$line->{id}",
+                                       target => '_blank',
+                                       -title => html_escape( $line->{title} ),
+                               )->rectangle( 
+                                       'x' => 50 + $start, 
+                                       'y' => 30 + ( $bctype eq 'te%' ? 0 : $tuner{terrestrial} * 20 ) + $slot * 20, 
+                                       width  => $stop - $start, 
+                                       height => 10, 
+                                       style  => { fill => "rgb($r,$g,$b)" } );
+                       }
+               }
+               print $svg->xmlify;
+               exit;
+       }
+       else
+       {
+               $HTML =~ s/%HTML_TITLE_OPT%/ - Schedule Viewer - Graphical/;
+               $HTML .= qq {<div style="float: left">\n};
+               # $base64 = encode_base64( $svg->xmlify );
+               # $HTML .= qq {<object data="data:image/svg+xml;base64,$base64">\n</object>\n};
+               $HTML .= qq {予約状況一覧です。T1,T2は地上波、S1,S2はBS/CS、赤はアニメ、緑はHD、青はインターレースを示しています。<br>\n};
+               $HTML .= qq {SVGが利用可能なブラウザでご覧ください。<br>\n};
+
+               $ary_ref = $dbh->selectcol_arrayref(
+                       "SELECT DISTINCT DATE( btime ) 
+                       FROM timeline 
+                       WHERE type in $type_user_made 
+                       ORDER BY btime"
+               );
+               foreach my $date ( @{ $ary_ref } ) {
+                       my @date = $date =~ /(.{4})-(.{2})-(.{2})/;
+                       my $dn = DateTime->new( year => $date[0], month => $date[1], day => $date[2], locale => 'ja_JP' )->day_name;
+                       #utf8::encode( $dn );
+                       $HTML .= qq {$date[1]/$date[2]($dn)の予約状況<br>\n};
+                       # <img src="">
+                       $HTML .= qq {<object type="image/svg+xml" data="rectool.pl?mode=graph&amp;date=$date" width="820">\n};
+                       $HTML .= qq {SVG Image $date\n</object>\n<br>\n};
+
+                       $date2 = Date::Simple->new( @date )->next->format('%Y-%m-%d');
+                       my $ary_ref = $dbh->selectall_arrayref(
+                               "SELECT chtxt, title, btime, etime FROM timeline 
+                               WHERE '$date 00:00' <= btime AND etime <= '$date2 01:00'
+                               ORDER BY btime"
+                       );
+
+                       foreach my $line ( @{ $ary_ref } ) {
+                               #$HTML .= qq {$line->[0] $line->[1] $line->[2] $line->[3]<br>\n};
+                       }
+
+               }
+
+               goto end;
+       }
+}
+
+################ mode=atom ################
+
+if ( $mode eq 'atom' ) {
+       require XML::Atom::Feed;
+       require XML::Atom::Entry;
+
+       my $recording_count = $encoding_count = $jbk_count = 0;
+       my $ary_ref = $dbh->selectall_arrayref(
+               "SELECT chtxt, title, btime, etime, opt 
+               FROM timeline 
+               WHERE type = 'reserve_running' ");
+       foreach my $line ( @{$ary_ref} ) {
+               my ( $begin, $end, $diff ) = &str2readable( $line->[2], $line->[3] );
+               $recording_status .= qq {$line->[0] $line->[1] $begin - $end $diff $line->[4]<br />\n};
+               $recording_count++;
+       }
+       $ary_ref = $dbh->selectall_arrayref(
+               "SELECT chtxt, title, btime, etime, opt 
+               FROM timeline 
+               WHERE type = 'convert_ts_mp4_running' ");
+       foreach my $line ( @{$ary_ref} ) {
+               my ( $begin, $end, $diff ) = &str2readable( $line->[2], $line->[3] );
+               $encoding_status .= qq {$line->[0] $line->[1] $begin - $end $diff $line->[4]<br />\n};
+               $encoding_count++;
+       }
+       $ary_ref = $dbh->selectall_arrayref(
+               "SELECT id, chtxt, title, btime, etime 
+               FROM auto_timeline_keyword " );
+       foreach my $line ( @{$ary_ref} ) {
+               my ( $begin, $end, $diff ) = &str2readable( $line->[3], $line->[4] );
+               $jbk_status .= qq {$line->[0] $line->[1] $line->[2] $begin - $end $diff<br />\n};
+               $jbk_count++;
+       }
+
+       my $feed = XML::Atom::Feed->new( Version => 1.0 );
+       $feed->title('Rec10 フィード');
+
+       my $entry = XML::Atom::Entry->new( Version => 1.0 );
+       $entry->title("Rec10 録画状況 ($recording_count)");
+       $entry->id('tag:recording_status');
+       $entry->content($recording_status);
+       $entry->add_link(str_to_link( './rectool.pl?mode=schedule' ) );
+       $feed->add_entry($entry);
+
+       $entry = XML::Atom::Entry->new( Version => 1.0 );
+       $entry->title("Rec10 縁故状況 ($encoding_count)");
+       $entry->id('tag:encoding_status');
+       $entry->content($encoding_status);
+       $entry->add_link(str_to_link( './rectool.pl?mode=schedule' ) );
+       $feed->add_entry($entry);
+
+       $entry = XML::Atom::Entry->new( Version => 1.0 );
+       $entry->title("Rec10 地引状況 ($jbk_count)");
+       $entry->id('tag:jbk_status');
+       $entry->content($jbk_status);
+       $entry->add_link(str_to_link( './rectool.pl?mode=jbk' ) );
+       $feed->add_entry($entry);
+
+       my $xml = $feed->as_xml;
+       print "Content-Type: application/atom+xml\n\n";
+       print $xml;
+       exit;
+
+       sub str_to_link {
+               my $link = XML::Atom::Link->new( Version => 1.0 );
+               $link->type('text/html');
+               $link->rel('alternate');
+               $link->href(shift);
+               return $link;
+       }
+}
+
+################ mode=edit ################
+
+if ( $mode eq 'edit' ) {
+       my $id = $params{ 'id' };
+
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Schedule Editor/;
+       $HTML .= qq {<div style="float: left">\n};
+
+       $script = <<EOM;
+               <script type="text/javascript" src="http://www.enjoyxstudy.com/javascript/dateformat/dateformat.js">
+               </script>
+               <script type="text/javascript">
+               function setType(value){
+                       var index = document.reserve.type.selectedIndex;
+                       var value = document.reserve.type[index].value;
+                       if ( value == 'search_everyday' ) {
+                               document.reserve.deltaday.value  = 7;
+                               document.reserve.deltatime.value = 3;
+                       }
+                       if ( value == 'convert_b25_ts' || value == 'convert_ts_mp4' ){
+                               var date       = new Date();
+                               var dateFormat = new DateFormat("yyyy-MM-dd HH:mm:ss");
+                               var minutes    = date.getMinutes();
+                               minutes = minutes - minutes % 5 + 10;
+                               date.setMinutes(minutes, 0, 0);
+                               document.reserve.begin.value = dateFormat.format(date);
+                               date.setSeconds( date.getSeconds() + 3600 );
+                               document.reserve.end.value   = dateFormat.format(date);
+                       }
+               }
+               function setSuggest(start, stop){
+                       document.reserve.begin.value = start;
+                       document.reserve.end.value   = stop;
+               }
+               function shiftEndTime(value){
+                       var dateFormat = new DateFormat("yyyy-MM-dd HH:mm:ss");
+                       var date = dateFormat.parse(document.reserve.end.value || document.reserve.begin.value);
+                       date.setSeconds( date.getSeconds() + value );
+                       document.reserve.end.value = dateFormat.format(date);
+               }
+               </script>
+EOM
+       $script =~ s/^\t{2}//gm;
+       $HTML =~ s/%SCRIPT%/$script/;
+
+       $HTML .= "スケジュール編集画面です。<br>\n";
+       $HTML .= "実装がとても適当なので、利用には細心の注意を払ってください。<br>\n<br>\n";
+       if ( $id ) {
+               # 予約の編集
+               &parse_program();
+               $button_bgn = $button_end = '';
+       }
+       else {
+               # 新規予約
+               $type = 'reserve_flexible';
+               $counter = -1;
+               $datetime_now = DateTime->now( time_zone => $tz )->set_second( 0 )->add( minutes => 1)->strftime( '%Y-%m-%d %H:%M:%S' );
+               $button_bgn = qq{<button type="button" onClick="document.reserve.begin.value='$datetime_now'">現在</button>\n<br>\n};
+               $button_end = 
+                        qq{<button type="button" onClick="document.reserve.end.value=document.reserve.begin.value">一致</button>}
+                       .qq{<button type="button" onClick="shiftEndTime(300);">+5m</button>}
+                       .qq{<button type="button" onClick="shiftEndTime(1800);">+30m</button>};
+       }
+
+       if ( $params{ 'suggest' } eq 'auto' ) {
+               my @btime = $begin =~ /(.{4})-(.{2})-(.{2}) (.{2}):(.{2}):(.{2})/;
+               my @etime = $end   =~ /(.{4})-(.{2})-(.{2}) (.{2}):(.{2}):(.{2})/;
+               my $btime = DateTime->new(
+                       year => $btime[0], month  => $btime[1], day    => $btime[2],
+                       hour => $btime[3], minute => $btime[4], second => $btime[5], 
+               );
+               my $etime = DateTime->new(
+                       year => $etime[0], month  => $etime[1], day    => $etime[2],
+                       hour => $etime[3], minute => $etime[4], second => $etime[5], 
+               );
+               my %hash = &sqlgetsuggested( $btime, $etime );
+
+               $HTML .= qq {可能性のある番組<br>\n};
+               $HTML .= qq {<table summary="suggesttable" border=1 cellspacing=0>\n<tr>\n};
+               $HTML .= qq {<th>優先度</th>\n};
+               $HTML .= qq {<th>タイトル</th>\n};
+               $HTML .= qq {<th>開始時刻</th>\n};
+               $HTML .= qq {<th>終了時刻</th>\n};
+               $HTML .= qq {<th>説明</th>\n};
+               $HTML .= qq {<th>適用</th>\n};
+               $HTML .= qq {</tr>\n};
+
+               foreach my $key (sort keys %hash){
+                       my $val = $hash{$key};
+                       foreach my $val ( @{$val} ) {
+                               my $style = qq {style="white-space: nowrap"};
+                               $val->[0] =~ s/(.{4})(.{2})(.{2})(.{2})(.{2})(.{2})/$1-$2-$3 $4:$5:$6/;
+                               $val->[1] =~ s/(.{4})(.{2})(.{2})(.{2})(.{2})(.{2})/$1-$2-$3 $4:$5:$6/;
+                               $HTML .= qq {<tr>\n<td>$key</td>\n<td>$val->[2]</td>\n};
+                               $HTML .= qq {<td $style>$val->[0]</td>\n<td $style>$val->[1]</td>\n<td>$val->[3]</td>\n};
+                               $HTML .= qq {<td><button onClick="setSuggest('$val->[0]','$val->[1]');">適用</button></td>\n</tr>\n};
+                       }
+               }
+               $HTML .= qq {</table>\n<br>\n};
+       }
+
+       my $len = length $id;
+       $HTML .= qq {<form method="get" action="rectool.pl" name="reserve">\n};
+       $HTML .= qq {<input type="hidden" name="mode" value="change">\n};
+       $HTML .= qq {<input type="hidden" name="mode_sub" value="update">\n};
+       $HTML .= qq {<input type="hidden" name="id" value="$id">\n};
+       $HTML .= qq {ID\n<input type="text" name="id" value="$id" size=$len disabled>\n};
+       $HTML .= qq {タイプ\n<select name="type" onChange="setType();">\n};
+       foreach my $key ( keys %type ) {
+               next if ( $key !~ /^search|^reserve_flexible$|^reserve_fixed$|^convert_b25_ts$|^convert_ts_mp4$|^$type$/ );
+               $value = $type{$key};
+               if ( $key eq $type ) {
+                       $HTML .= qq {<option value="$key" selected>$value</option>\n};
+               }
+               else {
+                       $HTML .= qq {<option value="$key">$value</option>\n};
+               }
+       }
+       $HTML .= qq {</select>\n};
+
+       $HTML .= qq {チャンネル\n<select name="chtxt">\n};
+       # 移動縁故など、チャンネルリスト内にchtxtが存在しない場合に備えて
+       $chtxt_0_chname{$chtxt} = $chname || $chtxt if ( !$chtxt_0_chname{$chtxt} );
+       foreach my $key ( sort keys %chtxt_0_chname ) {
+               if ( $key eq $chtxt || $key eq $chtxt_0 ) {
+                       $HTML .= qq {<option value="$key" selected>$chtxt_0_chname{$key}</option>\n};
+               }
+               else {
+                       $HTML .= qq {<option value="$key">$chtxt_0_chname{$key}</option>\n};
+               }
+       }
+       $HTML .= qq {</select><br>\n};
+       $HTML .= qq {タイトル\n<input type="text" name="title" value="$title" size=64><br>\n};
+       $HTML .= qq {開始時刻\n<input type="text" name="begin" value="$begin" maxlength=19 size=24>\n};
+       $HTML .= $button_bgn;
+       $HTML .= qq {終了時刻\n<input type="text" name="end" value="$end" maxlength=19 size=24>\n};
+       $HTML .= $button_end . "<br>\n";
+       $HTML .= qq {隔日周期\n<input type="text" name="deltaday" value="$deltaday" maxlength=2  size=2 >\n};
+       $HTML .= qq {時刻誤差\n<input type="text" name="deltatime" value="$deltatime" maxlength=2  size=2 >\n};
+       $HTML .= qq {オプション\n<input type="text" name="opt" value="$opt">\n};
+       $HTML .= qq {回数\n<input type="text" name="counter" value="$counter" size=2 >\n};
+       $HTML .= qq {<input type="submit" name="update" value="更新">\n</form>\n};
+}
+
+################ mode=change ################
+
+if ( $mode eq 'change' ) {
+       @id     = $q->param( 'id' );
+
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Change/;
+       $HTML .= qq {<div style="float: left">\n};
+
+       if ( $params{ 'delete' } )
+       {
+               if ( @id ) {
+                       foreach my $id ( @id ) {
+                               $dbh->do( "DELETE FROM timeline WHERE id = '$id'" );
+                       }
+                       $HTML .= "削除しました。<br>\n5秒後に予約確認画面に移動します。<br>\n";
+                       $HTML =~ s|%REFRESH%|<meta http-equiv="refresh" content="5; url=rectool.pl?mode=schedule">|;
+                       goto end;
+               }
+       }
+       if ( $params{ 'update' } )
+       {
+               $type      = $params{ 'type' };
+               $chtxt     = $params{ 'chtxt' };
+               $title     = $params{ 'title' };
+               $begin     = $params{ 'begin' };
+               $end       = $params{ 'end' };
+               $deltaday  = $params{ 'deltaday' };
+               $deltatime = $params{ 'deltatime' };
+               $opt       = $params{ 'opt' };
+               $counter   = $params{ 'counter' };
+               $id        = $id[0];
+               if ( $id ) {
+                       $dbh->do( 
+                               "UPDATE timeline SET type = '$type', chtxt = '$chtxt', title = '$title', 
+                               btime = '$begin', etime = '$end', 
+                               deltaday = '$deltaday', deltatime = '$deltatime', opt = '$opt', counter = '$counter' 
+                               WHERE id = '$id'" 
+                       );
+               }
+               else {
+                       $dbh->do( 
+                               "INSERT INTO timeline ( type, chtxt, title, btime, etime, deltaday, deltatime, opt, counter ) 
+                               VALUES ( '$type', '$chtxt', '$title', '$begin', '$end', '$deltaday', '$deltatime', '$opt', '$counter' )" 
+                       );
+               }
+               $HTML .= "更新しました。<br>\n5秒後に予約確認画面に移動します。<br>\n";
+               $HTML =~ s|%REFRESH%|<meta http-equiv="refresh" content="5; url=rectool.pl?mode=schedule">|;
+               goto end;
+       }
+       if ( $mode_sub eq 'proc' ) {
+               my $type  = $params{ 'type' };
+               my $chtxt = $params{ 'chtxt' } || 'nhk-k';
+               my $title = $params{ 'title' };
+               my @opt   = $q->param( 'opt' );
+               my $opt   = join '', @opt;
+
+               my $datetime_now = DateTime->now( time_zone => $tz )->set_second( 0 )->add( minutes => 10);
+               my $sql_type = $type_suggest{$type};
+               my $begin = $datetime_now->strftime( '%Y-%m-%d %H:%M:%S' );
+               $datetime_now = $datetime_now->add( minutes => 60 );
+               my $end = $datetime_now->strftime( '%Y-%m-%d %H:%M:%S' );
+
+               $dbh->do( 
+                       "INSERT INTO timeline ( type, chtxt, title, btime, etime, opt ) 
+                       VALUES ( '$sql_type', '$chtxt', '$title', '$begin', '$end', '$opt' )"
+               );
+
+               goto end;
+       }
+       if ( $mode_sub eq 'move' ) {
+               my $mode_sub2  = $params{ 'mode_sub2' };
+               my $title      = $params{ 'title' };
+               my $response;
+
+               $ENV{'LANG'} = 'ja_JP.UTF-8';
+               if ( $mode_sub2 eq 'predict' ) {
+                       $HTML .= "移動後のシミュレーション結果です。\n<br>";
+                       eval '$response = `python26 ' . $cfg->param( 'path.rec10' ) . "/classify.py -s '$title'`";
+               }
+               elsif ( $mode_sub2 eq 'exec' ) {
+                       eval '$response = `python26 ' . $cfg->param( 'path.rec10' ) . "/classify.py -e '$title'`";
+               }
+               utf8::decode( $response );
+               $HTML .= $response;
+
+               goto end;
+       }
+       if ( $mode_sub eq 'setting' ) {
+               my $jbk     = $params{ 'jbk' }     || '0';
+               my $bayes   = $params{ 'bayes' }   || '0';
+               my $del_tmp = $params{ 'del_tmp' } || '0';
+               my $opt     = $params{ 'opt' }     || '';
+               my $user    = $params{ 'user' }    || '';
+               my $pass    = $params{ 'pass' }    || '';
+
+               $dbh->do( 
+                       "UPDATE in_settings SET auto_jbk = '$jbk', auto_bayes = '$bayes', 
+                       auto_del_tmp = '$del_tmp', auto_opt = '$opt'"
+               );
+
+               goto end;
+       }
+       if ( $mode_sub eq 'fixstatus' ) {
+               my $key = $params{ 'terec'  } ? 'terec'  : $params{ 'bscsrec' } ? 'bscsrec' : 
+                         $params{ 'b252ts' } ? 'b252ts' : $params{ 'ts2avi'  } ? 'ts2avi'  : '';
+
+               $dbh->do( 
+                       "UPDATE in_status SET $key = 0"
+               );
+
+               goto end;
+       }
+
+}
+
+################ mode=confirm ################
+
+if ( $mode eq 'confirm' ) {
+       if ( $mode_sub eq 'reserve' ) {
+               $HTML =~ s/%HTML_TITLE_OPT%/ - Reserver/;
+               $HTML .= qq {<div style="float: left">\n};
+               &parse_program();
+
+               my $duration = ( str2datetime( $end ) - str2datetime( $begin ) )->delta_minutes;
+               $HTML .= "番組名:$title<br>\nチャンネル:$chname<br>\n放送継続時間:$duration 分<br>\n番組内容:$desc<br>\n";
+               if ( $longdesc ) {
+                       $longdesc =~ s/\\n/<br>\n/gs;
+                       $HTML .= "番組内容(長):$longdesc<br>\n";
+               }
+               my $error = &check_error();
+               if ( $error )
+               {
+                       # エラー
+
+                       $ary_ref = $dbh->selectall_arrayref(
+                               "SELECT start, stop FROM epg_timeline WHERE channel = '$chtxt' AND title = '$title' "
+                       );
+                       if ( $error != 1 ) {
+                               $HTML .= "同一の番組の他の放送予定です。<br>\n";
+                               foreach my $line ( @{$ary_ref} ) {
+                                       $begin = $line->[0];
+                                       $end   = $line->[1];
+                                       $begin =~ s/(.{4})(.{2})(.{2})(.{2})(.{2})(.{2})/$1-$2-$3 $4:$5:$6/;
+                                       $end   =~ s/(.{4})(.{2})(.{2})(.{2})(.{2})(.{2})/$1-$2-$3 $4:$5:$6/;
+                                       $overlap = &get_overlap() >= 2 ? '不可能' : 
+                                               qq {<a href="rectool.pl?mode=confirm&amp;mode_sub=reserve&amp;chtxt=$chtxt&amp;start=$line->[0]&amp;stop=$line->[1]">可能</a>};
+                                       $HTML .= "開始:$begin\n終了:$end\n録画は$overlap<br>\n";
+                               }
+                       }
+               }
+               else {
+                       $HTML .= "録画予約の詳細設定を行ってください。<br>\n";
+                       $HTML .= qq {<form method="get" action="rectool.pl">\n};
+                       $HTML .= qq {<input type="hidden" name="mode"  value="reserve">\n};
+                       $HTML .= qq {<input type="hidden" name="chtxt" value="$chtxt">\n};
+                       $HTML .= qq {<input type="hidden" name="start" value="$start">\n};
+                       $HTML .= qq {<input type="hidden" name="stop"  value="$stop">\n};
+                       $HTML .= qq {<input type="hidden" name="title" value="$title">\n} if ( $params{ 'title' } );
+                       &draw_form_opt( 'reserve' );
+                       $HTML .= qq {<input type="submit" value="予約">\n</form>\n};
+               }
+               goto end;
+       }
+       # End of $mode_sub eq 'reserve';
+
+       if ( $mode_sub eq 'proc' ) {
+               my    $type  = $params{ 'type' };
+               local $chtxt = $params{ 'chtxt' };
+               my    $title = $params{ 'title' };
+               local $opt   = $params{ 'opt' };
+               utf8::decode( $title );
+
+               $HTML .= "詳細設定を行ってください。<br>\n";
+               $HTML .= "タイトル:$title\n<br>\n";
+
+               $HTML .= qq {<form method="get" action="rectool.pl">\n};
+               $HTML .= qq {<input type="hidden" name="mode"     value="change">\n};
+               $HTML .= qq {<input type="hidden" name="mode_sub" value="proc">\n};
+               $HTML .= qq {<input type="hidden" name="type"     value="$type">\n};
+               $HTML .= qq {<input type="hidden" name="title"    value="$title">\n};
+               &draw_form_channel( 'nonone' );
+               &draw_form_opt();
+               $HTML .= qq {<input type="submit" value="予約">\n</form>\n};
+               goto end;
+       }
+}
+
+################ mode=reserve ################
+
+if ( $mode eq 'reserve' ) {
+       $HTML .= qq {<div style="float: left">\n};
+       &parse_program();
+       $title = $params{ 'title' } if ( !$title );
+       @opt = $q->param( 'opt' );
+       $opt = join '', @opt;
+       my ( $deltaday, $deltatime );
+
+       if ( $params{'every'} eq '1' ) {
+               $type = 'search_everyday';
+               ( $changed_t ) = $title =~ /(.*)#/;
+               $title = $changed_t if ( $changed_t );
+               ( $changed_t ) = $title =~ /(.*)第/;
+               $title = $changed_t if ( $changed_t );
+               ( $changed_t ) = $title =~ /(.*)▽/;
+               $title = $changed_t if ( $changed_t );
+               $title =~ s/「.*」//;
+               $title =~ s/<.*>//;
+               $title =~ s/(.*)//;
+               $title =~ s/\[新\]//;
+               $title =~ s/無料≫//;
+               $title =~ s/\s*$//;
+               $deltaday  = 7;
+               $deltatime = 3;
+       }
+       else {
+               $type = 'reserve_flexible';
+       }
+       $chtxt = $chtxt_0 if ( $chtxt_0 );
+       if ( !&check_error ) {
+               $dbh->do( 
+                       "INSERT INTO timeline ( type, chtxt, title, btime, etime, opt, deltaday, deltatime ) 
+                       VALUES ( '$type', '$chtxt', '$title', '$begin', '$end', '$opt', '$deltaday', '$deltatime' )" 
+               );
+       }
+       $HTML .= "録画予約を実行しました。<br>\n5秒後にトップへ移動します。<br>\n";
+       $HTML =~ s|%REFRESH%|<meta http-equiv="refresh" content="5; url=rectool.pl">|;
+       goto end;
+}
+
+################ mode=program ################
+
+if ( $mode eq 'program' ) {
+       &draw_form();
+
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Program Viewer/;
+       $unix = DateTime->now( time_zone => $tz )->strftime( '%Y%m%d%H%M%S' );
+       $sql = 
+               "SELECT channel, epg_ch.chname, start, stop, title, category 
+               FROM epg_timeline 
+               INNER JOIN epg_ch ON epg_timeline.channel = epg_ch.chtxt 
+               WHERE $unix <= stop %CH% %DATE% %CATEGORY% %KEY% ORDER BY start";
+
+       if ( $chtxt ) {
+               my $ch;
+               if ( $chtxt =~ /^\d+(_0)?$/ ) {
+                       # teはxx_yyy形式であるため
+                       $chtxt =~ s/_0//;
+                       $ch = "AND channel LIKE '$chtxt\_%'";
+               }
+               else {
+                       $ch = "AND channel = '$chtxt'";
+               }
+               $sql =~ s/%CH%/$ch/;
+       }
+       if ( $date_sel ) {
+               $date_1 = $date_sel . '000000';
+               $date_2 = Date::Simple->new( $date_sel =~ /(.{4})(.{2})(.{2})/ )->next->format('%Y%m%d') . '000000';
+               my $date = "AND '$date_1' <= stop AND start <= '$date_2'";
+               $sql =~ s/%DATE%/$date/;
+       }
+       if ( $category_sel ) {
+               # 一時的
+               #       $category_tmp = $category{$category_sel} . $category_sel;
+               my $category = "AND category = '$category{$category_sel}'";
+               $sql =~ s/%CATEGORY%/$category/;
+       }
+       if ( $key ) {
+               my $key = "AND TITLE LIKE '%$key%'";
+               $sql =~ s/%KEY%/$key/;
+       }
+       $sql =~ s/%CH%//;
+       $sql =~ s/%DATE%//;
+       $sql =~ s/%KEY%//;
+       $sql =~ s/%CATEGORY%//;
+
+       $ary_ref = $dbh->selectall_arrayref( $sql );
+       foreach my $prg ( @{ $ary_ref } ) {
+               my @date = $prg->[2] =~ /(.{4})(.{2})(.{2})(.{2})(.{2})(.{2})/;
+
+               $date = $date[2];
+               if ( $date != $prev ) {
+                       my $date = DateTime->new(
+                               year => $date[0], month  => $date[1], day    => $date[2], 
+                               locale => 'ja_JP'
+                       );
+
+                       my $dn = $date->day_name;
+                       #utf8::encode( $dn );
+                       $HTML .= qq {--------$date[1]/$date[2]($dn)--------<br>\n};
+               }
+               $HTML .= qq {$date[1]/$date[2] $date[3]:$date[4] };
+               $HTML .= qq {$prg->[1] } if ( !$chtxt );
+               $HTML .= qq {<a href="rectool.pl?mode=confirm&amp;mode_sub=reserve&amp;chtxt=$prg->[0]&amp;start=$prg->[2]&amp;stop=$prg->[3]">$prg->[4]</a><br>\n};
+               $prev = $date;
+       }
+}
+
+################ mode=list ################
+
+if ( $mode eq 'list' ) {
+       $HTML =~ s/%HTML_TITLE_OPT%/ - List/;
+       $HTML .= qq {<div>\n};
+
+       my $recording   = $cfg->param( 'path.recpath' );
+       my $ts_movepath = $cfg->param( 'path.ts_movepath' );
+       my $recorded    = $cfg->param( 'path.recorded' );
+
+       if ( $mode_sub eq 'log' ) {
+               my $title = $params{ 'title' };
+               my $log = slurp( "$recording/$title.log" ) if ( -e "$recording/$title.log" );
+               utf8::decode( $log );
+               $HTML .= '<pre>'.$log."</pre>\n";
+               goto end;
+       }
+       if ( !$mode_sub ) {
+               $HTML .= qq {<a href="rectool.pl?mode=list&amp;mode_sub=new">録画中のみ</a>\n};
+               $HTML .= qq {<a href="rectool.pl?mode=list&amp;mode_sub=old">録画後のみ</a>\n<br>\n};
+       }
+       if ( !$mode_sub || $mode_sub eq 'new' ) {
+               $HTML .= "録画中のファイル一覧<br>\n";
+               &list( $recording );
+       }
+       if ( !$mode_sub ) {
+               $HTML .= "<br>\n";
+       }
+       if ( !$mode_sub || $mode_sub eq 'old' ) {
+               $HTML .= "録画後のファイル一覧<br>\n";
+               &simple_list( $ts_movepath );
+               &simple_list( $recorded );
+       }
+
+       sub list {
+               local $path = shift;
+               local %list = ();
+               my @exp = ( 'log', 'log.zip', 'ts.b25', 'ts.tsmix', 'ts', 'ts.log', 
+                       'aac', 'srt', 'm2v', 'wav', '264', 'mp4', 'mkv' );
+               for ( 0..$#exp ) {
+                       $exp{$exp[$_]} = $_;
+               }
+               my $exp_count = scalar keys %exp;
+
+               &get_file_list_wrapper( $path, \&wanted );
+
+               my $help;
+               foreach my $name ( sort { $exp{$a} <=> $exp{$b} } keys %exp ) {
+                       $help .= $exp{$name} + 1 . " = $name / ";
+               }
+               $HTML .= $help;
+               $help  = qq {<tr style="background-color: #87CEEB"><td>$help\n</td>\n};
+               $help .= qq {<td>$_</td>\n} for ( 1..$exp_count );
+               $help .= qq {<td colspan="2">自動移動</td>\n</tr>\n};
+               $help .= qq {<tr>\n</tr>\n};
+
+               $HTML .= qq {<br>\n○ = 完了 / ● = 書き込み中 / ◆ = ファイルサイズ異常<br>\n};
+               $HTML .= qq {<table summary="listtable" border=1 cellspacing=0>\n<tr>\n};
+               $HTML .= qq {<th>タイトル</th>\n};
+               $HTML .= qq {<th>$_</th>\n} for ( 1..$exp_count );
+               $HTML .= qq {<th colspan="2">自動移動</th>\n};
+               $HTML .= qq {</tr>\n};
+
+               my $count = 0;
+
+               foreach my $title ( sort keys %list ) {
+                       my $value = $list{$title};
+                       my @flag = ( 0 ) x ( $exp_count );
+                       $HTML .= qq {<tr>\n<td width="600" style="width: 600px; white-space: normal">$title</td>\n};
+                       foreach my $exp ( keys %{$value} ) {
+                               if ( $exp eq 'log' ) {
+                                       my $title = $q->escape( $title );
+                                       my $check = qq {<td><a href="rectool.pl?mode=list&amp;mode_sub=log&amp;title=$title">○</a></td>\n};
+
+                                       $value->{$exp}->{check} = $check;
+                               }
+                               elsif ( $exp eq 'mkv' ) {
+                                       my $title = $q->escape( $title );
+
+                                       my $check = qq {<td><a title="$value->{$exp}->{size}" href="rectool.pl?mode=thumb&amp;title=$title">■</a></td>\n};
+                                       $value->{$exp}->{check} = $check;
+                               }
+                               $flag[$exp{$exp}] = $value->{$exp};
+                       }
+                       if ( !$flag[$exp{'mkv'}] ) {
+                               $flag[@flag]->{check} = qq {<td colspan="2"><br></td>\n};
+                       }
+                       else {
+                               my $title = $q->escape( $title );
+
+                               $flag[@flag]->{check} = 
+                                       qq {<td><a href="rectool.pl?mode=change&amp;mode_sub=move&amp;mode_sub2=predict&amp;title=$title">予測</a></td>\n}.
+                                       qq {<td><a href="rectool.pl?mode=change&amp;mode_sub=move&amp;mode_sub2=exec&amp;title=$title">実行</a></td>\n};
+                       }
+                       foreach ( @flag ) {
+                               my $size = $_->{size};
+                               my $last = $_->{last} || ( $_->{size} eq '0 B' ? '◆' : '○' );
+                               my $check =  $size ? qq {<span title="$size">$last</span>} : '<br>';
+                               $HTML .= $_->{check} ? $_->{check} : qq {<td>$check</td>\n};
+                       }
+                       $HTML .= qq {</tr>\n};
+                       $HTML .= $help unless ( ++$count % 20 );
+               }
+               $HTML .= qq {</table>\n};
+
+               sub wanted {
+                       my $rel = shift;
+                       my $abs = shift;
+
+                       return if ( $rel =~ /Thumbs\.db/ );
+                       return if ( $rel =~ /\.idx/ );
+
+                       $rel =~ s/\.temp$//;
+                       my $regexp = join '|', keys %exp;
+                       my ( $title, $exp ) = $rel =~ /(.*?)\.($regexp)$/;
+                       my ( $size, $last ) = &get_size( $abs );
+                       $rel =~ s/\.temp$//;
+                       if ( !$title ) {
+                               $title = '_error_exp_'.$rel;
+                               $exp   = 'log';
+                       }
+                       if ( $title !~ /[^0-9A-F]+/ ) {
+                               my $tmp = pack( 'H*', $title );
+                               if ( !$tmp ) {
+                                       $title = '_error_b16_'.$rel;
+                                       $exp   = 'log';
+                               }
+                               else {
+                                       $title = 'Base16_'.$tmp;
+                               }
+                       }
+                       $list{$title}->{$exp} = { 'last' => $last, 'size' => $size };
+               }
+       }
+
+       sub simple_list {
+               require Encode;
+
+               local $path = shift;
+               local @list = ();
+
+               &get_file_list_wrapper( $path, \&simple_wanted );
+
+#              @list = sort @list;
+               # natural sortを行う
+                       #@list = map( Encode::decode_utf8( $_ ), @list );
+                       @list = nsort @list;
+                       #@list = map( Encode::encode_utf8( $_ ), @list );
+
+               foreach ( @list ) {
+                       $HTML .= "$_<br>\n";
+               }
+
+               sub simple_wanted {
+                       my $rel = shift;
+                       my $abs = shift;
+
+                       my ( $size ) = &get_size( $abs );
+                       push @list, $rel ."\t\t". $size;
+               }
+       }
+
+       sub get_size {
+               my $file = shift;
+               my ( $size, $last ) = (stat( $file ))[7,9];
+               my @unim = ("B","KiB","MiB","GiB","TiB","PiB");
+               my $count = 0;
+
+               while($size >= 1024 ){
+                       $count++;
+                       $size = $size / 1024;
+               }
+               $size *= 100;
+               $size  = int( $size );
+               $size /= 100;
+               if ( time - $last < 10 ) {
+                       $last = '●';
+               }
+               else {
+                       $last = '';
+               }
+               return ( "$size $unim[$count]", $last );
+       }
+}
+
+################ mode=thumb ################
+
+if ( $mode eq 'thumb' ) {
+       my $title = $params{ 'title' };
+       my $pos  = $params{ 'pos' };
+       my $recording = $cfg->param( 'path.recpath' );
+
+       print "Content-Type: image/jpeg\n\n";
+       exec "ffmpeg -ss 300 -i '$recording/$title.mkv' -f image2 -pix_fmt jpg -vframes 1 -s 320x240 -";
+       exit;
+}
+
+################ mode=check ################
+
+if ( $mode eq 'check' ) {
+}
+
+################ mode=bravia ################
+
+if ( $mode eq 'bravia' ) {
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Bravia/;
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {<form method="get" action="rectool.pl">\n};
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {<table summary="bayestable" border=1 cellspacing=0>\n<tr>\n};
+       $HTML .= qq {<th>ID</th>\n};
+       $HTML .= qq {<th>チャンネル</th>\n};
+       $HTML .= qq {<th>タイトル</th>\n};
+       $HTML .= qq {<th><a href="rectool.pl?mode=bravia">開始時刻</a></th>\n};
+       $HTML .= qq {<th>終了時刻</th>\n};
+       $HTML .= qq {<th>録画時間</th>\n};
+       $HTML .= qq {<th><a href="rectool.pl?mode=bravia&amp;order=point">ポイント</a></th>\n};
+       $HTML .= qq {<th>予約</th>\n};
+       $HTML .= qq {</tr>\n};
+       my $order = $params{ 'order' };
+       if ( $order ne 'point' ) {
+               $order = 'btime';
+       }
+       else {
+               $order = 'point DESC';
+       }
+       my $ary_ref = $dbh->selectall_arrayref(
+               "SELECT id, chtxt, title, btime, etime, point 
+               FROM auto_timeline_bayes 
+               ORDER BY $order" );
+
+       foreach my $line ( @{ $ary_ref } ) {
+               my ( $begin, $end, $diff ) = &str2readable( $line->[3], $line->[4] );
+
+               $line->[1] = $chtxt_chname{$line->[1]} || $line->[1];
+               $HTML .= qq {<tr align="center">\n};
+               $HTML .= qq {<td>$line->[0]</td>\n};
+               $HTML .= qq {<td>$line->[1]</td>\n};
+               $HTML .= qq {<td>$line->[2]</td>\n};
+               $HTML .= qq {<td>$begin</td>\n<td>$end</td>\n<td>$diff</td>\n};
+               $HTML .= qq {<td>$line->[5]</td>\n};
+               $HTML .= qq {<td><a href="rectool.pl?mode=confirm&amp;mode_sub=reserve&amp;bayesid=$line->[0]">予約</a></td>\n};
+               $HTML .= qq {</tr>\n};
+       }
+       $HTML .= qq {</table>\n};
+       $HTML .= qq {</div>\n};
+       $HTML .= qq {</form>\n};
+
+}
+
+################ mode=proc ################
+
+if ( $mode eq 'proc' ) {
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Proposal/;
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {<table summary="proctable" border=1 cellspacing=0>\n<tr>\n};
+       $HTML .= qq {<th>タイプ</th>\n};
+       $HTML .= qq {<th>タイトル</th>\n};
+       $HTML .= qq {<th>予約</th>\n};
+       $HTML .= qq {</tr>\n};
+
+       my $ary_ref = $dbh->selectall_arrayref(
+               "SELECT type, chtxt, title 
+               FROM auto_proc 
+               ORDER BY title " );
+
+       foreach my $line ( @{ $ary_ref } ) {
+               my $url;
+               $line->[3] = $q->escape( $line->[2] );
+               my $opt = $dbh->selectrow_array( 
+                       "SELECT opt FROM in_timeline_log 
+                       WHERE title = '$line->[2]' "
+               );
+
+               if ( $line->[0] eq 'auto_suggest_dec' ) {
+                       unless ( $dbh->selectrow_array( 
+                               "SELECT 1 FROM timeline 
+                               WHERE ( type = 'convert_b25_ts' OR type = 'convert_b25_ts_running' )
+                               AND title = '$line->[2]' "
+                       ) ) {
+                               $url = qq {rectool.pl?mode=confirm&amp;mode_sub=proc&amp;type=$line->[0]&amp;chtxt=$line->[1]&amp;title=$line->[3]&amp;opt=$opt};
+                       }
+               }
+               elsif ( $line->[0] eq 'auto_suggest_enc' ) {
+                       unless ( $dbh->selectrow_array( 
+                               "SELECT 1 FROM timeline 
+                               WHERE ( type = 'convert_ts_mp4' OR type = 'convert_ts_mp4_running' ) 
+                               AND title = '$line->[2]' "
+                       ) ) {
+                               $url = qq {rectool.pl?mode=confirm&amp;mode_sub=proc&amp;type=$line->[0]&amp;chtxt=$line->[1]&amp;title=$line->[3]&amp;opt=$opt};
+                       }
+               }
+               else {
+                       unless ( $dbh->selectrow_array( 
+                               "SELECT 1 FROM timeline 
+                               WHERE ( type LIKE 'convert_avi%' OR type = 'convert_mkv' ) 
+                               AND title = '$line->[2]' "
+                       ) ) {
+                               $url = qq {rectool.pl?mode=confirm&amp;mode_sub=proc&amp;type=$line->[0]&amp;chtxt=$line->[1]&amp;title=$line->[3]};
+                       }
+               }
+               if ( $url ) { 
+                       $href = qq {<a href="$url">予約</a>};
+               }
+               else {
+                       $href = q {予約済};
+               }
+
+               my $color = $color{$type_suggest{$line->[0]}} ? $color{$type_suggest{$line->[0]}} : '';
+               $line->[0] = $type{$line->[0]} ? $type{$line->[0]} : $line->[0];
+               $line->[0] = qq {<span style="color: $color">$line->[0]</span>} if ( $color );
+               $HTML .= qq {<tr align="center">\n};
+               $HTML .= qq {<td>$line->[0]</td>\n};
+               $HTML .= qq {<td align="left">$line->[2]</td>\n};
+               $HTML .= qq {<td>$href</td>\n};
+               $HTML .= qq {</tr>\n};
+       }
+
+       $HTML .= qq {</table>\n};
+}
+
+################ mode=jbk ################
+
+if ( $mode eq 'jbk' ) {
+       $HTML =~ s/%HTML_TITLE_OPT%/ - JBK/;
+       $HTML .= qq {<div>\n};
+
+       if ( $mode_sub eq 'add' ) {
+               my $keyword = $params{ 'keyword' };
+               $HTML .= "キーワード「$keyword」を追加しました。<br>\n";
+               $dbh->do( 
+                       "INSERT INTO in_auto_jbk_key ( keyword ) 
+                       VALUES ( '$keyword' )" 
+               );
+       }
+       elsif ( $mode_sub eq 'del' ) {
+               my $id = $params{ 'id' };
+               my $keyword = $dbh->selectrow_array( 
+                       "SELECT keyword FROM in_auto_jbk_key 
+                       WHERE id = '$id' " );
+               $HTML .= "キーワード「$keyword」を削除しました。<br>\n";
+               $dbh->do( 
+                       "DELETE FROM in_auto_jbk_key WHERE id = '$id'" 
+               );
+       }
+       elsif ( $mode_sub eq 'on' ) {
+               my $id = $params{ 'id' };
+               $HTML .= "キーワード「$keyword」を自動録画対象にしました。<br>\n";
+               $dbh->do( 
+                       "UPDATE in_auto_jbk_key SET auto = 1 WHERE id = '$id'" 
+               );
+       }
+       elsif ( $mode_sub eq 'off' ) {
+               my $id = $params{ 'id' };
+               $HTML .= "キーワード「$keyword」を自動録画対象から外しました。<br>\n";
+               $dbh->do( 
+                       "UPDATE in_auto_jbk_key SET auto = 0 WHERE id = '$id'" 
+               );
+       }
+
+       $HTML .= qq {<table summary="jbktable" border=1 cellspacing=0>\n<tr>\n};
+       $HTML .= qq {<th>ID</th>\n};
+       $HTML .= qq {<th>キーワード</th>\n};
+       $HTML .= qq {<th>自動録画</th>\n};
+       $HTML .= qq {<th>切り替え</th>\n};
+       $HTML .= qq {<th>削除</th>\n};
+       $HTML .= qq {</tr>\n};
+
+       my $ary_ref = $dbh->selectall_arrayref(
+               "SELECT id, keyword, auto 
+               FROM in_auto_jbk_key
+               ORDER BY id " );
+
+       foreach my $line ( @{ $ary_ref } ) {
+               my $delurl = "rectool.pl?mode=jbk&amp;mode_sub=del&amp;id=$line->[0]";
+               my $auto = $line->[2] ? 'on' : 'off';
+               my $oppo = $line->[2] ? 'off' : 'on';
+               my $oppourl = "rectool.pl?mode=jbk&amp;mode_sub=$oppo&amp;id=$line->[0]";
+               $oppo .= "にする";
+
+               $HTML .= qq {<tr align="center">\n};
+               $HTML .= qq {<td>$line->[0]</td>\n};
+               $HTML .= qq {<td>$line->[1]</td>\n};
+               $HTML .= qq {<td>$auto</td>\n};
+               $HTML .= qq {<td><a href="$oppourl">$oppo</a></td>\n};
+               $HTML .= qq {<td><a href="$delurl">削除</a></td>\n};
+               $HTML .= qq {</tr>\n};
+       }
+
+       $HTML .= qq {</table>\n};
+
+       $HTML .= qq {<form method="get" action="rectool.pl">\n};
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {<input type="hidden" name="mode" value="jbk">\n};
+       $HTML .= qq {<input type="hidden" name="mode_sub" value="add">\n};
+       $HTML .= qq {<input name="keyword" type="text">\n};
+       $HTML .= qq {<input type="submit" value="追加">\n</div>\n</form>\n<br>\n};
+
+       $HTML .= qq {<table summary="jbkrestable" border=1 cellspacing=0>\n<tr>\n};
+       $HTML .= qq {<th>ID</th>\n};
+       $HTML .= qq {<th>チャンネル</th>\n};
+       $HTML .= qq {<th>タイトル</th>\n};
+       $HTML .= qq {<th>開始時刻</th>\n};
+       $HTML .= qq {<th>終了時刻</th>\n};
+       $HTML .= qq {<th>録画時間</th>\n};
+       $HTML .= qq {<th>予約</th>\n};
+       $HTML .= qq {</tr>\n};
+
+       $ary_ref = $dbh->selectall_arrayref(
+               "SELECT id, auto_timeline_keyword.chtxt, epg_ch.chname, title, btime, etime 
+               FROM auto_timeline_keyword 
+               INNER JOIN epg_ch ON auto_timeline_keyword.chtxt = epg_ch.chtxt " 
+               , {Slice=>{}} );
+
+       foreach my $line ( @{ $ary_ref } ) {
+               my ( $begin, $end, $diff ) = &str2readable( $line->{btime}, $line->{etime} );
+               $line->{btime} =~ s/(.{4})-(.{2})-(.{2}) (.{2}):(.{2}):(.{2})/$1$2$3$4$5$6/;
+               $line->{etime} =~ s/(.{4})-(.{2})-(.{2}) (.{2}):(.{2}):(.{2})/$1$2$3$4$5$6/;
+               my $url = qq "rectool.pl?mode=confirm&amp;mode_sub=reserve&amp;chtxt=$line->{chtxt}&amp;start=$line->{btime}&amp;stop=$line->{etime}";
+
+               $HTML .= qq {<tr align="center">\n};
+               $HTML .= qq {<td>$line->{id}</td>\n};
+               $HTML .= qq {<td>$line->{chname}</td>\n};
+               $HTML .= qq {<td>$line->{title}</td>\n};
+               $HTML .= qq {<td>$begin</td>\n};
+               $HTML .= qq {<td>$end</td>\n};
+               $HTML .= qq {<td>$diff</td>\n};
+               $HTML .= qq {<td><a href="$url">予約</a></td>\n};
+               $HTML .= qq {</tr>\n};
+       }
+
+       $HTML .= qq {</table>\n};
+
+}
+
+################ mode=recognize ################
+
+if ( $mode eq 'recognize' ) {
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Recognizer/;
+
+       my $text  = $params{ 'text' };
+       utf8::decode( $text );
+       $chtxt = $params{ 'chtxt' };
+       my $title = $params{ 'title' };
+       utf8::decode( $title );
+
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {与えられた文字列のうち、番組の放送時刻と思われる文字列を認識します。<br>\n};
+       $HTML .= qq {番組表が取得できない一週間以上先の予約ができます。<br>\n};
+       $HTML .= qq {<form method="post" action="rectool.pl">\n};
+       $HTML .= qq {<div>\n};
+       &draw_form_channel( 'nonone' );
+       $HTML .= qq {<input type="text" name="title" value="$title">\n};
+       $HTML .= qq {<br>\n};
+       $HTML .= qq {<input type="hidden" name="mode" value="recognize">\n};
+       $HTML .= qq {<textarea name="text" cols=40 rows=4>\n$text</textarea>\n};
+       $HTML .= qq {<input type="submit" value="実行">\n</div>\n</form>\n};
+
+       my $ch_list = join '|', grep /.+/, values %chtxt_0_chname;
+       my %ch_reverse = reverse %chtxt_0_chname;
+
+       if ( $text ) {
+               my ( $year, $month, $day );
+               my ( $bhour, $bminute, $ehour, $eminute );
+               my $next_day = 0;
+               foreach ( split /\n/, $text ) {
+                       my @bdate = /(\d{4}).(\d{1,2}).(\d{1,2})/;
+                       s/(\d{4}).(\d{2}).(\d{2})//;
+                       my @btime = /(\d{1,2})[::](\d{1,2})/;
+                       s/(\d{1,2})[::](\d{2})//;
+                       my @etime = /(\d{1,2})[::](\d{1,2})/;
+                       s/(\d{1,2})[::](\d{2})//;
+                       s/\(.*\)//;
+                       if ( !@bdate ) {
+                               $bdate[0] = Time::Piece->localtime->year;
+                               ( $bdate[1], $bdate[2] ) = /(\d{1,2})月(\d{1,2})日/;
+                               s/(\d{1,2})月(\d{1,2})日//;
+                       }
+                       next if (!( @bdate || @btime ));
+                       ( $year,  $month, $day ) = @bdate if ( $bdate[0] && $bdate[1] && $bdate[2] );
+                       ( $bhour, $bminute )     = @btime if ( defined $btime[0] && defined $btime[1] );
+                       ( $ehour, $eminute )     = @etime if ( defined $etime[0] && defined $etime[1] );
+                       $next_day = 1 if ( /深夜/ );
+                       my ( $ch ) = /($ch_list)/;
+                       my $chtxt = $ch_reverse{$ch} if ( $ch && $ch_reverse{$ch} );
+                       s/($ch_list)//;
+
+                       if ( $year && $month && $day && defined $bhour && defined $bminute ) {
+                               my $tp  = Time::Piece->strptime( "$year-$month-$day $bhour:$bminute", '%Y-%m-%d %H:%M' );
+                               my $etp = Time::Piece->strptime( "$year-$month-$day $ehour:$eminute", '%Y-%m-%d %H:%M' ) if ( defined $ehour && defined $eminute );
+                               $tp += ONE_DAY if ( $next_day );
+                               my $start = $tp->strftime( '%Y%m%d%H%M%S' );
+                               my $stop  = defined $etp ? 
+                                       $etp->strftime( '%Y%m%d%H%M%S' ) :
+                                       ( $tp + ONE_MINUTE * 30 )->strftime( '%Y%m%d%H%M%S' );
+                               $title = $_ if ( !$title );
+                               my $url = qq "rectool.pl?mode=confirm&amp;mode_sub=reserve&amp;chtxt=$chtxt&amp;start=$start&amp;stop=$stop&amp;title=$title";
+                               $HTML .= qq {認識結果:$year-$month-$day $bhour:$bminute -> $ehour:$eminute 残り:$_<a href="$url">リンク</a> <br>\n};
+                       }
+               }
+       }
+}
+
+################ mode=expert ################
+
+if ( $mode eq 'expert' ) {
+       require List::Compare;
+
+       my $ary_ref;
+
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Expert/;
+       $HTML .= qq {<div>\n};
+
+       if ( $mode_sub eq 'reget' ) {
+               my $bctype = $params{ 'bctype' };
+               my ( $chtxt, $chname ) = $dbh->selectrow_array( 
+                       "SELECT chtxt, chname FROM epg_ch 
+                       WHERE bctype = '$bctype' " );
+               $HTML .= "Update for $chname ( chtxt: $chtxt ) has been reserved.<br>\n";
+               $dbh->do( "UPDATE epg_ch SET status = '2' WHERE chtxt = '$chtxt' " );
+               goto end;
+       }
+
+
+       my @ary = $dbh->selectrow_array(
+               "SELECT auto_jbk, auto_bayes, auto_del_tmp, auto_opt 
+               FROM in_settings " );
+       my $opt = pop @ary;
+       @ary = map( $_ ? 'checked' : '', @ary );
+
+       $HTML .= qq {内部オプションの変更\n<br>};
+       $HTML .= qq {<form method="get" action="rectool.pl">\n};
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {<input type="hidden" name="mode"     value="change">\n};
+       $HTML .= qq {<input type="hidden" name="mode_sub" value="setting">\n};
+       $HTML .= qq {<input type="checkbox" name="jbk"     value="1" $ary[0]>自動地引\n};
+       $HTML .= qq {<input type="checkbox" name="bayes"   value="1" $ary[1]>自動ベイズ\n};
+       $HTML .= qq {<input type="checkbox" name="del_tmp" value="1" $ary[2]>自動一時ファイル削除\n};
+       $HTML .= qq {自動オプション:<input type="text" name="opt" value="$opt">\n};
+       $HTML .= qq {<input type="submit" value="保存">\n</div>\n</form>\n};
+
+
+       $HTML .= qq {<hr>\n番組表のカテゴリ一覧と内蔵のカテゴリ一覧の合致を確認中...\n};
+       $ary_ref = $dbh->selectcol_arrayref(
+               "SELECT DISTINCT category FROM epg_timeline"
+       );
+       my @category = sort values %category;
+       if ( List::Compare->new( $ary_ref, \@category )->get_symdiff ) {
+               $HTML .= qq {一致しません<br>\n};
+               $HTML .= qq {番組表:@{$ary_ref}<br>\n内蔵:@category<br>\n};
+       }
+       else {
+               $HTML .= qq {一致しました<br>\n};
+       }
+
+
+       @ary = $dbh->selectrow_array( "SELECT terec, bscsrec, b252ts, ts2avi FROM in_status" );
+       $HTML .= qq {<hr>\n地上波録画数:$ary[0]\n衛星波録画数:$ary[1]\n解読数:$ary[2]\n縁故数:$ary[3]\n<br>\n};
+       $HTML .= qq {<form method="get" action="rectool.pl">\n};
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {<input type="hidden" name="mode"     value="change">\n};
+       $HTML .= qq {<input type="hidden" name="mode_sub" value="fixstatus">\n};
+       $HTML .= qq {<input type="submit" name="terec"   value="地上波録画数をリセット">\n};
+       $HTML .= qq {<input type="submit" name="bscsrec" value="衛星波録画数をリセット">\n};
+       $HTML .= qq {<input type="submit" name="b252ts"  value="解読数をリセット">\n};
+       $HTML .= qq {<input type="submit" name="ts2avi"  value="縁故数をリセット">\n</div>\n</form>\n};
+
+
+       $HTML .= qq {<hr>\nRec10 バージョン:$rec10_version\nrectool バージョン:$rectool_version\n<br>\n};
+
+
+       $HTML .= qq {<hr>\n番組表の欠落<br>\n};
+       $ary_ref = $dbh->selectall_arrayref( "SELECT chname, chtxt FROM epg_ch" );
+       foreach my $line ( @{$ary_ref} ) {
+               my $ary_ref = $dbh->selectall_arrayref( 
+                       "SELECT start, stop, title FROM epg_timeline WHERE channel = '$line->[1]' ORDER BY start" 
+               );
+               my $error;
+               my @program_old = ( '', $ary_ref->[0]->[0] );
+               my $program_old = \@program_old;
+
+               foreach my $program_new ( @{$ary_ref} ) {
+                       if ( $program_old->[1] ne $program_new->[0] && 
+                               $program_old->[2] !~ /クロ?ジング|クロージング|エンディング|休止|ミッドナイト|ending/ && 
+                               $program_new->[2] !~ /オープニング|ウィークリー・インフォメーション|モーニング|opening/ && 
+                               ( str2datetime( $program_new->[0] ) - str2datetime( $program_old->[1] ) )->delta_minutes > 30 ) {
+                               $program_old->[1] =~ s/(.{4})(.{2})(.{2})(.{2})(.{2})(.{2})/$1-$2-$3 $4:$5:$6/;
+                               $program_new->[0] =~ s/(.{4})(.{2})(.{2})(.{2})(.{2})(.{2})/$1-$2-$3 $4:$5:$6/;
+                               $error .= qq{    $program_old->[2]    $program_old->[1]\n    ->  $program_new->[2]    $program_new->[0]\n};
+                       }
+                       $program_old = $program_new;
+               }
+               $HTML .= qq {<pre>\n$line->[0]\n$error</pre>\n} if ( $error );
+               }
+
+
+       $ary_ref = $dbh->selectall_arrayref( 
+               "SELECT chname, chtxt, bctype, ch, csch, updatetime, status, visible 
+               FROM epg_ch 
+               ORDER BY bctype " );
+       $HTML .= qq {<hr>\n番組表の更新状況<br>\n};
+       $HTML .= qq {<table summary="channeltable" border=1 cellspacing=0>\n<tr>\n};
+       $HTML .= qq {<th>チャンネル名</th>\n};
+       $HTML .= qq {<th>chtxt</th>\n};
+       $HTML .= qq {<th>bctype</th>\n};
+       $HTML .= qq {<th>ch</th>\n};
+       $HTML .= qq {<th>csch</th>\n};
+       $HTML .= qq {<th>最終更新時刻</th>\n};
+       $HTML .= qq {<th>状態</th>\n};
+       $HTML .= qq {<th>表示</th>\n};
+       $HTML .= qq {</tr>\n};
+       foreach my $status ( @{$ary_ref} ) {
+               $HTML .= qq {<tr>\n};
+               $HTML .= qq {<td>$status->[0]</td>\n<td>$status->[1]</td>\n<td>$status->[2]</td>\n<td>$status->[3]</td>\n};
+               $HTML .= qq {<td>$status->[4]</td>\n<td>$status->[5]</td>\n<td>$status->[6]</td>\n<td>$status->[7]</td>\n};
+               $HTML .= qq {</tr>\n};
+       }
+       $HTML .= qq {</table>\n};
+
+       $HTML .= qq {<form method="get" action="rectool.pl">\n};
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {番組表を再取得する\n};
+       $HTML .= qq {<input type="hidden" name="mode" value="expert">\n};
+       $HTML .= qq {<input type="hidden" name="mode_sub" value="reget">\n};
+       $HTML .= qq {<select name="bctype">\n};
+       $ary_ref = $dbh->selectall_arrayref(
+               "SELECT chname, bctype 
+               FROM epg_ch WHERE bctype NOT LIKE '_s%' "
+       );
+       foreach my $line ( @{$ary_ref} ) {
+               $HTML .= qq {<option value="$line->[1]">$line->[0]</option>\n};
+       }
+       $HTML .= qq {<option value="bs">BS</option>\n};
+       $HTML .= qq {<option value="cs1">CS1</option>\n};
+       $HTML .= qq {<option value="cs2">CS2</option>\n};
+       $HTML .= qq {</select>\n};
+       $HTML .= qq {<input type="submit" value="実行">\n</div>\n</form>\n};
+
+
+
+       $ary_ref = $dbh->selectall_arrayref(
+               "SELECT id, type, chtxt, title, btime, etime, opt, deltaday, deltatime 
+               FROM timeline 
+               ORDER BY id ");
+       $HTML .= qq {<hr>\n予約表<br>\n};
+       $HTML .= qq {<table summary="rectimetable" border=1 cellspacing=0>\n<tr>\n};
+       $HTML .= qq {<th>ID</th>\n};
+       $HTML .= qq {<th>type</th>\n};
+       $HTML .= qq {<th>chtxt</th>\n};
+       $HTML .= qq {<th>title</th>\n};
+       $HTML .= qq {<th>btime</th>\n};
+       $HTML .= qq {<th>etime</th>\n};
+       $HTML .= qq {<th>opt</th>\n};
+       $HTML .= qq {<th>deltaday</th>\n};
+       $HTML .= qq {<th>deltatime</th>\n};
+       $HTML .= qq {</tr>\n};
+       foreach my $status ( @{$ary_ref} ) {
+               $HTML .= qq {<tr>\n};
+               $HTML .= qq {<td>$status->[0]</td>\n<td>$status->[1]</td>\n<td>$status->[2]</td>\n<td>$status->[3]</td>\n};
+               $HTML .= qq {<td>$status->[4]</td>\n<td>$status->[5]</td>\n<td>$status->[6]</td>\n<td>$status->[7]</td>\n};
+               $HTML .= qq {<td>$status->[8]</td>\n};
+               $HTML .= qq {</tr>\n};
+       }
+       $HTML .= qq {</table>\n};
+}
+
+################ mode=log ################
+
+if ( $mode eq 'log' ) {
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Log/;
+
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {<table summary="reclogtable" border=1 cellspacing=0>\n<tr>\n};
+       $HTML .= qq {<th>ID</th>\n};
+       $HTML .= qq {<th>chtxt</th>\n};
+       $HTML .= qq {<th>title</th>\n};
+       $HTML .= qq {<th>btime</th>\n};
+       $HTML .= qq {<th>etime</th>\n};
+       $HTML .= qq {<th>opt</th>\n};
+       $HTML .= qq {<th>exp</th>\n};
+       $HTML .= qq {<th>longexp</th>\n};
+       $HTML .= qq {<th>category</th>\n};
+       $HTML .= qq {</tr>\n};
+       $ary_ref = $dbh->selectall_arrayref(
+               "SELECT id, chtxt, title, btime, etime, opt, exp, longexp, category 
+               FROM in_timeline_log "
+       );
+       foreach my $line ( @{$ary_ref} ) {
+               $HTML .= qq {<tr>\n};
+               $HTML .= qq {<td>$line->[0]</td>\n<td>$line->[1]</td>\n<td>$line->[2]</td>\n<td>$line->[3]</td>\n};
+               $HTML .= qq {<td>$line->[4]</td>\n<td>$line->[5]</td>\n<td>$line->[6]</td>\n<td>$line->[7]</td>\n};
+               $HTML .= qq {<td>$line->[8]</td>\n};
+               $HTML .= qq {</tr>\n};
+       }
+       $HTML .= qq {</table>\n};
+}
+
+################ mode=help ################
+
+if ( $mode eq 'help' ) {
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Help/;
+       $HTML =~ s|%REFRESH%|<meta http-equiv="refresh" content="300">|;
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {ヘルプ\n};
+}
+
+################ mode=test ################
+
+if ( $mode eq 'test' ) {
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Test/;
+       $HTML =~ s|%REFRESH%|<meta http-equiv="refresh" content="300">|;
+       $HTML .= qq {<div>\n};
+
+       require Data::Dumper;
+       $tmp = Perl6::Slurp::slurp( 'config.ini' );
+       $tmp =~ s/\n/<br>\n/gs;
+       $HTML .= $tmp;
+
+       # $HTML .= Dumper( $ary_ref );
+}
+
+################ mode nasi ################
+
+if ( !$mode ) {
+       &draw_form();
+       $HTML =~ s/%HTML_TITLE_OPT%/ - Top/;
+       $HTML .= qq {Welcome to Rec10!<br>\n};
+       goto end;
+}
+
+
+end:
+#<div style="float: right">
+$HTML .= <<EOM;
+</div>
+</body>
+</html>
+EOM
+
+#<div align="center">
+#$HTML_ADV = $HTML_ADV_IMG . $HTML_ADV_TEXT if ( !$HTML_ADV );
+my $HTML_ADV = '';
+$HTML_HEADER = qq {<div style="text-align: center">\n$HTML_ADV\n</div>\n};
+
+&draw_menu();
+$HTML =~ s/%HTML_TITLE_OPT%//;
+$HTML =~ s/%REFRESH%//;
+$HTML =~ s/%SCRIPT%//;
+$HTML =~ s/%CSS%//;
+$HTML =~ s/%HTML_HEADER%/$HTML_HEADER/;
+
+utf8::encode( $HTML );
+print $HTTP_HEADER;
+print $HTML;
+exit;
+
+sub draw_menu {
+       $hires = Time::HiRes::time() - $hires;
+       $last_modified = localtime((stat 'rectool.pl')[9]);
+
+       $HTML_HEADER .= qq {<div>\n};
+       $HTML_HEADER .= qq {<span style="float: right; font-size: 8px">Last-Modified: $last_modified<br>Time-Elapsed: $hires 秒</span>\n};
+       $HTML_HEADER .= qq {<span style="float: left">\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl">トップ(検索)</a>\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl?mode=schedule">予約確認</a>\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl?mode=graph">予約状況(画像版)</a>\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl?mode=list">録画一覧</a>\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl?mode=bravia">おまかせ</a>\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl?mode=expert">玄人仕様</a>\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl?mode=proc">復旧支援</a>\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl?mode=jbk">地引</a>\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl?mode=log">録画履歴</a>\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl?mode=recognize">文字認識</a>\n};
+       $HTML_HEADER .= qq {<a href="rectool.pl?mode=edit">新規予約</a>\n};
+#      $HTML_HEADER .= qq {<a href="../rec10web/rec10web.py">新規予約</a>\n};
+       $HTML_HEADER .= qq {</span>\n};
+       $HTML_HEADER .= qq {<hr style="clear: both; background-color: grey; height: 4px">\n};
+       $HTML_HEADER .= qq {</div>\n};
+}
+
+sub draw_form {
+       $chname = $params{ 'chname' };
+       $chtxt  = $params{ 'chtxt' };
+       $key    = $params{ 'key' };
+       utf8::decode( $key );
+       if ( $chname ) {
+               $chtxt = $dbh->selectrow_array("SELECT chtxt FROM epg_ch WHERE chname = '$chname' ");
+       }
+
+       $HTML .= qq {<div style="float: left">\n};
+       $HTML .= qq {<form method="get" action="rectool.pl">\n};
+       $HTML .= qq {<div>\n};
+       $HTML .= qq {<input type="hidden" name="mode" value="program">\n};
+
+       # チャンネル指定
+       &draw_form_channel();
+
+       # 日付指定
+       $HTML .= qq {<select name="date">\n<option value="" selected>無指定</option>\n};
+       $ary_ref = $dbh->selectcol_arrayref(
+               "SELECT DISTINCT SUBSTRING(start, 1, 8) FROM epg_timeline ORDER BY start"
+       );
+       $date_sel = $params{ 'date' };
+       foreach my $date ( @{ $ary_ref } ) {
+               my @date = $date =~ /(.{4})(.{2})(.{2})/;
+               $date_prt = "$date[1]/$date[2]";
+
+               if ( $date eq $date_sel ) {
+                       $HTML .= qq {<option value="$date" selected>$date_prt</option>\n};
+               }
+               else {
+                       $HTML .= qq {<option value="$date">$date_prt</option>\n};
+               }
+       }
+       $HTML .= qq {</select>\n};
+
+       # カテゴリ指定
+       $HTML .= qq {<select name="category">\n<option value="" selected>無指定</option>\n};
+       $category_sel = $params{ 'category' };
+       foreach my $category ( keys %category ) {
+               if ( $category eq $category_sel ) {
+                       $HTML .= qq {<option value="$category" selected>$category{$category}</option>\n};
+               }
+               else {
+                       $HTML .= qq {<option value="$category">$category{$category}</option>\n};
+               }
+       }
+       $HTML .= qq {</select>\n};
+
+       # キーワード指定
+       $HTML .= qq {<input name="key" type="text" value="$key" style="width:200px" accesskey="s">\n};
+
+       # フォーム描画
+       $HTML .= qq {<input type="submit" value="更新" accesskey="r">\n</div>\n</form>\n};
+}
+
+sub draw_form_channel {
+       $HTML .= qq {<select name="chtxt">\n};
+       $HTML .= qq {<option value="" selected>無指定</option>\n} if ( shift ne 'nonone' );
+
+       foreach my $key ( keys %chtxt_0_chname ) {
+               my $value = $chtxt_0_chname{$key};
+               if ( ($chtxt && $key eq $chtxt ) || ( $chname && $value eq $chname ) ) {
+                       $HTML .= qq {<option value="$key" selected>$value</option>\n};
+               }
+               else {
+                       $HTML .= qq {<option value="$key">$value</option>\n};
+               }
+       }
+       $HTML .= qq {</select>\n};
+}
+
+sub draw_form_opt {
+       my $shift = shift;
+       my ( %selected, %checked );
+
+       if ( $chtxt  =~ /BS_103/ ) {
+               $selected{F} = 'selected';
+       }
+       elsif ( $chtxt  =~ /CS_239|CS_240|CS_335/ ) {
+               $selected{H} = 'selected';
+       }
+       elsif ( $chtxt =~ /BS_101|BS_102/ || $bctype =~ /cs/ ) {
+               $selected{W} = 'selected';
+       }
+       elsif ( $bctype =~ /bs|te/ ) {
+               $selected{H} = 'selected';
+       }
+       $selected{g} = 'selected';
+       $selected{s} = 'selected';
+       $checked{a} = $chtxt =~ /CS_331|CS_332|CS_333|CS_334|CS_335/ || $category =~ /アニメ/ ? 'checked' : '';
+       $checked{l} = '';
+       $checked{d} = $title =~ /\Q[二]\E|[二]|\Q(二)\E|(二)/ ? 'checked' : '';
+       $checked{5} = $title =~ /5\.1|5.1/ ? 'checked' : '';
+       $checked{2} = 'checked';
+
+       if ( $opt ) {
+               undef %checked;
+               undef %selected;
+               my @opt = split //, $opt;
+               foreach my $opt ( @opt ) {
+                       $selected{$opt} = 'selected' if ( $opt =~ /S|L|G|H|F/ );
+                       $checked {$opt} = 'checked'  if ( $opt =~ /a|h|l|d|2|5/ );
+               }
+               $checked{d} = $title =~ /\Q[二]\E|[二]|\Q(二)\E|(二)/ ? 'checked' : '';
+               $checked{5} = $title =~ /5\.1|5.1/ ? 'checked' : '';
+       }
+       # 画質/圧縮率ともに指定されていない場合、真ん中をselectedにする
+       $selected{g} = 'selected' unless ( $selected{u} || $selected{i} || $selected{o} || $selected{p} );
+       $selected{s} = 'selected' unless ( $selected{q} || $selected{w} || $selected{e} || $selected{r} );
+
+       $HTML .= qq {<select name="opt">\n};
+       #$HTML .= qq {<option value="S" $selected{S}>S 720x480</option>\n};
+       $HTML .= qq {<option value="W" $selected{W}>W 854x480</option>\n};
+       $HTML .= qq {<option value="H" $selected{H}>H 1280x720</option>\n};
+       $HTML .= qq {<option value="F" $selected{F}>F 1920x1080</option>\n};
+       $HTML .= qq {<option value="I" $selected{I}>I インタレ保持</option>\n};
+       $HTML .= qq {</select>\n};
+
+       $HTML .= qq {<select name="opt">\n};
+       $HTML .= qq {<option value="u" $selected{u}>最低</option>\n};
+       $HTML .= qq {<option value="i" $selected{i}>低</option>\n};
+       $HTML .= qq {<option value=""  $selected{g}>画質</option>\n};
+       $HTML .= qq {<option value="o" $selected{o}>高</option>\n};
+       $HTML .= qq {<option value="p" $selected{p}>最高</option>\n};
+       $HTML .= qq {</select>\n};
+
+       $HTML .= qq {<select name="opt">\n};
+       $HTML .= qq {<option value="q" $selected{q}>最低</option>\n};
+       $HTML .= qq {<option value="w" $selected{w}>低</option>\n};
+       $HTML .= qq {<option value=""  $selected{s}>圧縮率</option>\n};
+       $HTML .= qq {<option value="e" $selected{e}>高</option>\n};
+       $HTML .= qq {<option value="r" $selected{r}>最高</option>\n};
+       $HTML .= qq {</select>\n};
+
+       $HTML .= qq {<select name="opt">\n};
+       $HTML .= qq {<option value=""  $selected{s}>コンテナ</option>\n};
+       $HTML .= qq {<option value="m" $selected{e}>MKV</option>\n};
+       $HTML .= qq {<option value="4" $selected{r}>MP4</option>\n};
+       $HTML .= qq {</select>\n};
+
+       $HTML .= qq {<select name="opt">\n};
+       $HTML .= qq {<option value=""  $selected{s}>モバイル向け</option>\n};
+       $HTML .= qq {<option value="1" $selected{e}>QVGA</option>\n};
+       $HTML .= qq {<option value="2" $selected{r}>WVGA</option>\n};
+       $HTML .= qq {</select>\n};
+
+       $HTML .= qq {<input type="checkbox" name="opt" value="a" $checked{a}>24fps(主にアニメ)\n};
+       $HTML .= qq {<input type="checkbox" name="opt" value="d" $checked{d}>二ヶ国語放送\n};
+       #$HTML .= qq {<input type="checkbox" name="opt" value="2" $checked{2}>2passモード\n};
+       $HTML .= qq {<input type="checkbox" name="opt" value="5" $checked{5}>5.1ch放送\n};
+       $HTML .= qq {<br>\n};
+       $HTML .= qq {<select name="opt">\n};
+       $HTML .= qq {<option value="">移動なし</option>\n};
+       $HTML .= qq {<option value="R">録画後移動</option>\n};
+       $HTML .= qq {<option value="D">解読後移動</option>\n};
+       $HTML .= qq {<option value="E">縁故後移動</option>\n};
+       $HTML .= qq {</select>\n};
+       $HTML .= qq {<input type="checkbox" name="opt"   value="N">ファイル名日時追加\n} if ( $shift eq 'reserve' );
+       $HTML .= qq {<input type="checkbox" name="every" value="1">隔週録画\n}           if ( $shift eq 'reserve' );
+}
+
+sub parse_program {
+       $chname  = $params{ 'chname' };
+       $chtxt   = $params{ 'chtxt' };
+       $start   = $params{ 'start' };
+       $stop    = $params{ 'stop' };
+       $bayesid = $params{ 'bayesid' };
+       $id      = $params{ 'id' };
+
+       if ( $chname ) {
+               $chtxt = $dbh->selectrow_array("SELECT chtxt FROM epg_ch WHERE chname = '$chname'");
+       }
+       elsif ( $chtxt && $chtxt_0_chname{$chtxt} ) {
+               $chname = $chtxt_0_chname{$chtxt};
+               ( $chtxt_sql = $chtxt ) =~ s/_0/_%/;
+               $bctype = $dbh->selectrow_array("SELECT bctype FROM epg_ch WHERE chtxt LIKE '$chtxt_sql'");
+       }
+       elsif ( $chtxt ) {
+               $chname = $dbh->selectrow_array("SELECT chname FROM epg_ch WHERE chtxt = '$chtxt'")
+       }
+       ( $title, $desc, $longdesc, $category ) = $dbh->selectrow_array(
+               "SELECT title, exp, longexp, category
+               FROM epg_timeline 
+               WHERE channel = '$chtxt' AND start = '$start' AND stop = '$stop' ");
+       if ( !$bctype ) {
+               $bctype = $dbh->selectrow_array("SELECT bctype FROM epg_ch WHERE chtxt = '$chtxt'");
+       }
+
+       if ( $bayesid ) {
+               ( $chtxt, $title, $begin, $end ) = $dbh->selectrow_array( 
+                       "SELECT chtxt, title, btime, etime FROM auto_timeline_bayes WHERE id = '$bayesid' " 
+               );
+               ( $chname, $bctype ) = $dbh->selectrow_array( 
+                       "SELECT chname, bctype FROM epg_ch WHERE chtxt = '$chtxt' " 
+               );
+               $start = str2datetime( $begin )->strftime( '%Y%m%d%H%M%S' );
+               $stop  = str2datetime( $end   )->strftime( '%Y%m%d%H%M%S' );
+               ( $desc, $longdesc, $category ) = $dbh->selectrow_array( 
+                       "SELECT exp, longexp, category FROM epg_timeline WHERE channel = '$chtxt' AND start = '$start' AND stop = '$stop' " 
+               );
+       }
+       if ( $id ) {
+               ( $type, $chtxt, $title, $begin, $end, $deltaday, $deltatime, $opt, $counter ) = $dbh->selectrow_array( 
+                       "SELECT type, chtxt, title, btime, etime, deltaday, deltatime, opt, counter 
+                       FROM timeline WHERE id = '$id' " 
+               );
+               ( $chname, $bctype ) = $dbh->selectrow_array( 
+                       "SELECT chname, bctype FROM epg_ch WHERE chtxt = '$chtxt' " 
+               );
+               $start = str2datetime( $begin )->strftime( '%Y%m%d%H%M%S' );
+               $stop  = str2datetime( $end   )->strftime( '%Y%m%d%H%M%S' );
+               ( $desc, $longdesc, $category ) = $dbh->selectrow_array( 
+                       "SELECT exp, longexp, category FROM epg_timeline WHERE channel = '$chtxt' AND start = '$start' AND stop = '$stop' " 
+               );
+       }
+       if ( $bctype =~ /bs|cs/ ) {
+               $bctype_sql = '_s%';
+       }
+       elsif ( $bctype =~ /te/ ) {
+               ( $chtxt_0   = $chtxt ) =~ s/(\d+)_.*/$1_0/;
+               ( $chtxt_sql = $chtxt ) =~ s/_0/_%/;
+               $bctype_sql = 'te%';
+       }
+       #( $chtxt_no0 ) = $chtxt   =~ /(\d+)_/;
+       @start = $start =~ /(.{4})(.{2})(.{2})(.{2})(.{2})/;
+       @stop  = $stop  =~ /(.{4})(.{2})(.{2})(.{2})(.{2})/;
+       $begin = sprintf( '%04d-%02d-%02d %02d:%02d:%02d', @start, '00' );
+       $end   = sprintf( '%04d-%02d-%02d %02d:%02d:%02d', @stop , '00' );
+
+       if ( $params{ 'title' } ) {
+               $title = $params{ 'title' };
+               utf8::decode( $title );
+       }
+       $HTML .= qq {<!-- chtxt=$chtxt chtxt_0=$chtxt_0 chtxt_sql=$chtxt_sql bctype=$bctype -->\n};
+}
+
+sub check_error {
+       my $is_error;
+       my $is_same = $dbh->selectrow_array( 
+               "SELECT COUNT(*) FROM timeline WHERE chtxt = '$chtxt' AND btime = '$begin' AND etime = '$end'" 
+       );
+       my @overlap = &get_overlap();
+
+       if ( $is_same ) {
+               $HTML .= "同一の番組が既に存在します。<br>\n";
+               $is_error = 1;
+       }
+       elsif ( $overlap[0] >= 2 ) {
+               $HTML .= "時間が被る番組が既に2個存在します。<br>\n";
+               $HTML .= $overlap[1];
+               $is_error = 2;
+       }
+       else {
+               $is_error = 0;
+       }
+       return $is_error;
+}
+
+sub get_overlap {
+       require List::Util;
+
+       my $ary_ref = $dbh->selectall_arrayref(
+               "SELECT btime, etime, title
+               FROM timeline 
+               INNER JOIN epg_ch ON timeline.chtxt = epg_ch.chtxt 
+               WHERE bctype LIKE '$bctype_sql' AND type IN $type_user_made 
+               AND btime < '$end' 
+               AND etime > '$begin' 
+               "
+       );
+
+       my %overlap;
+       my $overlap = $max = 0;
+       my $str;
+       foreach my $prg ( @{ $ary_ref } ) {
+               $str .= "$prg->[0] ? $prg->[1] : $prg->[2]<br>\n";
+               $overlap{$prg->[0]} += 1;
+               $overlap{$prg->[1]} -= 1;
+       }
+       foreach my $key ( sort keys %overlap ) {
+               $overlap += $overlap{$key};
+               $max = List::Util::max( $max, $overlap );
+       }
+       if ( wantarray ) {
+               return ( $max, $str );
+       }
+       else {
+               return $max;
+       }
+}
+
+sub get_file_list_wrapper {
+       local $base_dir = shift;
+       local $ptr = shift;
+
+       &get_file_list( $base_dir );
+}
+
+sub get_file_list{
+       my $dir = shift;
+
+       opendir ( DIR, $dir );
+       my @list = sort readdir( DIR );
+       closedir( DIR );
+
+       foreach my $file ( @list ) {
+               next if ( $file =~ /^\.{1,2}$/ );
+               if ( -d "$dir/$file" ){
+                       &get_file_list("$dir/$file");
+               }
+               else{
+                       $abs = "$dir/$file";
+                       utf8::decode( $abs );
+                       ( $rel ) = $abs =~ /^$base_dir\/(.*)$/;
+                       $ptr->( $rel, $abs );
+               }
+       }
+}
+
+sub strisjoined {
+       my $str = shift;
+
+       return $str =~ /.{4}-.{2}-.{2} .{2}:.{2}:.{2}/ ? 0 : 1;
+}
+
+sub str2datetime {
+       my $str    = shift;
+       my @time;
+
+       if ( strisjoined( $str ) ) {
+               @time = $str =~ /(.{4})(.{2})(.{2})(.{2})(.{2})(.{2})/;
+       }
+       else {
+               @time = $str =~ /(.{4})-(.{2})-(.{2}) (.{2}):(.{2}):(.{2})/;
+       }
+       return DateTime->new(
+               year   => $time[0], month     => $time[1], day    => $time[2],
+               hour   => $time[3], minute    => $time[4], second => $time[5], 
+               locale => 'ja_JP' , time_zone => $tz
+       );
+}
+
+sub str2dayname {
+       my  $str = shift;
+       our %day_name_cache;
+
+       if ( !$day_name_cache{$str} ) {
+               $day_name_cache{$str} = str2datetime( $str )->day_name;
+       }
+       return $day_name_cache{$str};
+}
+
+sub str2readable { 
+       my $begin = shift;
+       my $end   = shift;
+
+       my $dt_begin = ref( $begin ) eq 'DateTime' ? $begin : &str2datetime( $begin );
+       my $dt_end   = ref( $end   ) eq 'DateTime' ? $end   : &str2datetime( $end );
+
+       my $str_begin = $dt_begin->strftime( '%m/%d(%a) %H:%M' );
+       my $str_end   = $dt_end  ->strftime( $dt_begin->day == $dt_end->day ? '%H:%M' : '翌 %H:%M' );
+       # utf8::encode( $str_begin );
+
+       my ( $sec, $min, $hour );
+       $sec  = $dt_end->epoch - $dt_begin->epoch;
+       $min  = int( $sec / 60 );
+       $sec  = $sec - $min * 60;
+       $hour = int( $min / 60 );
+       $min  = $min - $hour * 60;
+       my $str_diff = '';
+       $str_diff .= $hour . '時間' if ( $hour );
+       $str_diff .= $min  . '分'   if ( $min );
+       $str_diff .= $sec  . '秒'   if ( $sec );
+
+       return ( $str_begin, $str_end, $str_diff );
+}
+
+sub sqlgetsuggested {
+       require Encode;
+       require Text::Ngram;
+
+       my ( $btime, $etime ) = @_;
+       $deltatime = 3 if ( !$deltatime );
+
+       $btime_bgn = $btime->clone->subtract( hours => $deltatime )->strftime( '%Y%m%d%H%M%S' );
+       $btime_end = $btime->clone->add(      hours => $deltatime )->strftime( '%Y%m%d%H%M%S' );
+       $etime_bgn = $etime->clone->subtract( hours => $deltatime )->strftime( '%Y%m%d%H%M%S' );
+       $etime_end = $etime->clone->add(      hours => $deltatime )->strftime( '%Y%m%d%H%M%S' );
+
+       $ary_ref = $dbh->selectall_arrayref(
+               "SELECT start, stop, title, exp 
+               FROM epg_timeline 
+               WHERE channel LIKE '$chtxt_sql' 
+               AND start BETWEEN '$btime_bgn' AND '$btime_end' 
+               AND stop  BETWEEN '$etime_bgn' AND '$etime_end' "
+       );
+       #die Dumper $ary_ref;
+
+       my %hash;
+       my $hash_r = Text::Ngram::ngram_counts( $title, 2 ); # bi-gram
+       foreach my $program ( @{$ary_ref} ) {
+               my $hash_k = Text::Ngram::ngram_counts( $program->[2], 2 );
+               my $point;
+               map $point += $hash_k->{$_}, keys %{$hash_r};
+               push @{$hash{$point}}, $program if ( $point );
+       }
+
+       return %hash;
+}