├── .gitignore ├── AribChannel.h ├── BonDriver_DVB.so.conf ├── BonDriver_LinuxPT.so.conf ├── COPYING ├── LICENSE ├── Makefile.in ├── README.md ├── README.md~ ├── autogen.sh ├── channels ├── sample.recpt1-channels-chiba ├── sample.recpt1-channels-kanazawa ├── sample.recpt1-channels-nagoya └── sample.recpt1-channels-tokyo ├── checksignal.c ├── configure.ac ├── decoder.c ├── decoder.h ├── linux_ch.diff ├── mkpath.c ├── mkpath.h ├── pt1_dev.h ├── recpt1.c ├── recpt1.h ├── recpt1core.c ├── recpt1core.h ├── recpt1ctl.c ├── tssplitter_lite.c └── tssplitter_lite.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | -------------------------------------------------------------------------------- /AribChannel.h: -------------------------------------------------------------------------------- 1 | #define BON_CHANNEL 0 2 | #define ARIB_GROUND 1 3 | #define ARIB_CATV 2 4 | #define ARIB_BS 3 5 | #define ARIB_BS_SID 4 6 | #define ARIB_CS 5 7 | #define ARIB_TSID 6 8 | #define ARIB_CH_ERROR 0x7FFFFFFFU 9 | 10 | #define ISDB_T_NODE_LIMIT 24 // 32:ARIB limit 24:program maximum 11 | #define ISDB_T_SLOT_LIMIT 8 12 | 13 | #ifndef _BONDRIVER_DVB_H_ 14 | #ifndef _BONDRIVER_LINUXPT_H_ 15 | 16 | // linux環境下で標準的なチャンネル指定をSetChannel()に渡せる形に変換 17 | // チューナードライバー直下のBonDriverに追加したchannelLinuxToBon()でBonDriverチャンネル番号へ変換される 18 | // "nn" 地デジ(n=1-63) 19 | // "Cnn" CATV(n=13-63) 20 | // "nnn" BSサービスID指定(n=101-999) 21 | // "BSnn_s" BSトラポン指定(n=node,s=slot DVBでは動作不良の可能性有り) 22 | // "CSnn" CSトラポン指定(n=2-24) 23 | // "0xhhhh" BS/CS TSID指定(h=0x4010-0x7fff) 24 | // "Bnn" BonDriverチャンネル番号(n=0-) 25 | DWORD channelAribToBon(char *channel) 26 | { 27 | DWORD tsid; 28 | DWORD node = 0; 29 | DWORD slot; 30 | DWORD freqno; 31 | 32 | if (channel[0] == '0' && (channel[1] == 'X' || channel[1] == 'x')) 33 | { 34 | tsid = strtoul(channel, NULL, 16); 35 | channel += strlen(channel); 36 | } 37 | else 38 | { 39 | int ch_type = 0; 40 | 41 | if (*channel == 'B') 42 | { 43 | channel++; 44 | ch_type++; 45 | if (*channel == 'S') 46 | { 47 | channel++; 48 | ch_type++; 49 | } 50 | } 51 | else if (*channel == 'C') 52 | { 53 | channel++; 54 | ch_type = 10; 55 | if (*channel == 'S') 56 | { 57 | channel++; 58 | ch_type++; 59 | } 60 | } 61 | while (isdigit((int)*channel)) 62 | { 63 | node *= 10; 64 | node += (DWORD)(*channel++ - '0'); 65 | } 66 | switch (ch_type) 67 | { 68 | case 1: // BonDriver Channel No 69 | if (*channel == '\0') 70 | return node; 71 | default: 72 | return ARIB_CH_ERROR; 73 | case 2: // "BSnn_n"指定 74 | if (*channel == '_' && (node & 0x01) && node < ISDB_T_NODE_LIMIT) 75 | { 76 | if (isdigit((int)*++channel)) 77 | { 78 | slot = *channel - '0'; 79 | if (*++channel == '\0' && slot < ISDB_T_SLOT_LIMIT) 80 | return (ARIB_BS << 16) | (node << 4) | slot; 81 | } 82 | } 83 | return ARIB_CH_ERROR; 84 | case 11: // CS 85 | if (*channel == '\0' && 2 <= node && node <= ISDB_T_NODE_LIMIT) 86 | return (ARIB_CS << 16) | node; 87 | return ARIB_CH_ERROR; 88 | case 10: // CATV 89 | if (*channel == '\0' && 13 <= node && node <= 63) 90 | { 91 | if (node >= 23) 92 | freqno = node - 1; 93 | else 94 | freqno = node - 10; 95 | return (ARIB_CATV << 16) | freqno; 96 | } 97 | return ARIB_CH_ERROR; 98 | case 0: // number 99 | if (*channel == '\0' && node) 100 | { 101 | if (node <= 63) 102 | { 103 | // 地上波 104 | if (node <= 3) 105 | freqno = node - 1; 106 | else if (node <= 12) 107 | freqno = node + 9; 108 | else 109 | freqno = node + 50; 110 | return (ARIB_GROUND << 16) | freqno; 111 | } 112 | else if (101 <= node && node <= 999) 113 | { 114 | // BS sid指定(あくまでチャンネル指定でありTS分離指示は別) 115 | return (ARIB_BS_SID << 16) | node; 116 | } 117 | tsid = node; 118 | } 119 | else 120 | return ARIB_CH_ERROR; 121 | } 122 | } 123 | // TransportStreamID指定 124 | if (*channel == '\0' && 0x4010U <= tsid && tsid <= 0x7fffU) 125 | { 126 | node = (tsid & 0x01f0U) >> 4; 127 | slot = tsid & 0x0007U; 128 | switch (tsid & 0xf008U) 129 | { 130 | case 0x4000U: // BS 131 | if (node == 15) 132 | { 133 | if (slot > 0) 134 | slot--; 135 | else 136 | return ARIB_CH_ERROR; 137 | } 138 | if ((node & 0x0001) && node < ISDB_T_NODE_LIMIT && slot < ISDB_T_SLOT_LIMIT) 139 | return (ARIB_TSID << 16) | tsid; 140 | break; 141 | case 0x6000U: // CS 142 | case 0x7000U: 143 | if ((node & 0x0001) == 0 && 2 <= node && node <= ISDB_T_NODE_LIMIT && slot == 0) 144 | return (ARIB_TSID << 16) | tsid; 145 | break; 146 | } 147 | } 148 | return ARIB_CH_ERROR; 149 | } 150 | 151 | #endif // _BONDRIVER_LINUXPT_H_ 152 | #endif // _BONDRIVER_DVB_H_ 153 | -------------------------------------------------------------------------------- /BonDriver_DVB.so.conf: -------------------------------------------------------------------------------- 1 | #ADAPTER_NO=0 2 | #GETCNRMODE=0 3 | #USELNB=0 4 | #USESERVICEID=0 5 | ; #B25=1 6 | ; #STRIP=1 7 | ; #EMM=1 8 | ; #MULTI2ROUND=4 9 | ; 名称, BonDriverとしてのチャンネル番号, 周波数テーブル番号, TSID, サービスID 10 | ; 記述はタブ区切り 11 | #ISDB_S 12 | ; BS 13 | BS朝日 0 0 0x4010 151 14 | BS-TBS 1 0 0x4011 161 15 | WOWOWプライム 2 1 0x4030 191 16 | BSジャパン 3 1 0x4031 171 17 | WOWOWライブ 4 2 0x4450 192 18 | WOWOWシネマ 5 2 0x4451 193 19 | スターチャンネル2 6 3 0x4470 201 20 | スターチャンネル3 7 3 0x4470 202 21 | BSアニマックス 8 3 0x4671 236 22 | ディズニーチャンネル 9 3 0x4672 256 23 | BS11 10 4 0x4090 211 24 | スターチャンネル1 11 4 0x4091 200 25 | TwellV 12 4 0x4092 222 26 | FOX bs238 13 5 0x46b0 238 27 | BSスカパー! 14 5 0x46b1 241 28 | 放送大学BS1 15 5 0x46b2 231 29 | 放送大学BS2 16 5 0x46b2 232 30 | 放送大学BS3 17 5 0x46b2 233 31 | BS日テレ 18 6 0x40d0 141 32 | BSフジ 19 6 0x40d1 181 33 | NHK-BS1 20 7 0x40f1 101 34 | NHK-BSプレミアム 21 7 0x40f2 103 35 | 旧難視聴1 22 8 0x4310 291 36 | 旧難視聴2 23 8 0x4311 292 37 | 旧難視聴3 24 8 0x4312 293 38 | グリーンチャンネル 25 9 0x4730 234 39 | J Sports 1 26 9 0x4731 242 40 | J Sports 2 27 9 0x4732 243 41 | IMAGICA BS 28 10 0x4750 252 42 | J Sports 3 29 10 0x4751 244 43 | J Sports 4 30 10 0x4752 245 44 | BS釣りビジョン 31 11 0x4770 251 45 | BS日本映画専門チャンネル 32 11 0x4771 255 46 | D-Life 33 11 0x4772 258 47 | ; CS110 48 | ND2 34 12 0x6020 0 49 | ND4 35 13 0x7040 0 50 | ND6 36 14 0x7060 0 51 | ND8 37 15 0x6080 0 52 | ND10 38 16 0x60a0 0 53 | ND12 39 17 0x70c0 0 54 | ND14 40 18 0x70e0 0 55 | ND16 41 19 0x7100 0 56 | ND18 42 20 0x7120 0 57 | ND20 43 21 0x7140 0 58 | ND22 44 22 0x7160 0 59 | ND24 45 23 0x7180 0 60 | 61 | #ISDB_T 62 | 1 0 0 0 0 63 | 2 1 1 0 0 64 | 3 2 2 0 0 65 | C13 3 3 0 0 66 | C14 4 4 0 0 67 | C15 5 5 0 0 68 | C16 6 6 0 0 69 | C17 7 7 0 0 70 | C18 8 8 0 0 71 | C19 9 9 0 0 72 | C20 10 10 0 0 73 | C21 11 11 0 0 74 | C22 12 12 0 0 75 | 4 13 13 0 0 76 | 5 14 14 0 0 77 | 6 15 15 0 0 78 | 7 16 16 0 0 79 | 8 17 17 0 0 80 | 9 18 18 0 0 81 | 10 19 19 0 0 82 | 11 20 20 0 0 83 | 12 21 21 0 0 84 | C23 22 22 0 0 85 | C24 23 23 0 0 86 | C25 24 24 0 0 87 | C26 25 25 0 0 88 | C27 26 26 0 0 89 | C28 27 27 0 0 90 | C29 28 28 0 0 91 | C30 29 29 0 0 92 | C31 30 30 0 0 93 | C32 31 31 0 0 94 | C33 32 32 0 0 95 | C34 33 33 0 0 96 | C35 34 34 0 0 97 | C36 35 35 0 0 98 | C37 36 36 0 0 99 | C38 37 37 0 0 100 | C39 38 38 0 0 101 | C40 39 39 0 0 102 | C41 40 40 0 0 103 | C42 41 41 0 0 104 | C43 42 42 0 0 105 | C44 43 43 0 0 106 | C45 44 44 0 0 107 | C46 45 45 0 0 108 | C47 46 46 0 0 109 | C48 47 47 0 0 110 | C49 48 48 0 0 111 | C50 49 49 0 0 112 | C51 50 50 0 0 113 | C52 51 51 0 0 114 | C53 52 52 0 0 115 | C54 53 53 0 0 116 | C55 54 54 0 0 117 | C56 55 55 0 0 118 | C57 56 56 0 0 119 | C58 57 57 0 0 120 | C59 58 58 0 0 121 | C60 59 59 0 0 122 | C61 60 60 0 0 123 | C62 61 61 0 0 124 | C63 62 62 0 0 125 | 13 63 63 0 0 126 | 14 64 64 0 0 127 | 15 65 65 0 0 128 | 16 66 66 0 0 129 | 17 67 67 0 0 130 | 18 68 68 0 0 131 | 19 69 69 0 0 132 | 20 70 70 0 0 133 | 21 71 71 0 0 134 | 22 72 72 0 0 135 | 23 73 73 0 0 136 | 24 74 74 0 0 137 | 25 75 75 0 0 138 | 26 76 76 0 0 139 | 27 77 77 0 0 140 | 28 78 78 0 0 141 | 29 79 79 0 0 142 | 30 80 80 0 0 143 | 31 81 81 0 0 144 | 32 82 82 0 0 145 | 33 83 83 0 0 146 | 34 84 84 0 0 147 | 35 85 85 0 0 148 | 36 86 86 0 0 149 | 37 87 87 0 0 150 | 38 88 88 0 0 151 | 39 89 89 0 0 152 | 40 90 90 0 0 153 | 41 91 91 0 0 154 | 42 92 92 0 0 155 | 43 93 93 0 0 156 | 44 94 94 0 0 157 | 45 95 95 0 0 158 | 46 96 96 0 0 159 | 47 97 97 0 0 160 | 48 98 98 0 0 161 | 49 99 99 0 0 162 | 50 100 100 0 0 163 | 51 101 101 0 0 164 | 52 102 102 0 0 165 | 53 103 103 0 0 166 | 54 104 104 0 0 167 | 55 105 105 0 0 168 | 56 106 106 0 0 169 | 57 107 107 0 0 170 | 58 108 108 0 0 171 | 59 109 109 0 0 172 | 60 110 110 0 0 173 | 61 111 111 0 0 174 | 62 112 112 0 0 175 | 63 113 113 0 0 176 | -------------------------------------------------------------------------------- /BonDriver_LinuxPT.so.conf: -------------------------------------------------------------------------------- 1 | #DEVICE=/dev/pt3video0 2 | #USELNB=0 3 | #USESERVICEID=0 4 | ; #B25=1 5 | ; #STRIP=1 6 | ; #EMM=1 7 | ; #MULTI2ROUND=4 8 | ; 名称, BonDriverとしてのチャンネル番号, 周波数テーブル番号, スロット番号/加算する周波数, サービスID 9 | ; 記述はタブ区切り 10 | #ISDB_S 11 | ; BS 12 | BS朝日 0 0 0 151 13 | BS-TBS 1 0 1 161 14 | WOWOWプライム 2 1 0 191 15 | BSジャパン 3 1 1 171 16 | WOWOWライブ 4 2 0 192 17 | WOWOWシネマ 5 2 1 193 18 | スターチャンネル2 6 3 0 201 19 | スターチャンネル3 7 3 0 202 20 | BSアニマックス 8 3 1 236 21 | ディズニーチャンネル 9 3 2 256 22 | BS11 10 4 0 211 23 | スターチャンネル1 11 4 1 200 24 | TwellV 12 4 2 222 25 | FOX bs238 13 5 0 238 26 | BSスカパー! 14 5 1 241 27 | 放送大学BS1 15 5 2 231 28 | 放送大学BS2 16 5 2 232 29 | 放送大学BS3 17 5 2 233 30 | BS日テレ 18 6 0 141 31 | BSフジ 19 6 1 181 32 | NHK-BS1 20 7 0 101 33 | NHK-BSプレミアム 21 7 1 103 34 | 旧難視聴1 22 8 0 291 35 | 旧難視聴2 23 8 1 292 36 | 旧難視聴3 24 8 2 293 37 | グリーンチャンネル 25 9 0 234 38 | J Sports 1 26 9 1 242 39 | J Sports 2 27 9 2 243 40 | IMAGICA BS 28 10 0 252 41 | J Sports 3 29 10 1 244 42 | J Sports 4 30 10 2 245 43 | BS釣りビジョン 31 11 0 251 44 | BS日本映画専門チャンネル 32 11 1 255 45 | D-Life 33 11 2 258 46 | ; CS110 47 | ND2 34 12 0 0 48 | ND4 35 13 0 0 49 | ND6 36 14 0 0 50 | ND8 37 15 0 0 51 | ND10 38 16 0 0 52 | ND12 39 17 0 0 53 | ND14 40 18 0 0 54 | ND16 41 19 0 0 55 | ND18 42 20 0 0 56 | ND20 43 21 0 0 57 | ND22 44 22 0 0 58 | ND24 45 23 0 0 59 | 60 | #ISDB_T 61 | 1 0 0 0 0 62 | 2 1 1 0 0 63 | 3 2 2 0 0 64 | C13 3 3 0 0 65 | C14 4 4 0 0 66 | C15 5 5 0 0 67 | C16 6 6 0 0 68 | C17 7 7 0 0 69 | C18 8 8 0 0 70 | C19 9 9 0 0 71 | C20 10 10 0 0 72 | C21 11 11 0 0 73 | C22 12 12 0 0 74 | 4 13 13 0 0 75 | 5 14 14 0 0 76 | 6 15 15 0 0 77 | 7 16 16 0 0 78 | 8 17 17 0 0 79 | 9 18 18 0 0 80 | 10 19 19 0 0 81 | 11 20 20 0 0 82 | 12 21 21 0 0 83 | C23 22 22 0 0 84 | C24 23 23 0 0 85 | C25 24 24 0 0 86 | C26 25 25 0 0 87 | C27 26 26 0 0 88 | C28 27 27 0 0 89 | C29 28 28 0 0 90 | C30 29 29 0 0 91 | C31 30 30 0 0 92 | C32 31 31 0 0 93 | C33 32 32 0 0 94 | C34 33 33 0 0 95 | C35 34 34 0 0 96 | C36 35 35 0 0 97 | C37 36 36 0 0 98 | C38 37 37 0 0 99 | C39 38 38 0 0 100 | C40 39 39 0 0 101 | C41 40 40 0 0 102 | C42 41 41 0 0 103 | C43 42 42 0 0 104 | C44 43 43 0 0 105 | C45 44 44 0 0 106 | C46 45 45 0 0 107 | C47 46 46 0 0 108 | C48 47 47 0 0 109 | C49 48 48 0 0 110 | C50 49 49 0 0 111 | C51 50 50 0 0 112 | C52 51 51 0 0 113 | C53 52 52 0 0 114 | C54 53 53 0 0 115 | C55 54 54 0 0 116 | C56 55 55 0 0 117 | C57 56 56 0 0 118 | C58 57 57 0 0 119 | C59 58 58 0 0 120 | C60 59 59 0 0 121 | C61 60 60 0 0 122 | C62 61 61 0 0 123 | C63 62 62 0 0 124 | 13 63 63 0 0 125 | 14 64 64 0 0 126 | 15 65 65 0 0 127 | 16 66 66 0 0 128 | 17 67 67 0 0 129 | 18 68 68 0 0 130 | 19 69 69 0 0 131 | 20 70 70 0 0 132 | 21 71 71 0 0 133 | 22 72 72 0 0 134 | 23 73 73 0 0 135 | 24 74 74 0 0 136 | 25 75 75 0 0 137 | 26 76 76 0 0 138 | 27 77 77 0 0 139 | 28 78 78 0 0 140 | 29 79 79 0 0 141 | 30 80 80 0 0 142 | 31 81 81 0 0 143 | 32 82 82 0 0 144 | 33 83 83 0 0 145 | 34 84 84 0 0 146 | 35 85 85 0 0 147 | 36 86 86 0 0 148 | 37 87 87 0 0 149 | 38 88 88 0 0 150 | 39 89 89 0 0 151 | 40 90 90 0 0 152 | 41 91 91 0 0 153 | 42 92 92 0 0 154 | 43 93 93 0 0 155 | 44 94 94 0 0 156 | 45 95 95 0 0 157 | 46 96 96 0 0 158 | 47 97 97 0 0 159 | 48 98 98 0 0 160 | 49 99 99 0 0 161 | 50 100 100 0 0 162 | 51 101 101 0 0 163 | 52 102 102 0 0 164 | 53 103 103 0 0 165 | 54 104 104 0 0 166 | 55 105 105 0 0 167 | 56 106 106 0 0 168 | 57 107 107 0 0 169 | 58 108 108 0 0 170 | 59 109 109 0 0 171 | 60 110 110 0 0 172 | 61 111 111 0 0 173 | 62 112 112 0 0 174 | 63 113 113 0 0 175 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | 676 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | DESTDIR = 2 | prefix = @prefix@ 3 | exec_prefix = @exec_prefix@ 4 | bindir = @bindir@ 5 | #CC = @CC@ 6 | CC = g++ 7 | 8 | TARGET = recbond 9 | TARGET2 = recpt1ctl 10 | TARGET3 = checkbond 11 | TARGETS = $(TARGET) $(TARGET2) $(TARGET3) 12 | RELEASE_VERSION = "1.0.0" 13 | 14 | CXX = g++ 15 | CPPFLAGS = -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 16 | CXXFLAGS = -O2 -g -pthread 17 | CFLAGS = -O2 -g -pthread 18 | 19 | LIBS = @LIBS@ -ldl -rdynamic 20 | LIBS2 = -ldl 21 | LIBS3 = -lpthread -ldl -rdynamic 22 | LDFLAGS = 23 | 24 | OBJS = recpt1.o decoder.o mkpath.o tssplitter_lite.o recpt1core.o 25 | OBJS2 = recpt1ctl.o recpt1core.o 26 | OBJS3 = checksignal.o recpt1core.o 27 | OBJALL = $(OBJS) $(OBJS2) $(OBJS3) 28 | DEPEND = .deps 29 | 30 | ifdef EXTRA_SID 31 | CPPFLAGS += -DENABLE_EXTRA_SID 32 | endif 33 | 34 | all: $(TARGETS) 35 | 36 | clean: 37 | rm -f $(OBJALL) $(TARGETS) $(DEPEND) version.h 38 | 39 | distclean: clean 40 | rm -f Makefile config.h config.log config.status 41 | 42 | maintainer-clean: distclean 43 | rm -fr configure config.h.in aclocal.m4 autom4te.cache *~ 44 | 45 | $(TARGET): $(OBJS) 46 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) 47 | 48 | $(TARGET2): $(OBJS2) 49 | $(CC) $(LDFLAGS) -o $@ $(OBJS2) $(LIBS2) 50 | 51 | $(TARGET3): $(OBJS3) 52 | $(CC) $(LDFLAGS) -o $@ $(OBJS3) $(LIBS3) 53 | 54 | $(DEPEND): version.h 55 | $(CC) -MM $(OBJS:.o=.c) $(OBJS2:.o=.c) $(CPPFLAGS) > $@ 56 | 57 | version.h: 58 | revh=`hg parents --template 'const char *version = "r{rev}:{node|short} ({date|shortdate})";\n' 2>/dev/null`; \ 59 | if [ -n "$$revh" ] ; then \ 60 | echo "$$revh" > $@; \ 61 | else \ 62 | echo "const char *version = \"$(RELEASE_VERSION)\";" > $@; \ 63 | fi 64 | 65 | install: $(TARGET) 66 | install -m 755 $(TARGETS) $(DESTDIR)$(bindir) 67 | 68 | -include .deps 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- recbond --- 2 | 3 | これは、recpt1(http://hg.honeyplanet.jp/pt1/)+httpサーバパッチをベースにした 4 | Linux用BonDriver録画コマンドです。 5 | 今までのソフト資産を生かしつつLinuxだけで完結する環境下での運用を想定しています。 6 | 7 | BonDriverProxy_Linux(https://github.com/u-n-k-n-o-w-n/BonDriverProxy_Linux)の 8 | ヘッダーファイルをインクルードしていますのでBonDriverProxy_Linuxのソースディレクトリ上に 9 | recbondのディレクトリ"./recbond"を残したまま展開してrecpt1と同じ手順でビルドしてください。 10 | 11 | 12 | [オプション] 13 | recpt1のものをそのまま受け継いでいますが"--LNB"と"--device"を廃止、BonDriver指定 14 | "--driver"とスペース指定"--space"を追加しています。 15 | あと「字幕が出ない」と言われてしまうので無効化してありますが"--sid"のストリーム指定子に 16 | "epg1seg"(1セグ用EPG)・"caption"(字幕)・"esdata"(データ放送等)が追加されています。 17 | 有効化する場合は、"EXTRA_SID=1 make"てな感じでビルド時に環境変数を渡してやってください。 18 | 19 | 20 | [チャンネル指定] 21 | BonDriverチャンネル指定に加えrecpt1で使われている従来のものをそのまま使用できます。 22 | またBS/CSについてはDVB対応のためにTSIDによる指定(16進数か10進数)を新たに加えました。 23 | なおBonDriverチャンネル指定方法は、"Bn"(nは0から始まる数字)となります。 24 | 25 | 全てのチャンネル指定方法を有効にするにはBonDriverのチャンネル定義とrecbond/pt1_dev.h 26 | のチャンネル定義を並びも含めて同期させる必要があります。 27 | 28 | LinuxのBonDriverの場合は、BonDriverに同梱のパッチ linux_ch.diffをあててconfファイル 29 | を差し替えることにより全てのチャンネル指定方法が利用可能です。 30 | 31 | WindowsのBonDriverをBonDriverProxy経由で使用する場合は、BonDriverのiniファイルの 32 | チャンネル定義をrecbond/pt1_dev.hのそれと同期させる必要があります。同梱のconfファイル 33 | を参考にして変更してください。 34 | sidとTSIDでのチャンネル指定はBonDriverの改造が必要なので使えないものと考えてください。 35 | いろいろ面倒な場合は、BonDriverチャンネル指定方法でお願いします。 36 | (注意:BonDriverが動くWindows環境が無いので適当に書いています) 37 | 38 | 39 | [スペース指定] 40 | 省略時は、0が設定されます。 41 | 42 | 43 | [BonDriver指定] 44 | フルパス指定の他に短縮指定が行なえます。 45 | またBonDriverチャンネル指定以外で省略された場合は、自動選択されます。 46 | 47 | 短縮指定と自動選択を利用する場合は、ビルド時に recbond/pt1_dev.hを編集して各BonDriver 48 | のファイルパスをフルパスで登録してください。 49 | 50 | 短縮指定の指定方法は、地デジが"Tn"・BS/CSは"Sn"(nは0から始まる数字)です。 51 | 52 | BonDriver_Proxy(クライアント)を利用する場合は、短縮指定時に"P"を頭に付加してください。 53 | 自動選択時は、"P"を単独で指定してください。 54 | 55 | 56 | [備考] 57 | ・チャンネル定義をいじらない 58 | 「BonDriverチャンネル指定しか使わないぜ!」という場合を除き一切変更してはいけません。 59 | もちろんチャンネルスキャンは考慮しませんしBonDriver_LinuxPTやBonDriver_DVBのサービス 60 | 絞込み(#USESERVICEID=1)は以ての外です。 61 | BSで局編成の変更があった場合は、がんばって変更してください。 62 | ・実録画時間が変動する 63 | 録画コマンドで受け取る前にストリームを加工していると実録画時間が変動します。 64 | BonDriver直接利用で-1秒ぐらい、BonDriverProxy経由で±1秒ぐらい変動します。 65 | よって1~2秒長めに時間指示するようにしてください。 66 | ・BonDriverProxy使用時にBonDriver指定を省略した場合は、指定チャンネル受信中チューナー 67 | を探査して無ければ空きチューナーを探してチューニングを行います。 68 | 69 | 70 | version 1.0.1 (2015/04/04) 71 | ・BS難視聴対策チャンネルを整理 72 | ・CSが受信できないバグを修正 73 | ・BonDriver自動選択処理を見直し 74 | ・httpサーバーのリクエストコマンド取り込みバッファーのオーバーフロー対策 75 | 76 | version 1.0.0 (2015/03/01) 77 | ・初版リリース 78 | -------------------------------------------------------------------------------- /README.md~: -------------------------------------------------------------------------------- 1 | --- recbond --- 2 | 3 | これは、recpt1(http://hg.honeyplanet.jp/pt1/)+httpサーバパッチをベースにした 4 | Linux用BonDriver録画コマンドです。 5 | 今までのソフト資産を生かしつつLinuxだけで完結する環境下での運用を想定しています。 6 | 7 | BonDriverProxy_Linux(https://github.com/u-n-k-n-o-w-n/BonDriverProxy_Linux)の 8 | ヘッダーファイルをインクルードしていますのでBonDriverProxy_Linuxのソースディレクトリ上に 9 | recbondのディレクトリ"./recbond"を残したまま展開してrecpt1と同じ手順でビルドしてください。 10 | 11 | 12 | [オプション] 13 | recpt1のものをそのまま受け継いでいますが"--LNB"と"--device"を廃止、BonDriver指定 14 | "--driver"とスペース指定"--space"を追加しています。 15 | あと「字幕が出ない」と言われてしまうので無効化してありますが"--sid"のストリーム指定子に 16 | "epg1seg"(1セグ用EPG)・"caption"(字幕)・"esdata"(データ放送等)が追加されています。 17 | 有効化する場合は、"EXTRA_SID=1 make"てな感じでビルド時に環境変数を渡してやってください。 18 | 19 | 20 | [チャンネル指定] 21 | BonDriverチャンネル指定に加えrecpt1で使われている従来のものをそのまま使用できます。 22 | またBS/CSについてはDVB対応のためにTSIDによる指定(16進数か10進数)を新たに加えました。 23 | なおBonDriverチャンネル指定方法は、"Bn"(nは0から始まる数字)となります。 24 | 25 | 全てのチャンネル指定方法を有効にするにはBonDriverのチャンネル定義とrecbond/pt1_dev.h 26 | のチャンネル定義を並びも含めて同期させる必要があります。 27 | 28 | LinuxのBonDriverの場合は、BonDriverに同梱のパッチ linux_ch.diffをあててconfファイル 29 | を差し替えることにより全てのチャンネル指定方法が利用可能です。 30 | 31 | WindowsのBonDriverをBonDriverProxy経由で使用する場合は、BonDriverのiniファイルの 32 | チャンネル定義をrecbond/pt1_dev.hのそれと同期させる必要があります。同梱のconfファイル 33 | を参考にして変更してください。 34 | sidとTSIDでのチャンネル指定はBonDriverの改造が必要なので使えないものと考えてください。 35 | いろいろ面倒な場合は、BonDriverチャンネル指定方法でお願いします。 36 | (注意:BonDriverが動くWindows環境が無いので適当に書いています) 37 | 38 | 39 | [スペース指定] 40 | 省略時は、0が設定されます。 41 | 42 | 43 | [BonDriver指定] 44 | フルパス指定の他に短縮指定が行なえます。 45 | またBonDriverチャンネル指定以外で省略された場合は、自動選択されます。 46 | 47 | 短縮指定と自動選択を利用する場合は、ビルド時に recbond/pt1_dev.hを編集して各BonDriver 48 | のファイルパスをフルパスで登録してください。 49 | 50 | 短縮指定の指定方法は、地デジが"Tn"・BS/CSは"Sn"(nは0から始まる数字)です。 51 | 52 | BonDriver_Proxy(クライアント)を利用する場合は、短縮指定時に"P"を頭に付加してください。 53 | 自動選択時は、"P"を単独で指定してください。 54 | 55 | 56 | [備考] 57 | ・チャンネル定義をいじらない 58 | 「BonDriverチャンネル指定しか使わないぜ!」という場合を除き一切変更してはいけません。 59 | もちろんチャンネルスキャンは考慮しませんしBonDriver_LinuxPTやBonDriver_DVBのサービス 60 | 絞込み(#USESERVICEID=1)は以ての外です。 61 | BSで局編成の変更があった場合は、がんばって変更してください。 62 | ・実録画時間が変動する 63 | 録画コマンドで受け取る前にストリームを加工していると実録画時間が変動します。 64 | BonDriver直接利用で-1秒ぐらい、BonDriverProxy経由で±1秒ぐらい変動します。 65 | よって1~2秒長めに時間指示するようにしてください。 66 | ・BonDriverProxy使用時にBonDriver指定を省略した場合は、指定チャンネル受信中チューナー 67 | を探査して無ければ空きチューナーを探してチューニングを行います。 68 | 69 | 70 | version 1.0.1 (2015/04/04) 71 | ・BS難視聴対策チャンネルを整理 72 | ・CSが受信できないバグを修正 73 | ・BonDriver自動選択処理を見直し 74 | ・httpサーバーのリクエストコマンド取り込みバッファーのオーバーフロー対策 75 | 76 | version 1.0.0 (2015/03/01) 77 | ・初版リリース 78 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | [ -f configure.ac ] || { 4 | echo "autogen.sh: run this command only at the top of a recpt1 source tree." 5 | exit 1 6 | } 7 | 8 | DIE=0 9 | 10 | (autoconf --version) < /dev/null > /dev/null 2>&1 || { 11 | echo 12 | echo "You must have autoconf installed to compile recpt1." 13 | echo "Get ftp://ftp.gnu.org/pub/gnu/autoconf/autoconf-2.62.tar.gz" 14 | echo "(or a newer version if it is available)" 15 | DIE=1 16 | NO_AUTOCONF=yes 17 | } 18 | 19 | (automake --version) < /dev/null > /dev/null 2>&1 || { 20 | echo 21 | echo "You must have automake installed to compile recpt1." 22 | echo "Get ftp://ftp.gnu.org/pub/gnu/automake/automake-1.10.1.tar.gz" 23 | echo "(or a newer version if it is available)" 24 | DIE=1 25 | NO_AUTOMAKE=yes 26 | } 27 | 28 | # if no automake, don't bother testing for aclocal 29 | test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { 30 | echo 31 | echo "**Error**: Missing \`aclocal'. The version of \`automake'" 32 | echo "installed doesn't appear recent enough." 33 | echo "Get ftp://ftp.gnu.org/pub/gnu/automake/automake-1.10.1.tar.gz" 34 | echo "(or a newer version if it is available)" 35 | DIE=1 36 | } 37 | 38 | # if no autoconf, don't bother testing for autoheader 39 | test -n "$NO_AUTOCONF" || (autoheader --version) < /dev/null > /dev/null 2>&1 || { 40 | echo 41 | echo "**Error**: Missing \`autoheader'. The version of \`autoheader'" 42 | echo "installed doesn't appear recent enough." 43 | echo "Get ftp://ftp.gnu.org/pub/gnu/autoconf/autoconf-2.62.tar.gz" 44 | echo "(or a newer version if it is available)" 45 | DIE=1 46 | } 47 | 48 | if test "$DIE" -eq 1; then 49 | exit 1 50 | fi 51 | 52 | echo "Generating configure script and Makefiles for recpt1." 53 | 54 | echo "Running aclocal ..." 55 | aclocal -I . 56 | echo "Running autoheader ..." 57 | autoheader 58 | echo "Running autoconf ..." 59 | autoconf 60 | -------------------------------------------------------------------------------- /channels/sample.recpt1-channels-chiba: -------------------------------------------------------------------------------- 1 | 20ch: Tokyo MX TV 2 | 21ch: Fuji TV 3 | 22ch: TBS 4 | 23ch: TV Tokyo 5 | 24ch: TV Asahi 6 | 25ch: Nihon TV 7 | 26ch: NHK Educational 8 | 27ch: NHK General 9 | 28ch: Housou Daigaku 10 | 30ch: CTC Chiba TV 11 | -------------------------------------------------------------------------------- /channels/sample.recpt1-channels-kanazawa: -------------------------------------------------------------------------------- 1 | 13ch: NHK Educational 2 | 14ch: MRO 3 | 15ch: NHK General 4 | 16ch: Ishikawa TV 5 | 17ch: TV Kanazawa 6 | 23ch: Hokuriku Asahi 7 | -------------------------------------------------------------------------------- /channels/sample.recpt1-channels-nagoya: -------------------------------------------------------------------------------- 1 | 13ch: NHK Educational 2 | 18ch: CBC 3 | 19ch: Chukyo TV 4 | 20ch: NHK Gemeral 5 | 21ch: Tokai TV 6 | 22ch: Nagoya TV (mei tere) 7 | 23ch: TV Aichi 8 | 27ch: Mie TV 9 | -------------------------------------------------------------------------------- /channels/sample.recpt1-channels-tokyo: -------------------------------------------------------------------------------- 1 | 20ch: Tokyo MX TV 2 | 21ch: Fuji TV 3 | 22ch: TBS 4 | 23ch: TV Tokyo 5 | 24ch: TV Asahi 6 | 25ch: Nihon TV 7 | 26ch: NHK Educational 8 | 27ch: NHK General 9 | 28ch: Housou Daigaku 10 | -------------------------------------------------------------------------------- /checksignal.c: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | //#include "pt1_ioctl.h" 25 | 26 | #include "config.h" 27 | #include "decoder.h" 28 | #include "recpt1core.h" 29 | #include "mkpath.h" 30 | 31 | #include 32 | #include 33 | #include "tssplitter_lite.h" 34 | 35 | /* prototypes */ 36 | int tune(char *channel, thread_data *tdata, char *driver); 37 | int close_tuner(thread_data *tdata); 38 | 39 | void 40 | cleanup(thread_data *tdata) 41 | { 42 | f_exit = TRUE; 43 | } 44 | 45 | /* will be signal handler thread */ 46 | void * 47 | process_signals(void *data) 48 | { 49 | sigset_t waitset; 50 | int sig; 51 | thread_data *tdata = (thread_data *)data; 52 | 53 | sigemptyset(&waitset); 54 | sigaddset(&waitset, SIGINT); 55 | sigaddset(&waitset, SIGTERM); 56 | sigaddset(&waitset, SIGUSR1); 57 | 58 | sigwait(&waitset, &sig); 59 | 60 | switch(sig) { 61 | case SIGINT: 62 | fprintf(stderr, "\nSIGINT received. cleaning up...\n"); 63 | cleanup(tdata); 64 | break; 65 | case SIGTERM: 66 | fprintf(stderr, "\nSIGTERM received. cleaning up...\n"); 67 | cleanup(tdata); 68 | break; 69 | case SIGUSR1: /* normal exit*/ 70 | cleanup(tdata); 71 | break; 72 | } 73 | 74 | return NULL; /* dummy */ 75 | } 76 | 77 | void 78 | init_signal_handlers(pthread_t *signal_thread, thread_data *tdata) 79 | { 80 | sigset_t blockset; 81 | 82 | sigemptyset(&blockset); 83 | sigaddset(&blockset, SIGINT); 84 | sigaddset(&blockset, SIGTERM); 85 | sigaddset(&blockset, SIGUSR1); 86 | 87 | if(pthread_sigmask(SIG_BLOCK, &blockset, NULL)) 88 | fprintf(stderr, "pthread_sigmask() failed.\n"); 89 | 90 | pthread_create(signal_thread, NULL, process_signals, tdata); 91 | } 92 | 93 | void 94 | show_usage(char *cmd) 95 | { 96 | // fprintf(stderr, "Usage: \n%s [--driver devicefile] [--lnb voltage] [--bell] channel\n", cmd); 97 | fprintf(stderr, "Usage: \n%s [--driver devicefile] [--bell] channel\n", cmd); 98 | fprintf(stderr, "\n"); 99 | } 100 | 101 | void 102 | show_options(void) 103 | { 104 | fprintf(stderr, "Options:\n"); 105 | fprintf(stderr, "--driver devicefile: Specify devicefile to use\n"); 106 | // fprintf(stderr, "--lnb voltage: Specify LNB voltage (0, 11, 15)\n"); 107 | fprintf(stderr, "--bell: Notify signal quality by bell\n"); 108 | fprintf(stderr, "--help: Show this help\n"); 109 | fprintf(stderr, "--version: Show version\n"); 110 | fprintf(stderr, "--list: Show channel list\n"); 111 | } 112 | 113 | int 114 | main(int argc, char **argv) 115 | { 116 | pthread_t signal_thread; 117 | static thread_data tdata; 118 | int result; 119 | int option_index; 120 | struct option long_options[] = { 121 | { "bell", 0, NULL, 'b'}, 122 | { "help", 0, NULL, 'h'}, 123 | { "version", 0, NULL, 'v'}, 124 | { "list", 0, NULL, 'l'}, 125 | // { "LNB", 1, NULL, 'n'}, 126 | { "lnb", 1, NULL, 'n'}, 127 | { "driver", 1, NULL, 'd'}, 128 | {0, 0, NULL, 0} /* terminate */ 129 | }; 130 | 131 | tdata.hModule = NULL; 132 | tdata.dwSpace = 0; 133 | tdata.table = NULL; 134 | tdata.lnb = 0; 135 | char *driver = NULL; 136 | #if 0 137 | int val; 138 | char *voltage[] = {"0V", "11V", "15V"}; 139 | #endif 140 | boolean use_bell = FALSE; 141 | 142 | while((result = getopt_long(argc, argv, "bhvln:d:", 143 | long_options, &option_index)) != -1) { 144 | switch(result) { 145 | case 'b': 146 | use_bell = TRUE; 147 | break; 148 | case 'h': 149 | fprintf(stderr, "\n"); 150 | show_usage(argv[0]); 151 | fprintf(stderr, "\n"); 152 | show_options(); 153 | fprintf(stderr, "\n"); 154 | show_channels(); 155 | fprintf(stderr, "\n"); 156 | exit(0); 157 | break; 158 | case 'v': 159 | fprintf(stderr, "%s %s\n", argv[0], version); 160 | fprintf(stderr, "signal check utility for PT1/2 digital tuner.\n"); 161 | exit(0); 162 | break; 163 | case 'l': 164 | show_channels(); 165 | exit(0); 166 | break; 167 | #if 0 168 | /* following options require argument */ 169 | case 'n': 170 | val = atoi(optarg); 171 | switch(val) { 172 | case 11: 173 | tdata.lnb = 1; 174 | break; 175 | case 15: 176 | tdata.lnb = 2; 177 | break; 178 | default: 179 | tdata.lnb = 0; 180 | break; 181 | } 182 | fprintf(stderr, "LNB = %s\n", voltage[tdata.lnb]); 183 | break; 184 | #endif 185 | case 'd': 186 | driver = optarg; 187 | break; 188 | } 189 | } 190 | 191 | if(argc - optind < 1) { 192 | fprintf(stderr, "channel must be specified!\n"); 193 | fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]); 194 | return 1; 195 | } 196 | 197 | /* set tune_persistent flag */ 198 | tdata.tune_persistent = TRUE; 199 | 200 | /* spawn signal handler thread */ 201 | init_signal_handlers(&signal_thread, &tdata); 202 | 203 | /* tune */ 204 | if(tune(argv[optind], &tdata, driver) != 0) 205 | return 1; 206 | 207 | while(1) { 208 | if(f_exit) 209 | break; 210 | tdata.pIBon->PurgeTsStream(); // 凡ドラはCh設定時からストリームデータをバッファに溜め込むため追加 211 | /* show signal strength */ 212 | calc_cn(&tdata, use_bell); 213 | sleep(1); 214 | } 215 | 216 | /* wait for signal thread */ 217 | pthread_kill(signal_thread, SIGUSR1); 218 | pthread_join(signal_thread, NULL); 219 | 220 | /* close tuner */ 221 | if(close_tuner(&tdata) != 0) 222 | return 1; 223 | 224 | return 0; 225 | } 226 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.59) 5 | AC_INIT([recpt1], [1.2.0], yaz@honeyplanet.jp) 6 | AC_CONFIG_SRCDIR([recpt1.c]) 7 | AC_CONFIG_HEADERS([config.h]) 8 | 9 | # Checks for programs. 10 | AC_PROG_CC 11 | 12 | # Checks for b25 support. 13 | AC_ARG_ENABLE(b25, 14 | [AS_HELP_STRING([--enable-b25],[enable b25 support])], 15 | [AC_CHECK_LIB([arib25], [create_arib_std_b25], , [AC_MSG_WARN(libarb25 is not available.)])] 16 | ) 17 | 18 | # Checks for libraries. 19 | #AC_CHECK_LIB([m], [log10]) 20 | AC_CHECK_LIB([pthread], [pthread_kill]) 21 | 22 | AC_CONFIG_FILES([Makefile]) 23 | AC_OUTPUT 24 | -------------------------------------------------------------------------------- /decoder.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "decoder.h" 5 | 6 | #ifdef HAVE_LIBARIB25 7 | 8 | DECODER * 9 | b25_startup(decoder_options *opt) 10 | { 11 | DECODER *dec = (DECODER *)calloc(1, sizeof(DECODER)); 12 | int code; 13 | const char *err = NULL; 14 | 15 | dec->b25 = create_arib_std_b25(); 16 | if(!dec->b25) { 17 | err = "create_arib_std_b25 failed"; 18 | goto error; 19 | } 20 | 21 | code = dec->b25->set_multi2_round(dec->b25, opt->round); 22 | if(code < 0) { 23 | err = "set_multi2_round failed"; 24 | goto error; 25 | } 26 | 27 | code = dec->b25->set_strip(dec->b25, opt->strip); 28 | if(code < 0) { 29 | err = "set_strip failed"; 30 | goto error; 31 | } 32 | 33 | code = dec->b25->set_emm_proc(dec->b25, opt->emm); 34 | if(code < 0) { 35 | err = "set_emm_proc failed"; 36 | goto error; 37 | } 38 | 39 | dec->bcas = create_b_cas_card(); 40 | if(!dec->bcas) { 41 | err = "create_b_cas_card failed"; 42 | goto error; 43 | } 44 | code = dec->bcas->init(dec->bcas); 45 | if(code < 0) { 46 | err = "bcas->init failed"; 47 | goto error; 48 | } 49 | 50 | code = dec->b25->set_b_cas_card(dec->b25, dec->bcas); 51 | if(code < 0) { 52 | err = "set_b_cas_card failed"; 53 | goto error; 54 | } 55 | 56 | return dec; 57 | 58 | error: 59 | fprintf(stderr, "%s\n", err); 60 | free(dec); 61 | return NULL; 62 | } 63 | 64 | int 65 | b25_shutdown(DECODER *dec) 66 | { 67 | dec->b25->release(dec->b25); 68 | dec->bcas->release(dec->bcas); 69 | free(dec); 70 | 71 | return 0; 72 | } 73 | 74 | int 75 | b25_decode(DECODER *dec, ARIB_STD_B25_BUFFER *sbuf, ARIB_STD_B25_BUFFER *dbuf) 76 | { 77 | int code; 78 | 79 | code = dec->b25->put(dec->b25, sbuf); 80 | if(code < 0) { 81 | fprintf(stderr, "b25->put failed\n"); 82 | return code; 83 | } 84 | 85 | code = dec->b25->get(dec->b25, dbuf); 86 | if(code != 0) { 87 | fprintf(stderr, "b25->get failed\n"); 88 | return code; 89 | } 90 | 91 | return 0; 92 | } 93 | 94 | int 95 | b25_finish(DECODER *dec, ARIB_STD_B25_BUFFER *sbuf, ARIB_STD_B25_BUFFER *dbuf) 96 | { 97 | int code; 98 | 99 | code = dec->b25->flush(dec->b25); 100 | if(code < 0) { 101 | fprintf(stderr, "b25->flush failed\n"); 102 | return code; 103 | } 104 | 105 | code = dec->b25->get(dec->b25, dbuf); 106 | if(code < 0) { 107 | fprintf(stderr, "b25->get failed\n"); 108 | return code; 109 | } 110 | 111 | return code; 112 | } 113 | 114 | #else 115 | 116 | /* functions */ 117 | DECODER *b25_startup(decoder_options *opt) 118 | { 119 | return NULL; 120 | } 121 | 122 | int b25_shutdown(DECODER *dec) 123 | { 124 | return 0; 125 | } 126 | 127 | int b25_decode(DECODER *dec, 128 | ARIB_STD_B25_BUFFER *sbuf, 129 | ARIB_STD_B25_BUFFER *dbuf) 130 | { 131 | return 0; 132 | } 133 | 134 | int b25_finish(DECODER *dec, 135 | ARIB_STD_B25_BUFFER *sbuf, 136 | ARIB_STD_B25_BUFFER *dbuf) 137 | { 138 | return 0; 139 | } 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /decoder.h: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #ifndef _DECODER_H_ 3 | #define _DECODER_H_ 4 | 5 | #include 6 | #include "config.h" 7 | 8 | #ifdef HAVE_LIBARIB25 9 | 10 | #include 11 | #include 12 | 13 | typedef struct _decoder { 14 | ARIB_STD_B25 *b25; 15 | B_CAS_CARD *bcas; 16 | } DECODER; 17 | 18 | typedef struct _decoder_options { 19 | int round; 20 | int strip; 21 | int emm; 22 | } decoder_options; 23 | 24 | #else 25 | 26 | typedef struct { 27 | uint8_t *data; 28 | int32_t size; 29 | } ARIB_STD_B25_BUFFER; 30 | 31 | typedef struct _decoder { 32 | void *dummy; 33 | } DECODER; 34 | 35 | typedef struct _decoder_options { 36 | int round; 37 | int strip; 38 | int emm; 39 | } decoder_options; 40 | 41 | #endif 42 | 43 | /* prototypes */ 44 | DECODER *b25_startup(decoder_options *opt); 45 | int b25_shutdown(DECODER *dec); 46 | int b25_decode(DECODER *dec, 47 | ARIB_STD_B25_BUFFER *sbuf, 48 | ARIB_STD_B25_BUFFER *dbuf); 49 | int b25_finish(DECODER *dec, 50 | ARIB_STD_B25_BUFFER *sbuf, 51 | ARIB_STD_B25_BUFFER *dbuf); 52 | 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /linux_ch.diff: -------------------------------------------------------------------------------- 1 | --- old/BonDriver_DVB.cpp 2015-03-13 01:43:30.930590954 +0900 2 | +++ new/BonDriver_DVB.cpp 2015-03-16 22:07:30.619739932 +0900 3 | @@ -222,8 +222,7 @@ 4 | } 5 | g_stChannels[idx][dw].freq.frequencyno = ::atoi(cp[2]); 6 | g_stChannels[idx][dw].freq.tsid = ::strtoul(cp[3], NULL, 16); 7 | - if (g_UseServiceID) 8 | - g_stChannels[idx][dw].ServiceID = ::strtoul(cp[4], NULL, 10); 9 | + g_stChannels[idx][dw].ServiceID = ::strtoul(cp[4], NULL, 10); 10 | g_stChannels[idx][dw].bUnused = FALSE; 11 | } 12 | } 13 | @@ -235,6 +234,99 @@ 14 | return 0; 15 | } 16 | 17 | +#include "recbond/AribChannel.h" 18 | + 19 | +// linux環境下で標準的なチャンネル指定を仮変換したものをBonDriverチャンネル番号へ変換 20 | +const DWORD TransChannelAribToBon(const DWORD dwChannelSrc) 21 | +{ 22 | + DWORD dwChannel = dwChannelSrc & 0xFFFFU; 23 | + DWORD tsid,node,slot; 24 | + DWORD lp; 25 | + 26 | + switch(dwChannelSrc>>16) 27 | + { 28 | + case BON_CHANNEL: 29 | + return dwChannel; 30 | + case ARIB_GROUND: 31 | + case ARIB_CATV: 32 | + // g_stChannelsから探査 33 | + for (lp = 0; lp < MAX_CH; lp++) 34 | + { 35 | + if (!g_stChannels[0][lp].bUnused && g_stChannels[0][lp].freq.frequencyno == (int)dwChannel) 36 | + return lp; 37 | + } 38 | + break; 39 | + case ARIB_BS: 40 | + // g_stChannelsから探査 41 | + tsid = dwChannel; 42 | + node = (tsid & 0x01f0U) >> 4; 43 | + slot = tsid & 0x0007U; 44 | + if (node == 15) 45 | + tsid++; 46 | + for (lp = 0; lp> 4; 95 | + if ((tsid & 0xf000U) == 0x4000U) 96 | + g_stChannels[1][lp].freq.frequencyno = node / 2; // BS 97 | + else 98 | + g_stChannels[1][lp].freq.frequencyno = node / 2 + 11; // CS 99 | + ::sprintf(g_stChannels[1][lp].strChName, "0x%X", tsid); 100 | + g_stChannels[1][lp].freq.tsid = tsid; 101 | + g_stChannels[1][lp].bUnused = FALSE; 102 | + return lp; 103 | + } 104 | + } 105 | + break; 106 | + } 107 | + return ARIB_CH_ERROR; 108 | +} 109 | + 110 | static float CalcCNR_S(uint16_t signal) 111 | { 112 | static const float fCnrTable[] = { 113 | @@ -625,8 +717,9 @@ 114 | #define DTV_STREAM_ID DTV_ISDBS_TS_ID 115 | #endif 116 | 117 | -const BOOL cBonDriverDVB::SetChannel(const DWORD dwSpace, const DWORD dwChannel) 118 | +const BOOL cBonDriverDVB::SetChannel(const DWORD dwSpace, const DWORD dwChannelSrc) 119 | { 120 | + DWORD dwChannel = TransChannelAribToBon(dwChannelSrc); 121 | BOOL bFlag; 122 | if (!m_bTuner) 123 | goto err; 124 | --- old/BonDriver_LinuxPT.cpp 2015-03-13 01:43:30.930590954 +0900 125 | +++ new/BonDriver_LinuxPT.cpp 2015-03-16 22:07:54.751039786 +0900 126 | @@ -241,8 +241,7 @@ 127 | } 128 | g_stChannels[idx][dw].freq.frequencyno = ::atoi(cp[2]); 129 | g_stChannels[idx][dw].freq.slot = ::atoi(cp[3]); 130 | - if (g_UseServiceID) 131 | - g_stChannels[idx][dw].ServiceID = ::strtoul(cp[4], NULL, 10); 132 | + g_stChannels[idx][dw].ServiceID = ::strtoul(cp[4], NULL, 10); 133 | g_stChannels[idx][dw].bUnused = FALSE; 134 | } 135 | } 136 | @@ -254,6 +253,104 @@ 137 | return 0; 138 | } 139 | 140 | +#include "recbond/AribChannel.h" 141 | + 142 | +// linux環境下で標準的なチャンネル指定を仮変換したものをBonDriverチャンネル番号へ変換 143 | +DWORD TransChannelAribToBon(const DWORD dwChannelSrc) 144 | +{ 145 | + DWORD dwChannel = dwChannelSrc & 0xFFFFU; 146 | + DWORD tsid,node,slot,freqno; 147 | + DWORD lp; 148 | + 149 | + switch(dwChannelSrc>>16) 150 | + { 151 | + case BON_CHANNEL: 152 | + return dwChannel; 153 | + case ARIB_GROUND: 154 | + case ARIB_CATV: 155 | + // g_stChannelsから探査 156 | + for (lp = 0; lp < MAX_CH; lp++) 157 | + { 158 | + if (!g_stChannels[0][lp].bUnused && g_stChannels[0][lp].freq.frequencyno == (int)dwChannel) 159 | + return lp; 160 | + } 161 | + break; 162 | + case ARIB_BS: 163 | + // g_stChannelsから探査 164 | + tsid = dwChannel; 165 | + node = (tsid & 0x01f0U) >> 4; 166 | + slot = tsid & 0x0007U; 167 | + freqno = node / 2; 168 | + for (lp = 0; lp> 4; 206 | + slot = tsid & 0x0007U; 207 | + if ((tsid & 0xf000U) == 0x4000U) 208 | + { 209 | + if (node == 15) 210 | + slot--; 211 | + freqno = node / 2; 212 | + } 213 | + else 214 | + freqno = node / 2 + 11; 215 | + // g_stChannelsから探査 216 | + for (lp = 0; lp < MAX_CH; lp++) 217 | + { 218 | + if (!g_stChannels[1][lp].bUnused && g_stChannels[1][lp].freq.frequencyno == (int)freqno && g_stChannels[1][lp].freq.slot == (int)slot) 219 | + return lp; 220 | + } 221 | + // 新規追加 222 | + for (lp = 0; lp < MAX_CH; lp++) 223 | + { 224 | + if (g_stChannels[1][lp].bUnused) 225 | + { 226 | + ::sprintf(g_stChannels[1][lp].strChName, "0x%X", tsid); 227 | + g_stChannels[1][lp].freq.frequencyno = freqno; 228 | + g_stChannels[1][lp].freq.slot = slot; 229 | + g_stChannels[1][lp].bUnused = FALSE; 230 | + return lp; 231 | + } 232 | + } 233 | + break; 234 | + } 235 | + return ARIB_CH_ERROR; 236 | +} 237 | + 238 | static float CalcCNR_S(int signal) 239 | { 240 | static const float fCnrTable[] = { 241 | @@ -509,8 +606,9 @@ 242 | return (LPCTSTR)(g_stChannels[g_Type][dwChannel].strChName); 243 | } 244 | 245 | -const BOOL cBonDriverLinuxPT::SetChannel(const DWORD dwSpace, const DWORD dwChannel) 246 | +const BOOL cBonDriverLinuxPT::SetChannel(const DWORD dwSpace, const DWORD dwChannelSrc) 247 | { 248 | + DWORD dwChannel = TransChannelAribToBon(dwChannelSrc); 249 | BOOL bFlag; 250 | if (!m_bTuner) 251 | goto err; 252 | -------------------------------------------------------------------------------- /mkpath.c: -------------------------------------------------------------------------------- 1 | /* mkpath is originally written by Jonathan Leffler. 2 | * see "http://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux" for detail. 3 | * copyright: (C) JLSS 1990-91,1997-98,2001,2005,2008 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static int 13 | do_mkdir(const char *path, mode_t mode) 14 | { 15 | struct stat st; 16 | int status = 0; 17 | 18 | if (stat(path, &st) != 0) { 19 | /* Directory does not exist */ 20 | if (mkdir(path, mode) != 0) 21 | status = -1; 22 | } 23 | else if (!S_ISDIR(st.st_mode)) { 24 | errno = ENOTDIR; 25 | status = -1; 26 | } 27 | 28 | return(status); 29 | } 30 | 31 | int 32 | mkpath(const char *path, mode_t mode) 33 | { 34 | char *pp; 35 | char *sp; 36 | int status; 37 | char *copypath = strdup(path); 38 | 39 | status = 0; 40 | pp = copypath; 41 | while (status == 0 && (sp = strchr(pp, '/')) != 0) { 42 | if (sp != pp) { 43 | /* Neither root nor double slash in path */ 44 | *sp = '\0'; 45 | status = do_mkdir(copypath, mode); 46 | *sp = '/'; 47 | } 48 | pp = sp + 1; 49 | } 50 | if (status == 0) 51 | status = do_mkdir(path, mode); 52 | free(copypath); 53 | return (status); 54 | } 55 | -------------------------------------------------------------------------------- /mkpath.h: -------------------------------------------------------------------------------- 1 | #ifndef _MKPATH_H_ 2 | #define _MKPATH_H_ 3 | 4 | int mkpath(const char *path, mode_t mode); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /pt1_dev.h: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #ifndef _PT1_DEV_H_ 3 | #define _PT1_DEV_H_ 4 | 5 | 6 | // BonDriverテーブル(pathは各自で変更すること) 7 | // 衛星波 8 | char * bsdev[] = { 9 | (char *)"/usr/local/lib/BonDriver/BonDriver_LinuxPT-S0.so", 10 | (char *)"/usr/local/lib/BonDriver/BonDriver_LinuxPT-S1.so", 11 | (char *)"/usr/local/lib/BonDriver/BonDriver_LinuxPT-S2.so", 12 | (char *)"/usr/local/lib/BonDriver/BonDriver_LinuxPT-S3.so" 13 | }; 14 | // 衛星波Proxy 15 | char * bsdev_proxy[] = { 16 | (char *)"/usr/local/lib/BonDriver/BonDriver_ProxyS0.so", 17 | (char *)"/usr/local/lib/BonDriver/BonDriver_ProxyS1.so", 18 | (char *)"/usr/local/lib/BonDriver/BonDriver_ProxyS2.so", 19 | (char *)"/usr/local/lib/BonDriver/BonDriver_ProxyS3.so" 20 | }; 21 | 22 | // 地上波 23 | char * isdb_t_dev[] = { 24 | (char *)"/usr/local/lib/BonDriver/BonDriver_LinuxPT-T0.so", 25 | (char *)"/usr/local/lib/BonDriver/BonDriver_LinuxPT-T1.so", 26 | (char *)"/usr/local/lib/BonDriver/BonDriver_LinuxPT-T2.so", 27 | (char *)"/usr/local/lib/BonDriver/BonDriver_LinuxPT-T3.so" 28 | }; 29 | // 地上波Proxy 30 | char * isdb_t_dev_proxy[] = { 31 | (char *)"/usr/local/lib/BonDriver/BonDriver_ProxyT0.so", 32 | (char *)"/usr/local/lib/BonDriver/BonDriver_ProxyT1.so", 33 | (char *)"/usr/local/lib/BonDriver/BonDriver_ProxyT2.so", 34 | (char *)"/usr/local/lib/BonDriver/BonDriver_ProxyT3.so" 35 | }; 36 | 37 | #define NUM_BSDEV (sizeof(bsdev)/sizeof(char *)) 38 | #define NUM_BSDEV_PROXY (sizeof(bsdev_proxy)/sizeof(char *)) 39 | #define NUM_ISDB_T_DEV (sizeof(isdb_t_dev)/sizeof(char *)) 40 | #define NUM_ISDB_T_DEV_PROXY (sizeof(isdb_t_dev_proxy)/sizeof(char *)) 41 | 42 | 43 | // 変換テーブル(衛星波専用・ISDB-Tは演算) 44 | // BSの局編成変更がない限りいじらないように 45 | 46 | const ISDB_T_FREQ_CONV_TABLE isdb_t_conv_table[] = { 47 | { 0, CHTYPE_SATELLITE, 0, (char *)"151"}, // BS朝日 48 | { 0, CHTYPE_SATELLITE, 1, (char *)"161"}, // BS-TBS 49 | { 1, CHTYPE_SATELLITE, 0, (char *)"191"}, // WOWOWプライム 50 | { 1, CHTYPE_SATELLITE, 1, (char *)"171"}, // BSジャパン 51 | { 2, CHTYPE_SATELLITE, 0, (char *)"192"}, // WOWOWライブ 52 | { 2, CHTYPE_SATELLITE, 1, (char *)"193"}, // WOWOWシネマ 53 | { 3, CHTYPE_SATELLITE, 0, (char *)"201"}, // スターチャンネル2 54 | { 3, CHTYPE_SATELLITE, 0, (char *)"202"}, // スターチャンネル3 55 | { 3, CHTYPE_SATELLITE, 1, (char *)"236"}, // BSアニマックス 56 | { 3, CHTYPE_SATELLITE, 2, (char *)"256"}, // ディズニーチャンネル 57 | { 4, CHTYPE_SATELLITE, 0, (char *)"211"}, // BS11 58 | { 4, CHTYPE_SATELLITE, 1, (char *)"200"}, // スターチャンネル1 59 | { 4, CHTYPE_SATELLITE, 2, (char *)"222"}, // TwellV 60 | { 5, CHTYPE_SATELLITE, 0, (char *)"238"}, // FOX bs238 61 | { 5, CHTYPE_SATELLITE, 1, (char *)"241"}, // BSスカパー! 62 | { 5, CHTYPE_SATELLITE, 2, (char *)"231"}, // 放送大学BS1 63 | { 5, CHTYPE_SATELLITE, 2, (char *)"232"}, // 放送大学BS2 64 | { 5, CHTYPE_SATELLITE, 2, (char *)"233"}, // 放送大学BS3 65 | { 6, CHTYPE_SATELLITE, 0, (char *)"141"}, // BS日テレ 66 | { 6, CHTYPE_SATELLITE, 1, (char *)"181"}, // BSフジ 67 | { 7, CHTYPE_SATELLITE, 0, (char *)"101"}, // NHK-BS1 68 | { 7, CHTYPE_SATELLITE, 1, (char *)"103"}, // NHK-BSプレミアム 69 | { 8, CHTYPE_SATELLITE, 0, (char *)"291"}, // 旧難視聴1 70 | { 8, CHTYPE_SATELLITE, 1, (char *)"292"}, // 旧難視聴2 71 | { 8, CHTYPE_SATELLITE, 2, (char *)"293"}, // 旧難視聴3 72 | { 9, CHTYPE_SATELLITE, 0, (char *)"234"}, // グリーンチャンネル 73 | { 9, CHTYPE_SATELLITE, 1, (char *)"242"}, // J Sports 1 74 | { 9, CHTYPE_SATELLITE, 2, (char *)"243"}, // J Sports 2 75 | { 10, CHTYPE_SATELLITE, 0, (char *)"252"}, // IMAGICA BS 76 | { 10, CHTYPE_SATELLITE, 1, (char *)"244"}, // J Sports 3 77 | { 10, CHTYPE_SATELLITE, 2, (char *)"245"}, // J Sports 4 78 | { 11, CHTYPE_SATELLITE, 0, (char *)"251"}, // BS釣りビジョン 79 | { 11, CHTYPE_SATELLITE, 1, (char *)"255"}, // BS日本映画専門チャンネル 80 | { 11, CHTYPE_SATELLITE, 2, (char *)"258"}, // D-Life 81 | { 12, CHTYPE_SATELLITE, 0, (char *)"CS2"}, 82 | { 13, CHTYPE_SATELLITE, 0, (char *)"CS4"}, 83 | { 14, CHTYPE_SATELLITE, 0, (char *)"CS6"}, 84 | { 15, CHTYPE_SATELLITE, 0, (char *)"CS8"}, 85 | { 16, CHTYPE_SATELLITE, 0, (char *)"CS10"}, 86 | { 17, CHTYPE_SATELLITE, 0, (char *)"CS12"}, 87 | { 18, CHTYPE_SATELLITE, 0, (char *)"CS14"}, 88 | { 19, CHTYPE_SATELLITE, 0, (char *)"CS16"}, 89 | { 20, CHTYPE_SATELLITE, 0, (char *)"CS18"}, 90 | { 21, CHTYPE_SATELLITE, 0, (char *)"CS20"}, 91 | { 22, CHTYPE_SATELLITE, 0, (char *)"CS22"}, 92 | { 23, CHTYPE_SATELLITE, 0, (char *)"CS24"}, 93 | #if 0 94 | { 0, CHTYPE_GROUND, 0, (char *)"1"}, { 1, CHTYPE_GROUND, 0, (char *)"2"}, 95 | { 2, CHTYPE_GROUND, 0, (char *)"3"}, { 3, CHTYPE_GROUND, 0, (char *)"C13"}, 96 | { 4, CHTYPE_GROUND, 0, (char *)"C14"}, { 5, CHTYPE_GROUND, 0, (char *)"C15"}, 97 | { 6, CHTYPE_GROUND, 0, (char *)"C16"}, { 7, CHTYPE_GROUND, 0, (char *)"C17"}, 98 | { 8, CHTYPE_GROUND, 0, (char *)"C18"}, { 9, CHTYPE_GROUND, 0, (char *)"C19"}, 99 | { 10, CHTYPE_GROUND, 0, (char *)"C20"}, { 11, CHTYPE_GROUND, 0, (char *)"C21"}, 100 | { 12, CHTYPE_GROUND, 0, (char *)"C22"}, { 13, CHTYPE_GROUND, 0, (char *)"4"}, 101 | { 14, CHTYPE_GROUND, 0, (char *)"5"}, { 15, CHTYPE_GROUND, 0, (char *)"6"}, 102 | { 16, CHTYPE_GROUND, 0, (char *)"7"}, { 17, CHTYPE_GROUND, 0, (char *)"8"}, 103 | { 18, CHTYPE_GROUND, 0, (char *)"9"}, { 19, CHTYPE_GROUND, 0, (char *)"10"}, 104 | { 20, CHTYPE_GROUND, 0, (char *)"11"}, { 21, CHTYPE_GROUND, 0, (char *)"12"}, 105 | { 22, CHTYPE_GROUND, 0, (char *)"C23"}, { 23, CHTYPE_GROUND, 0, (char *)"C24"}, 106 | { 24, CHTYPE_GROUND, 0, (char *)"C25"}, { 25, CHTYPE_GROUND, 0, (char *)"C26"}, 107 | { 26, CHTYPE_GROUND, 0, (char *)"C27"}, { 27, CHTYPE_GROUND, 0, (char *)"C28"}, 108 | { 28, CHTYPE_GROUND, 0, (char *)"C29"}, { 29, CHTYPE_GROUND, 0, (char *)"C30"}, 109 | { 30, CHTYPE_GROUND, 0, (char *)"C31"}, { 31, CHTYPE_GROUND, 0, (char *)"C32"}, 110 | { 32, CHTYPE_GROUND, 0, (char *)"C33"}, { 33, CHTYPE_GROUND, 0, (char *)"C34"}, 111 | { 34, CHTYPE_GROUND, 0, (char *)"C35"}, { 35, CHTYPE_GROUND, 0, (char *)"C36"}, 112 | { 36, CHTYPE_GROUND, 0, (char *)"C37"}, { 37, CHTYPE_GROUND, 0, (char *)"C38"}, 113 | { 38, CHTYPE_GROUND, 0, (char *)"C39"}, { 39, CHTYPE_GROUND, 0, (char *)"C40"}, 114 | { 40, CHTYPE_GROUND, 0, (char *)"C41"}, { 41, CHTYPE_GROUND, 0, (char *)"C42"}, 115 | { 42, CHTYPE_GROUND, 0, (char *)"C43"}, { 43, CHTYPE_GROUND, 0, (char *)"C44"}, 116 | { 44, CHTYPE_GROUND, 0, (char *)"C45"}, { 45, CHTYPE_GROUND, 0, (char *)"C46"}, 117 | { 46, CHTYPE_GROUND, 0, (char *)"C47"}, { 47, CHTYPE_GROUND, 0, (char *)"C48"}, 118 | { 48, CHTYPE_GROUND, 0, (char *)"C49"}, { 49, CHTYPE_GROUND, 0, (char *)"C50"}, 119 | { 50, CHTYPE_GROUND, 0, (char *)"C51"}, { 51, CHTYPE_GROUND, 0, (char *)"C52"}, 120 | { 52, CHTYPE_GROUND, 0, (char *)"C53"}, { 53, CHTYPE_GROUND, 0, (char *)"C54"}, 121 | { 54, CHTYPE_GROUND, 0, (char *)"C55"}, { 55, CHTYPE_GROUND, 0, (char *)"C56"}, 122 | { 56, CHTYPE_GROUND, 0, (char *)"C57"}, { 57, CHTYPE_GROUND, 0, (char *)"C58"}, 123 | { 58, CHTYPE_GROUND, 0, (char *)"C59"}, { 59, CHTYPE_GROUND, 0, (char *)"C60"}, 124 | { 60, CHTYPE_GROUND, 0, (char *)"C61"}, { 61, CHTYPE_GROUND, 0, (char *)"C62"}, 125 | { 62, CHTYPE_GROUND, 0, (char *)"C63"}, { 63, CHTYPE_GROUND, 0, (char *)"13"}, 126 | { 64, CHTYPE_GROUND, 0, (char *)"14"}, { 65, CHTYPE_GROUND, 0, (char *)"15"}, 127 | { 66, CHTYPE_GROUND, 0, (char *)"16"}, { 67, CHTYPE_GROUND, 0, (char *)"17"}, 128 | { 68, CHTYPE_GROUND, 0, (char *)"18"}, { 69, CHTYPE_GROUND, 0, (char *)"19"}, 129 | { 70, CHTYPE_GROUND, 0, (char *)"20"}, { 71, CHTYPE_GROUND, 0, (char *)"21"}, 130 | { 72, CHTYPE_GROUND, 0, (char *)"22"}, { 73, CHTYPE_GROUND, 0, (char *)"23"}, 131 | { 74, CHTYPE_GROUND, 0, (char *)"24"}, { 75, CHTYPE_GROUND, 0, (char *)"25"}, 132 | { 76, CHTYPE_GROUND, 0, (char *)"26"}, { 77, CHTYPE_GROUND, 0, (char *)"27"}, 133 | { 78, CHTYPE_GROUND, 0, (char *)"28"}, { 79, CHTYPE_GROUND, 0, (char *)"29"}, 134 | { 80, CHTYPE_GROUND, 0, (char *)"30"}, { 81, CHTYPE_GROUND, 0, (char *)"31"}, 135 | { 82, CHTYPE_GROUND, 0, (char *)"32"}, { 83, CHTYPE_GROUND, 0, (char *)"33"}, 136 | { 84, CHTYPE_GROUND, 0, (char *)"34"}, { 85, CHTYPE_GROUND, 0, (char *)"35"}, 137 | { 86, CHTYPE_GROUND, 0, (char *)"36"}, { 87, CHTYPE_GROUND, 0, (char *)"37"}, 138 | { 88, CHTYPE_GROUND, 0, (char *)"38"}, { 89, CHTYPE_GROUND, 0, (char *)"39"}, 139 | { 90, CHTYPE_GROUND, 0, (char *)"40"}, { 91, CHTYPE_GROUND, 0, (char *)"41"}, 140 | { 92, CHTYPE_GROUND, 0, (char *)"42"}, { 93, CHTYPE_GROUND, 0, (char *)"43"}, 141 | { 94, CHTYPE_GROUND, 0, (char *)"44"}, { 95, CHTYPE_GROUND, 0, (char *)"45"}, 142 | { 96, CHTYPE_GROUND, 0, (char *)"46"}, { 97, CHTYPE_GROUND, 0, (char *)"47"}, 143 | { 98, CHTYPE_GROUND, 0, (char *)"48"}, { 99, CHTYPE_GROUND, 0, (char *)"49"}, 144 | { 100, CHTYPE_GROUND, 0, (char *)"50"}, { 101, CHTYPE_GROUND, 0, (char *)"51"}, 145 | { 102, CHTYPE_GROUND, 0, (char *)"52"}, { 103, CHTYPE_GROUND, 0, (char *)"53"}, 146 | { 104, CHTYPE_GROUND, 0, (char *)"54"}, { 105, CHTYPE_GROUND, 0, (char *)"55"}, 147 | { 106, CHTYPE_GROUND, 0, (char *)"56"}, { 107, CHTYPE_GROUND, 0, (char *)"57"}, 148 | { 108, CHTYPE_GROUND, 0, (char *)"58"}, { 109, CHTYPE_GROUND, 0, (char *)"59"}, 149 | { 110, CHTYPE_GROUND, 0, (char *)"60"}, { 111, CHTYPE_GROUND, 0, (char *)"61"}, 150 | { 112, CHTYPE_GROUND, 0, (char *)"62"}, { 113, CHTYPE_GROUND, 0, (char *)"63"}, 151 | #endif 152 | { 0, 0, 0, NULL} /* terminate */ 153 | }; 154 | #endif 155 | -------------------------------------------------------------------------------- /recpt1.c: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | #include "config.h" 30 | #ifdef HAVE_LIBARIB25 31 | #include "decoder.h" 32 | #endif 33 | #include "../typedef.h" 34 | #include "../IBonDriver2.h" 35 | //#include "recpt1.h" 36 | #include "recpt1core.h" 37 | #include "mkpath.h" 38 | 39 | #include "tssplitter_lite.h" 40 | 41 | /* maximum write length at once */ 42 | #define SIZE_CHANK 1316 43 | 44 | /* ipc message size */ 45 | #define MSGSZ 255 46 | 47 | /* globals */ 48 | extern BON_CHANNEL_SET *isdb_t_conv_set; 49 | 50 | 51 | //read 1st line from socket 52 | void read_line(int socket, char *p){ 53 | int i; 54 | for (i=0; i < 255; i++){ 55 | int ret; 56 | ret = read(socket, p, 1); 57 | if ( ret == -1 ){ 58 | perror("read"); 59 | exit(1); 60 | } else if ( ret == 0 ){ 61 | break; 62 | } 63 | if ( *p == '\n' ){ 64 | p++; 65 | break; 66 | } 67 | p++; 68 | } 69 | *p = '\0'; 70 | } 71 | 72 | 73 | /* will be ipc message receive thread */ 74 | void * 75 | mq_recv(void *t) 76 | { 77 | BON_CHANNEL_SET *table = NULL; 78 | thread_data *tdata = (thread_data *)t; 79 | message_buf rbuf; 80 | char channel[16]; 81 | char service_id[32] = {0}; 82 | int recsec = 0, time_to_add = 0; 83 | 84 | while(1) { 85 | if(msgrcv(tdata->msqid, &rbuf, MSGSZ, 1, 0) < 0) { 86 | return NULL; 87 | } 88 | 89 | sscanf(rbuf.mtext, "ch=%s t=%d e=%d sid=%s", channel, &recsec, &time_to_add, service_id); 90 | 91 | if( (table = searchrecoff(channel)) != NULL ) 92 | strcpy(channel, table->parm_freq); 93 | if(strcmp(channel, tdata->table->parm_freq)) { 94 | if( table == NULL ){ 95 | table = searchrecoff(channel); 96 | if (table == NULL) { 97 | fprintf(stderr, "Invalid Channel: %s\n", channel); 98 | goto CHECK_TIME_TO_ADD; 99 | } 100 | } 101 | 102 | /* wait for remainder */ 103 | while(tdata->queue->num_used > 0) { 104 | usleep(10000); 105 | } 106 | 107 | if (tdata->table->type != table->type) { 108 | /* re-open device */ 109 | if(close_tuner(tdata) != 0) 110 | return NULL; 111 | 112 | tdata->table = table; 113 | tune(channel, tdata, NULL); 114 | } else { 115 | tdata->table = table; 116 | /* SET_CHANNEL only */ 117 | if(tdata->pIBon2->SetChannel(tdata->dwSpace, tdata->table->set_freq) == FALSE) { 118 | fprintf(stderr, "Cannot tune to the specified channel\n"); 119 | goto CHECK_TIME_TO_ADD; 120 | } 121 | calc_cn(tdata, FALSE); 122 | } 123 | } 124 | 125 | CHECK_TIME_TO_ADD: 126 | if(time_to_add) { 127 | tdata->recsec += time_to_add; 128 | fprintf(stderr, "Extended %d sec\n", time_to_add); 129 | } 130 | 131 | if(recsec) { 132 | time_t cur_time; 133 | time(&cur_time); 134 | if(cur_time - tdata->start_time > recsec) { 135 | f_exit = TRUE; 136 | } 137 | else { 138 | tdata->recsec = recsec; 139 | fprintf(stderr, "Total recording time = %d sec\n", recsec); 140 | } 141 | } 142 | 143 | if(f_exit) 144 | return NULL; 145 | } 146 | } 147 | 148 | 149 | QUEUE_T * 150 | create_queue(size_t size) 151 | { 152 | QUEUE_T *p_queue; 153 | int memsize = sizeof(QUEUE_T) + size * sizeof(BUFSZ*); 154 | 155 | p_queue = (QUEUE_T*)calloc(memsize, sizeof(char)); 156 | 157 | if(p_queue != NULL) { 158 | p_queue->size = size; 159 | p_queue->num_avail = size; 160 | p_queue->num_used = 0; 161 | pthread_mutex_init(&p_queue->mutex, NULL); 162 | pthread_cond_init(&p_queue->cond_avail, NULL); 163 | pthread_cond_init(&p_queue->cond_used, NULL); 164 | } 165 | 166 | return p_queue; 167 | } 168 | 169 | void 170 | destroy_queue(QUEUE_T *p_queue) 171 | { 172 | if(!p_queue) 173 | return; 174 | 175 | pthread_mutex_destroy(&p_queue->mutex); 176 | pthread_cond_destroy(&p_queue->cond_avail); 177 | pthread_cond_destroy(&p_queue->cond_used); 178 | free(p_queue); 179 | } 180 | 181 | /* enqueue data. this function will block if queue is full. */ 182 | void 183 | enqueue(QUEUE_T *p_queue, BUFSZ *data) 184 | { 185 | struct timeval now; 186 | struct timespec spec; 187 | int retry_count = 0; 188 | 189 | pthread_mutex_lock(&p_queue->mutex); 190 | /* entered critical section */ 191 | 192 | /* wait while queue is full */ 193 | while(p_queue->num_avail == 0) { 194 | 195 | gettimeofday(&now, NULL); 196 | spec.tv_sec = now.tv_sec + 1; 197 | spec.tv_nsec = now.tv_usec * 1000; 198 | 199 | pthread_cond_timedwait(&p_queue->cond_avail, 200 | &p_queue->mutex, &spec); 201 | retry_count++; 202 | if(retry_count > 60) { 203 | f_exit = TRUE; 204 | } 205 | if(f_exit) { 206 | pthread_mutex_unlock(&p_queue->mutex); 207 | return; 208 | } 209 | } 210 | 211 | p_queue->buffer[p_queue->in] = data; 212 | 213 | /* move position marker for input to next position */ 214 | p_queue->in++; 215 | p_queue->in %= p_queue->size; 216 | 217 | /* update counters */ 218 | p_queue->num_avail--; 219 | p_queue->num_used++; 220 | 221 | /* leaving critical section */ 222 | pthread_mutex_unlock(&p_queue->mutex); 223 | pthread_cond_signal(&p_queue->cond_used); 224 | } 225 | 226 | /* dequeue data. this function will block if queue is empty. */ 227 | BUFSZ * 228 | dequeue(QUEUE_T *p_queue) 229 | { 230 | struct timeval now; 231 | struct timespec spec; 232 | BUFSZ *buffer; 233 | int retry_count = 0; 234 | 235 | pthread_mutex_lock(&p_queue->mutex); 236 | /* entered the critical section*/ 237 | 238 | /* wait while queue is empty */ 239 | while(p_queue->num_used == 0) { 240 | 241 | gettimeofday(&now, NULL); 242 | spec.tv_sec = now.tv_sec + 1; 243 | spec.tv_nsec = now.tv_usec * 1000; 244 | 245 | pthread_cond_timedwait(&p_queue->cond_used, 246 | &p_queue->mutex, &spec); 247 | retry_count++; 248 | if(retry_count > 60) { 249 | f_exit = TRUE; 250 | } 251 | if(f_exit) { 252 | pthread_mutex_unlock(&p_queue->mutex); 253 | return NULL; 254 | } 255 | } 256 | 257 | /* take buffer address */ 258 | buffer = p_queue->buffer[p_queue->out]; 259 | 260 | /* move position marker for output to next position */ 261 | p_queue->out++; 262 | p_queue->out %= p_queue->size; 263 | 264 | /* update counters */ 265 | p_queue->num_avail++; 266 | p_queue->num_used--; 267 | 268 | /* leaving the critical section */ 269 | pthread_mutex_unlock(&p_queue->mutex); 270 | pthread_cond_signal(&p_queue->cond_avail); 271 | 272 | return buffer; 273 | } 274 | 275 | /* this function will be reader thread */ 276 | void * 277 | reader_func(void *p) 278 | { 279 | thread_data *tdata = (thread_data *)p; 280 | QUEUE_T *p_queue = tdata->queue; 281 | Splitter *splitter = tdata->splitter; 282 | int wfd = tdata->wfd; 283 | #ifdef HAVE_LIBARIB25 284 | DECODER *dec = tdata->decoder; 285 | boolean use_b25 = dec ? TRUE : FALSE; 286 | #endif 287 | boolean use_udp = tdata->sock_data ? TRUE : FALSE; 288 | boolean fileless = FALSE; 289 | boolean use_splitter = splitter ? TRUE : FALSE; 290 | int sfd = -1; 291 | pthread_t signal_thread = tdata->signal_thread; 292 | // struct sockaddr_in *addr = NULL; 293 | BUFSZ *qbuf; 294 | static splitbuf_t splitbuf; 295 | ARIB_STD_B25_BUFFER sbuf, dbuf, buf; 296 | int code; 297 | int split_select_finish = TSS_ERROR; 298 | 299 | buf.size = 0; 300 | buf.data = NULL; 301 | splitbuf.buffer_size = 0; 302 | splitbuf.buffer = NULL; 303 | 304 | if(wfd == -1) 305 | fileless = TRUE; 306 | 307 | if(use_udp) { 308 | sfd = tdata->sock_data->sfd; 309 | // addr = &tdata->sock_data->addr; 310 | } 311 | 312 | while(1) { 313 | ssize_t wc = 0; 314 | int file_err = 0; 315 | qbuf = dequeue(p_queue); 316 | /* no entry in the queue */ 317 | if(qbuf == NULL) { 318 | break; 319 | } 320 | 321 | sbuf.data = qbuf->buffer; 322 | sbuf.size = qbuf->size; 323 | 324 | buf = sbuf; /* default */ 325 | 326 | #ifdef HAVE_LIBARIB25 327 | if(use_b25) { 328 | code = b25_decode(dec, &sbuf, &dbuf); 329 | if(code < 0) { 330 | fprintf(stderr, "b25_decode failed (code=%d). fall back to encrypted recording.\n", code); 331 | use_b25 = FALSE; 332 | } 333 | else 334 | buf = dbuf; 335 | } 336 | #endif 337 | 338 | if(use_splitter) { 339 | splitbuf.buffer_filled = 0; 340 | 341 | /* allocate split buffer */ 342 | if(splitbuf.buffer_size < buf.size && buf.size > 0) { 343 | splitbuf.buffer = (u_char *)realloc(splitbuf.buffer, buf.size); 344 | if(splitbuf.buffer == NULL) { 345 | fprintf(stderr, "split buffer allocation failed\n"); 346 | use_splitter = FALSE; 347 | goto fin; 348 | } 349 | } 350 | 351 | while(buf.size) { 352 | /* 分離対象PIDの抽出 */ 353 | if(split_select_finish != TSS_SUCCESS) { 354 | split_select_finish = split_select(splitter, &buf); 355 | if(split_select_finish == TSS_NULL) { 356 | /* mallocエラー発生 */ 357 | fprintf(stderr, "split_select malloc failed\n"); 358 | use_splitter = FALSE; 359 | goto fin; 360 | } 361 | else if(split_select_finish != TSS_SUCCESS) { 362 | /* 分離対象PIDが完全に抽出できるまで出力しない 363 | * 1秒程度余裕を見るといいかも 364 | */ 365 | time_t cur_time; 366 | time(&cur_time); 367 | if(cur_time - tdata->start_time > 4) { 368 | use_splitter = FALSE; 369 | goto fin; 370 | } 371 | break; 372 | } 373 | } 374 | 375 | /* 分離対象以外をふるい落とす */ 376 | code = split_ts(splitter, &buf, &splitbuf); 377 | if(code == TSS_NULL) { 378 | fprintf(stderr, "PMT reading..\n"); 379 | } 380 | else if(code != TSS_SUCCESS) { 381 | fprintf(stderr, "split_ts failed\n"); 382 | break; 383 | } 384 | 385 | break; 386 | } /* while */ 387 | 388 | buf.size = splitbuf.buffer_filled; 389 | buf.data = splitbuf.buffer; 390 | fin: 391 | ; 392 | } /* if */ 393 | 394 | 395 | if(!fileless) { 396 | /* write data to output file */ 397 | int size_remain = buf.size; 398 | int offset = 0; 399 | 400 | while(size_remain > 0) { 401 | int ws = size_remain < SIZE_CHANK ? size_remain : SIZE_CHANK; 402 | 403 | wc = write(wfd, buf.data + offset, ws); 404 | if(wc < 0) { 405 | perror("write"); 406 | file_err = 1; 407 | pthread_kill(signal_thread, 408 | errno == EPIPE ? SIGPIPE : SIGUSR2); 409 | break; 410 | } 411 | size_remain -= wc; 412 | offset += wc; 413 | } 414 | } 415 | 416 | if(use_udp && sfd != -1) { 417 | /* write data to socket */ 418 | int size_remain = buf.size; 419 | int offset = 0; 420 | while(size_remain > 0) { 421 | int ws = size_remain < SIZE_CHANK ? size_remain : SIZE_CHANK; 422 | wc = write(sfd, buf.data + offset, ws); 423 | if(wc < 0) { 424 | if(errno == EPIPE) 425 | pthread_kill(signal_thread, SIGPIPE); 426 | break; 427 | } 428 | size_remain -= wc; 429 | offset += wc; 430 | } 431 | } 432 | 433 | free(qbuf); 434 | qbuf = NULL; 435 | 436 | /* normal exit */ 437 | if((f_exit && !p_queue->num_used) || file_err) { 438 | 439 | buf = sbuf; /* default */ 440 | 441 | #ifdef HAVE_LIBARIB25 442 | if(use_b25) { 443 | code = b25_finish(dec, &sbuf, &dbuf); 444 | if(code < 0) 445 | fprintf(stderr, "b25_finish failed\n"); 446 | else 447 | buf = dbuf; 448 | } 449 | #endif 450 | 451 | if(use_splitter) { 452 | /* 分離対象以外をふるい落とす */ 453 | code = split_ts(splitter, &buf, &splitbuf); 454 | if(code == TSS_NULL) { 455 | split_select_finish = TSS_ERROR; 456 | fprintf(stderr, "PMT reading..\n"); 457 | } 458 | else if(code != TSS_SUCCESS) { 459 | fprintf(stderr, "split_ts failed\n"); 460 | break; 461 | } 462 | 463 | buf.data = splitbuf.buffer; 464 | buf.size = splitbuf.buffer_size; 465 | } 466 | 467 | if(!fileless && !file_err) { 468 | /* write data to output file */ 469 | int size_remain = buf.size; 470 | int offset = 0; 471 | 472 | while(size_remain > 0) { 473 | int ws = size_remain < SIZE_CHANK ? size_remain : SIZE_CHANK; 474 | 475 | wc = write(wfd, buf.data + offset, ws); 476 | if(wc < 0) { 477 | perror("write"); 478 | file_err = 1; 479 | pthread_kill(signal_thread, 480 | errno == EPIPE ? SIGPIPE : SIGUSR2); 481 | break; 482 | } 483 | size_remain -= wc; 484 | offset += wc; 485 | } 486 | } 487 | 488 | if(use_udp && sfd != -1) { 489 | wc = write(sfd, buf.data, buf.size); 490 | if(wc < 0) { 491 | if(errno == EPIPE) 492 | pthread_kill(signal_thread, SIGPIPE); 493 | } 494 | } 495 | 496 | if(use_splitter) { 497 | free(splitbuf.buffer); 498 | splitbuf.buffer = NULL; 499 | splitbuf.buffer_size = 0; 500 | } 501 | 502 | break; 503 | } 504 | } 505 | 506 | time_t cur_time; 507 | time(&cur_time); 508 | fprintf(stderr, "Recorded %dsec\n", 509 | (int)(cur_time - tdata->start_time)); // recsec 510 | 511 | return NULL; 512 | } 513 | 514 | void 515 | show_usage(char *cmd) 516 | { 517 | #ifdef HAVE_LIBARIB25 518 | // fprintf(stderr, "Usage: \n%s [--b25 [--round N] [--strip] [--EMM]] [--udp [--addr hostname --port portnumber]] [--http portnumber] [--driver drivername] [--lnb voltage] [--sid SID1,SID2] channel rectime destfile\n", cmd); 519 | fprintf(stderr, "Usage: \n%s [--b25 [--round N] [--strip] [--EMM]] [--udp [--addr hostname --port portnumber]] [--http portnumber] [--driver drivername] [--sid SID1,SID2] channel rectime destfile\n", cmd); 520 | #else 521 | // fprintf(stderr, "Usage: \n%s [--udp [--addr hostname --port portnumber]] [--driver drivername] [--lnb voltage] [--sid SID1,SID2] channel rectime destfile\n", cmd); 522 | fprintf(stderr, "Usage: \n%s [--udp [--addr hostname --port portnumber]] [--driver drivername] [--sid SID1,SID2] channel rectime destfile\n", cmd); 523 | #endif 524 | fprintf(stderr, "\n"); 525 | fprintf(stderr, "Remarks:\n"); 526 | fprintf(stderr, "if rectime is '-', records indefinitely.\n"); 527 | fprintf(stderr, "if destfile is '-', stdout is used for output.\n"); 528 | } 529 | 530 | void 531 | show_options(void) 532 | { 533 | fprintf(stderr, "Options:\n"); 534 | #ifdef HAVE_LIBARIB25 535 | fprintf(stderr, "--b25: Decrypt using BCAS card\n"); 536 | fprintf(stderr, " --round N: Specify round number\n"); 537 | fprintf(stderr, " --strip: Strip null stream\n"); 538 | fprintf(stderr, " --EMM: Instruct EMM operation\n"); 539 | #endif 540 | fprintf(stderr, "--udp: Turn on udp broadcasting\n"); 541 | fprintf(stderr, " --addr hostname: Hostname or address to connect\n"); 542 | fprintf(stderr, " --port portnumber: Port number to connect\n"); 543 | fprintf(stderr, "--http portnumber: Turn on http broadcasting (run as a daemon)\n"); 544 | fprintf(stderr, "--driver drivername: Specify drivername to use\n"); 545 | #if 0 // LNB 546 | fprintf(stderr, "--lnb voltage: Specify LNB voltage (0, 11, 15)\n"); 547 | #endif 548 | fprintf(stderr, "--sid SID1,SID2,...: Specify SID number in CSV format (101,102,...)\n"); 549 | fprintf(stderr, "--help: Show this help\n"); 550 | fprintf(stderr, "--version: Show version\n"); 551 | fprintf(stderr, "--list: Show channel list\n"); 552 | } 553 | 554 | void 555 | cleanup(thread_data *tdata) 556 | { 557 | close_tuner(tdata); 558 | 559 | f_exit = TRUE; 560 | 561 | pthread_cond_signal(&tdata->queue->cond_avail); 562 | pthread_cond_signal(&tdata->queue->cond_used); 563 | } 564 | 565 | /* will be signal handler thread */ 566 | void * 567 | process_signals(void *t) 568 | { 569 | sigset_t waitset; 570 | int sig; 571 | thread_data *tdata = (thread_data *)t; 572 | 573 | sigemptyset(&waitset); 574 | sigaddset(&waitset, SIGPIPE); 575 | sigaddset(&waitset, SIGINT); 576 | sigaddset(&waitset, SIGTERM); 577 | sigaddset(&waitset, SIGUSR1); 578 | sigaddset(&waitset, SIGUSR2); 579 | 580 | sigwait(&waitset, &sig); 581 | 582 | switch(sig) { 583 | case SIGPIPE: 584 | fprintf(stderr, "\nSIGPIPE received. cleaning up...\n"); 585 | cleanup(tdata); 586 | break; 587 | case SIGINT: 588 | fprintf(stderr, "\nSIGINT received. cleaning up...\n"); 589 | cleanup(tdata); 590 | break; 591 | case SIGTERM: 592 | fprintf(stderr, "\nSIGTERM received. cleaning up...\n"); 593 | cleanup(tdata); 594 | break; 595 | case SIGUSR1: /* normal exit*/ 596 | cleanup(tdata); 597 | break; 598 | case SIGUSR2: /* error */ 599 | fprintf(stderr, "Detected an error. cleaning up...\n"); 600 | cleanup(tdata); 601 | break; 602 | } 603 | 604 | return NULL; /* dummy */ 605 | } 606 | 607 | void 608 | init_signal_handlers(pthread_t *signal_thread, thread_data *tdata) 609 | { 610 | sigset_t blockset; 611 | 612 | sigemptyset(&blockset); 613 | sigaddset(&blockset, SIGPIPE); 614 | sigaddset(&blockset, SIGINT); 615 | sigaddset(&blockset, SIGTERM); 616 | sigaddset(&blockset, SIGUSR1); 617 | sigaddset(&blockset, SIGUSR2); 618 | 619 | if(pthread_sigmask(SIG_BLOCK, &blockset, NULL)) 620 | fprintf(stderr, "pthread_sigmask() failed.\n"); 621 | 622 | pthread_create(signal_thread, NULL, process_signals, tdata); 623 | } 624 | 625 | int 626 | main(int argc, char **argv) 627 | { 628 | pthread_t signal_thread; 629 | pthread_t reader_thread; 630 | pthread_t ipc_thread; 631 | QUEUE_T *p_queue = create_queue(MAX_QUEUE); 632 | BUFSZ *bufptr; 633 | #ifdef HAVE_LIBARIB25 634 | DECODER *decoder = NULL; 635 | #endif 636 | Splitter *splitter = NULL; 637 | static thread_data tdata; 638 | #ifdef HAVE_LIBARIB25 639 | decoder_options dopt = { 640 | 4, /* round */ 641 | 0, /* strip */ 642 | 0 /* emm */ 643 | }; 644 | tdata.dopt = &dopt; 645 | #endif 646 | tdata.hModule = NULL; 647 | tdata.dwSpace = 0; 648 | tdata.table = NULL; 649 | tdata.lnb = -1; 650 | 651 | int result; 652 | int option_index; 653 | struct option long_options[] = { 654 | #ifdef HAVE_LIBARIB25 655 | { "b25", 0, NULL, 'b'}, 656 | { "B25", 0, NULL, 'b'}, 657 | { "round", 1, NULL, 'r'}, 658 | { "strip", 0, NULL, 's'}, 659 | { "emm", 0, NULL, 'm'}, 660 | { "EMM", 0, NULL, 'm'}, 661 | #endif 662 | #if 0 // LNB 663 | { "LNB", 1, NULL, 'n'}, 664 | { "lnb", 1, NULL, 'n'}, 665 | #endif 666 | { "udp", 0, NULL, 'u'}, 667 | { "addr", 1, NULL, 'a'}, 668 | { "port", 1, NULL, 'p'}, 669 | { "http", 1, NULL, 'H'}, 670 | { "space", 1, NULL, 'S'}, 671 | { "driver", 1, NULL, 'd'}, 672 | { "help", 0, NULL, 'h'}, 673 | { "version", 0, NULL, 'v'}, 674 | { "list", 0, NULL, 'l'}, 675 | { "sid", 1, NULL, 'i'}, 676 | {0, 0, NULL, 0} /* terminate */ 677 | }; 678 | 679 | #ifdef HAVE_LIBARIB25 680 | boolean use_b25 = FALSE; 681 | #endif 682 | boolean use_udp = FALSE; 683 | boolean use_http = FALSE; 684 | boolean fileless = FALSE; 685 | boolean use_stdout = FALSE; 686 | boolean use_splitter = FALSE; 687 | char *host_to = NULL; 688 | int port_to = 1234; 689 | int port_http = 12345; 690 | SOCK_data *sockdata = NULL; 691 | char *driver = NULL; 692 | #if 0 // LNB 693 | int val; 694 | char *voltage[] = {"0V", "11V", "15V"}; 695 | #endif 696 | char *sid_list = NULL; 697 | int connected_socket = 0, listening_socket = 0; 698 | unsigned int len; 699 | char *channel = NULL; 700 | 701 | while((result = getopt_long(argc, argv, "br:smua:H:p:S:d:hvli:", 702 | long_options, &option_index)) != -1) { 703 | switch(result) { 704 | #ifdef HAVE_LIBARIB25 705 | case 'b': 706 | use_b25 = TRUE; 707 | fprintf(stderr, "using B25...\n"); 708 | break; 709 | case 's': 710 | dopt.strip = TRUE; 711 | fprintf(stderr, "enable B25 strip\n"); 712 | break; 713 | case 'm': 714 | dopt.emm = TRUE; 715 | fprintf(stderr, "enable B25 emm processing\n"); 716 | break; 717 | case 'r': 718 | dopt.round = atoi(optarg); 719 | fprintf(stderr, "set round %d\n", dopt.round); 720 | break; 721 | #endif 722 | case 'u': 723 | use_udp = TRUE; 724 | host_to = (char *)"localhost"; 725 | fprintf(stderr, "enable UDP broadcasting\n"); 726 | break; 727 | case 'H': 728 | use_http = TRUE; 729 | port_http = atoi(optarg); 730 | fprintf(stderr, "creating a http daemon\n"); 731 | break; 732 | case 'h': 733 | fprintf(stderr, "\n"); 734 | show_usage(argv[0]); 735 | fprintf(stderr, "\n"); 736 | show_options(); 737 | fprintf(stderr, "\n"); 738 | show_channels(); 739 | fprintf(stderr, "\n"); 740 | exit(0); 741 | break; 742 | case 'v': 743 | fprintf(stderr, "%s %s\n", argv[0], version); 744 | fprintf(stderr, "recorder command for PT1/2 digital tuner.\n"); 745 | exit(0); 746 | break; 747 | case 'l': 748 | show_channels(); 749 | exit(0); 750 | break; 751 | /* following options require argument */ 752 | #if 0 753 | case 'n': 754 | val = atoi(optarg); 755 | switch(val) { 756 | case 11: 757 | tdata.lnb = 1; 758 | break; 759 | case 15: 760 | tdata.lnb = 2; 761 | break; 762 | default: 763 | tdata.lnb = 0; 764 | break; 765 | } 766 | fprintf(stderr, "LNB = %s\n", voltage[tdata.lnb]); 767 | break; 768 | #endif 769 | case 'a': 770 | use_udp = TRUE; 771 | host_to = optarg; 772 | fprintf(stderr, "UDP destination address: %s\n", host_to); 773 | break; 774 | case 'p': 775 | port_to = atoi(optarg); 776 | fprintf(stderr, "UDP port: %d\n", port_to); 777 | break; 778 | case 'S': 779 | tdata.dwSpace = atoi(optarg); 780 | fprintf(stderr, "using Space: %i\n", tdata.dwSpace); 781 | break; 782 | case 'd': 783 | driver = optarg; 784 | fprintf(stderr, "using driver: %s\n", driver); 785 | break; 786 | case 'i': 787 | use_splitter = TRUE; 788 | sid_list = optarg; 789 | break; 790 | } 791 | } 792 | 793 | if(use_http){ // http-server add- 794 | fprintf(stderr, "run as a daemon..\n"); 795 | if(daemon(1,1)){ 796 | perror("failed to start"); 797 | return 1; 798 | } 799 | fprintf(stderr, "pid = %d\n", getpid()); 800 | 801 | struct sockaddr_in sin; 802 | int ret; 803 | int sock_optval = 1; 804 | 805 | listening_socket = socket(AF_INET, SOCK_STREAM, 0); 806 | if ( listening_socket == -1 ){ 807 | perror("socket"); 808 | return 1; 809 | } 810 | 811 | if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, 812 | &sock_optval, sizeof(sock_optval)) == -1 ){ 813 | perror("setsockopt"); 814 | return 1; 815 | } 816 | 817 | sin.sin_family = AF_INET; 818 | sin.sin_port = htons(port_http); 819 | sin.sin_addr.s_addr = htonl(INADDR_ANY); 820 | 821 | if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){ 822 | perror("bind"); 823 | return 1; 824 | } 825 | 826 | ret = listen(listening_socket, SOMAXCONN); 827 | if ( ret == -1 ){ 828 | perror("listen"); 829 | return 1; 830 | } 831 | fprintf(stderr,"listening at port %d\n", port_http); 832 | //set rectime to the infinite 833 | if(parse_time("-",&tdata.recsec) != 0){ 834 | return 1; 835 | } 836 | if(tdata.recsec == -1) 837 | tdata.indefinite = TRUE; 838 | }else{ // -http-server add 839 | if(argc - optind < 3) { 840 | if(argc - optind == 2 && use_udp) { 841 | fprintf(stderr, "Fileless UDP broadcasting\n"); 842 | fileless = TRUE; 843 | tdata.wfd = -1; 844 | } 845 | else { 846 | fprintf(stderr, "Arguments are necessary!\n"); 847 | fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]); 848 | return 1; 849 | } 850 | } 851 | 852 | fprintf(stderr, "pid = %d\n", getpid()); 853 | 854 | /* set recsec */ 855 | if(parse_time(argv[optind + 1], &tdata.recsec) != 0) // no other thread --yaz 856 | return 1; 857 | 858 | if(tdata.recsec == -1) 859 | tdata.indefinite = TRUE; 860 | 861 | /* open output file */ 862 | char *destfile = argv[optind + 2]; 863 | if(destfile && !strcmp("-", destfile)) { 864 | use_stdout = TRUE; 865 | tdata.wfd = 1; /* stdout */ 866 | } 867 | else { 868 | if(!fileless) { 869 | int status; 870 | char *path = strdup(argv[optind + 2]); 871 | char *dir = dirname(path); 872 | status = mkpath(dir, 0777); 873 | if(status == -1) 874 | perror("mkpath"); 875 | free(path); 876 | 877 | tdata.wfd = open(argv[optind + 2], (O_RDWR | O_CREAT | O_TRUNC), 0666); 878 | if(tdata.wfd < 0) { 879 | fprintf(stderr, "Cannot open output file: %s\n", argv[optind + 2]); 880 | return 1; 881 | } 882 | } 883 | } 884 | 885 | /* tune */ 886 | if(tune(argv[optind], &tdata, driver) != 0) 887 | return 1; 888 | time(&tdata.start_time); 889 | } // http-server add 890 | 891 | #ifdef HAVE_LIBARIB25 892 | /* initialize decoder */ 893 | if(use_b25) { 894 | decoder = b25_startup(&dopt); 895 | if(!decoder) { 896 | fprintf(stderr, "Cannot start b25 decoder\n"); 897 | fprintf(stderr, "Fall back to encrypted recording\n"); 898 | use_b25 = FALSE; 899 | } 900 | } 901 | #endif 902 | 903 | while(1){ // http-server add- 904 | if(use_http){ 905 | struct hostent *peer_host; 906 | struct sockaddr_in peer_sin; 907 | 908 | len = sizeof(peer_sin); 909 | 910 | connected_socket = accept(listening_socket, (struct sockaddr *)&peer_sin, &len); 911 | if ( connected_socket == -1 ){ 912 | perror("accept"); 913 | return 1; 914 | } 915 | 916 | peer_host = gethostbyaddr((char *)&peer_sin.sin_addr.s_addr, 917 | sizeof(peer_sin.sin_addr), AF_INET); 918 | if ( peer_host == NULL ){ 919 | fprintf(stderr, "gethostbyname failed\n"); 920 | return 1; 921 | } 922 | 923 | fprintf(stderr,"connect from: %s [%s] port %d\n", peer_host->h_name, inet_ntoa(peer_sin.sin_addr), ntohs(peer_sin.sin_port)); 924 | 925 | char buf[256]; 926 | read_line(connected_socket, buf); 927 | fprintf(stderr,"request command is %s\n",buf); 928 | char s0[256],s1[256],s2[256]; 929 | sscanf(buf,"%s%s%s",s0,s1,s2); 930 | char delim[] = "/"; 931 | channel = strtok(s1,delim); 932 | char *sidflg = strtok(NULL,delim); 933 | if(sidflg) 934 | sid_list = sidflg; 935 | fprintf(stderr,"channel is %s\n",channel); 936 | 937 | if(!strcmp(sid_list,"all")){ 938 | use_splitter = FALSE; 939 | splitter = NULL; 940 | }else{ 941 | use_splitter = TRUE; 942 | } 943 | } // -http-server add 944 | 945 | /* initialize splitter */ 946 | if(use_splitter) { 947 | splitter = split_startup(sid_list); 948 | if(splitter->sid_list == NULL) { 949 | fprintf(stderr, "Cannot start TS splitter\n"); 950 | return 1; 951 | } 952 | } 953 | 954 | if(use_http){ // http-server add- 955 | char header[] = "HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nCache-Control: no-cache\r\n\r\n"; 956 | int len = strlen(header); 957 | if(write(connected_socket, header, len) < len){ 958 | close(connected_socket); 959 | if(use_splitter) 960 | split_shutdown(splitter); 961 | continue; 962 | } 963 | 964 | //set write target to http 965 | tdata.wfd = connected_socket; 966 | 967 | //tune 968 | if(tune(channel, &tdata, driver) != 0){ 969 | fprintf(stderr, "Tuner cannot start recording\n"); 970 | continue; 971 | } 972 | }else{ // -http-server add 973 | /* initialize udp connection */ 974 | if(use_udp) { 975 | sockdata = (SOCK_data *)calloc(1, sizeof(SOCK_data)); 976 | struct in_addr ia; 977 | ia.s_addr = inet_addr(host_to); 978 | if(ia.s_addr == INADDR_NONE) { 979 | struct hostent *hoste = gethostbyname(host_to); 980 | if(!hoste) { 981 | perror("gethostbyname"); 982 | return 1; 983 | } 984 | ia.s_addr = *(in_addr_t*) (hoste->h_addr_list[0]); 985 | } 986 | if((sockdata->sfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 987 | perror("socket"); 988 | return 1; 989 | } 990 | 991 | sockdata->addr.sin_family = AF_INET; 992 | sockdata->addr.sin_port = htons (port_to); 993 | sockdata->addr.sin_addr.s_addr = ia.s_addr; 994 | 995 | if(connect(sockdata->sfd, (struct sockaddr *)&sockdata->addr, 996 | sizeof(sockdata->addr)) < 0) { 997 | perror("connect"); 998 | return 1; 999 | } 1000 | } 1001 | } // http-server add 1002 | /* prepare thread data */ 1003 | tdata.queue = p_queue; 1004 | #ifdef HAVE_LIBARIB25 1005 | tdata.decoder = decoder; 1006 | #endif 1007 | tdata.splitter = splitter; 1008 | tdata.sock_data = sockdata; 1009 | tdata.tune_persistent = FALSE; 1010 | 1011 | /* spawn signal handler thread */ 1012 | init_signal_handlers(&signal_thread, &tdata); 1013 | tdata.signal_thread = signal_thread; 1014 | 1015 | /* spawn reader thread */ 1016 | pthread_create(&reader_thread, NULL, reader_func, &tdata); 1017 | 1018 | /* spawn ipc thread */ 1019 | key_t key; 1020 | key = (key_t)getpid(); 1021 | 1022 | if ((tdata.msqid = msgget(key, IPC_CREAT | 0666)) < 0) { 1023 | perror("msgget"); 1024 | } 1025 | pthread_create(&ipc_thread, NULL, mq_recv, &tdata); 1026 | 1027 | fprintf(stderr, "\nRecording...\n"); 1028 | 1029 | /* read from tuner */ 1030 | while(1) { 1031 | if(f_exit) 1032 | break; 1033 | 1034 | // TSストリーム取得 1035 | char *getbuf; 1036 | DWORD getsize; 1037 | DWORD dwRemain; 1038 | if (tdata.pIBon->GetTsStream((BYTE **)&getbuf, &getsize, &dwRemain)){ 1039 | if (getsize > 0){ 1040 | bufptr = (BUFSZ *)malloc(getsize + sizeof(int)); 1041 | if(!bufptr) { 1042 | f_exit = TRUE; 1043 | break; 1044 | } 1045 | memcpy(bufptr->buffer, getbuf, getsize); 1046 | bufptr->size = getsize; 1047 | enqueue(p_queue, bufptr); 1048 | } 1049 | /* stop recording */ 1050 | if(!tdata.indefinite && time(NULL) - tdata.start_time >= tdata.recsec) { 1051 | /* read remaining data */ 1052 | #if 1 1053 | // DWORD cnt_remain = tdata.pIBon->GetReadyCount(); 1054 | DWORD cnt_remain = 40; // 1sec分 1055 | timespec ts; 1056 | ts.tv_sec = 0; 1057 | ts.tv_nsec = 50 * 1000 * 1000; // 10ms -> 50ms(25ms/readなのでそれ以上にすること) 1058 | while(cnt_remain){ 1059 | cnt_remain--; 1060 | dwRemain = 1; 1061 | if (tdata.pIBon->GetTsStream((BYTE **)&getbuf, &getsize, &dwRemain)){ 1062 | if(getsize > 0){ 1063 | bufptr = (BUFSZ *)malloc(getsize + sizeof(int)); 1064 | if(!bufptr) 1065 | break; 1066 | memcpy(bufptr->buffer, getbuf, getsize); 1067 | bufptr->size = getsize; 1068 | enqueue(p_queue, bufptr); 1069 | } 1070 | }else 1071 | if(dwRemain == 1) 1072 | break; 1073 | // 取得待ちTSデータが無ければ適当な時間待つ 1074 | if (dwRemain == 0) 1075 | nanosleep(&ts, NULL); 1076 | } 1077 | #else 1078 | // CloseTuner()した段階でGetTsStream()がFALSEを返すのでこれはダメ 1079 | tdata.pIBon->CloseTuner(); 1080 | tdata.tfd = FALSE; 1081 | DWORD cnt_remain = 0; 1082 | do{ 1083 | if (tdata.pIBon->GetTsStream((BYTE **)&getbuf, &getsize, &dwRemain) && getsize > 0){ 1084 | bufptr = (BUFSZ *)malloc(getsize + sizeof(int)); 1085 | if(!bufptr) 1086 | break; 1087 | memcpy(bufptr->buffer, getbuf, getsize); 1088 | bufptr->size = getsize; 1089 | enqueue(p_queue, bufptr); 1090 | fprintf(stderr, "getsize: %i(%i)\n", getsize, dwRemain); 1091 | } 1092 | }while(dwRemain && ++cnt_remain < 100); 1093 | #endif 1094 | // f_exit = TRUE; 1095 | enqueue(p_queue, NULL); 1096 | break; 1097 | } 1098 | } 1099 | // 取得待ちTSデータが無ければ適当な時間待つ 1100 | if (dwRemain == 0){ 1101 | timespec ts; 1102 | ts.tv_sec = 0; 1103 | ts.tv_nsec = 50 * 1000 * 1000; // 10ms -> 50ms(25ms/readなのでそれ以上にすること) 1104 | nanosleep(&ts, NULL); 1105 | } 1106 | } 1107 | 1108 | /* close tuner */ 1109 | if(close_tuner(&tdata) != 0) 1110 | return 1; 1111 | 1112 | /* delete message queue*/ 1113 | msgctl(tdata.msqid, IPC_RMID, NULL); 1114 | 1115 | pthread_kill(signal_thread, SIGUSR1); 1116 | 1117 | /* wait for threads */ 1118 | pthread_join(reader_thread, NULL); 1119 | pthread_join(signal_thread, NULL); 1120 | pthread_join(ipc_thread, NULL); 1121 | 1122 | /* release queue */ 1123 | destroy_queue(p_queue); 1124 | if(use_http){ // http-server add- 1125 | //reset queue 1126 | p_queue = create_queue(MAX_QUEUE); 1127 | 1128 | /* close http socket */ 1129 | close(tdata.wfd); 1130 | 1131 | fprintf(stderr,"connection closed. still listening at port %d\n",port_http); 1132 | f_exit = FALSE; 1133 | }else{ // -http-server add 1134 | /* close output file */ 1135 | if(!use_stdout){ 1136 | fsync(tdata.wfd); 1137 | close(tdata.wfd); 1138 | } 1139 | 1140 | /* free socket data */ 1141 | if(use_udp) { 1142 | close(sockdata->sfd); 1143 | free(sockdata); 1144 | } 1145 | 1146 | #ifdef HAVE_LIBARIB25 1147 | /* release decoder */ 1148 | if(!use_http && use_b25) 1149 | b25_shutdown(decoder); 1150 | #endif 1151 | } // http-server add 1152 | if(use_splitter) { 1153 | split_shutdown(splitter); 1154 | } 1155 | 1156 | if(!use_http) // http-server add 1157 | return 0; 1158 | } // http-server add 1159 | } 1160 | -------------------------------------------------------------------------------- /recpt1.h: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #ifndef _RECPT1_H_ 3 | #define _RECPT1_H_ 4 | 5 | #define CHTYPE_SATELLITE 0 /* satellite digital */ 6 | #define CHTYPE_GROUND 1 /* terrestrial digital */ 7 | #define CHTYPE_BonNUMBER 2 // BonDriver number 8 | #define MAX_QUEUE 8192 9 | #define MAX_READ_SIZE (188 * 256) // BonDriver_DVB.hのTS_BUFSIZEと同値 10 | #define WRITE_SIZE (1024 * 1024 * 2) 11 | #define TRUE 1 12 | #define FALSE 0 13 | 14 | typedef struct _BUFSZ { 15 | int size; 16 | u_char buffer[MAX_READ_SIZE]; // 凡ドラ側でB25デコード時はこのサイズより大きくなるので注意 17 | } BUFSZ; 18 | 19 | typedef struct _QUEUE_T { 20 | unsigned int in; // 次に入れるインデックス 21 | unsigned int out; // 次に出すインデックス 22 | unsigned int size; // キューのサイズ 23 | unsigned int num_avail; // 満タンになると 0 になる 24 | unsigned int num_used; // 空っぽになると 0 になる 25 | pthread_mutex_t mutex; 26 | pthread_cond_t cond_avail; // データが満タンのときに待つための cond 27 | pthread_cond_t cond_used; // データが空のときに待つための cond 28 | BUFSZ *buffer[1]; // バッファポインタ 29 | } QUEUE_T; 30 | 31 | typedef struct _ISDB_T_FREQ_CONV_TABLE { 32 | int set_freq; // 実際にioctl()を行う値 33 | int type; // チャンネルタイプ 34 | int add_freq; // 追加する周波数(BS/CSの場合はスロット番号) 35 | char *parm_freq; // パラメータで受ける値 36 | } ISDB_T_FREQ_CONV_TABLE; 37 | 38 | typedef struct _BON_CHANNEL_SET { 39 | int bon_num; // BonDriver channel number 40 | int set_freq; // BonDriver channel number 仮値 41 | int type; // チャンネルタイプ 42 | char parm_freq[16]; // パラメータで受ける値 43 | } BON_CHANNEL_SET; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /recpt1core.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "../typedef.h" 7 | #include "../IBonDriver2.h" 8 | #include "AribChannel.h" 9 | #include "recpt1core.h" 10 | #include "version.h" 11 | #include "pt1_dev.h" 12 | 13 | /* globals */ 14 | boolean f_exit = FALSE; 15 | BON_CHANNEL_SET *isdb_t_conv_set = NULL; 16 | 17 | 18 | int getBonNumber(DWORD node, DWORD slot) 19 | { 20 | for(int lp = 0; isdb_t_conv_table[lp].parm_freq != NULL; lp++) { 21 | if(isdb_t_conv_table[lp].set_freq == (int)node && isdb_t_conv_table[lp].add_freq == (int)slot){ 22 | return lp; 23 | } 24 | } 25 | return ARIB_CH_ERROR; 26 | } 27 | 28 | /* lookup frequency conversion table*/ 29 | BON_CHANNEL_SET * 30 | searchrecoff(char *channel) 31 | { 32 | BON_CHANNEL_SET *isdb_t_conv_tmp; 33 | DWORD node; 34 | DWORD slot; 35 | DWORD dwBonChannel = channelAribToBon(channel); 36 | 37 | if( dwBonChannel == ARIB_CH_ERROR ) 38 | return NULL; 39 | isdb_t_conv_tmp = (BON_CHANNEL_SET *)malloc(sizeof(BON_CHANNEL_SET)); 40 | memset(isdb_t_conv_tmp->parm_freq, 0, 16); 41 | isdb_t_conv_tmp->set_freq = (int)dwBonChannel; 42 | switch(dwBonChannel>>16){ 43 | case BON_CHANNEL: 44 | isdb_t_conv_tmp->bon_num = (int)dwBonChannel; 45 | isdb_t_conv_tmp->type = CHTYPE_BonNUMBER; 46 | sprintf(isdb_t_conv_tmp->parm_freq, "B%d", node); 47 | break; 48 | case ARIB_GROUND: 49 | case ARIB_CATV: 50 | isdb_t_conv_tmp->bon_num = (int)(dwBonChannel & 0xFFFFU); 51 | isdb_t_conv_tmp->type = CHTYPE_GROUND; 52 | sprintf(isdb_t_conv_tmp->parm_freq, "%s", channel); 53 | break; 54 | case ARIB_BS: 55 | node = (dwBonChannel & 0x01f0U) >> 4; 56 | slot = dwBonChannel & 0x0007U; 57 | isdb_t_conv_tmp->type = CHTYPE_SATELLITE; 58 | sprintf(isdb_t_conv_tmp->parm_freq, "BS%d_%d", node, slot); 59 | isdb_t_conv_tmp->bon_num = getBonNumber(node/2, slot); 60 | break; 61 | case ARIB_BS_SID: 62 | for(int lp = 0; isdb_t_conv_table[lp].parm_freq != NULL; lp++) { 63 | /* return entry number in the table when strings match and 64 | * lengths are same. */ 65 | // if((memcmp(isdb_t_conv_table[lp].parm_freq, channel, strlen(channel)) == 0) && 66 | // (strlen(channel) == strlen(isdb_t_conv_table[lp].parm_freq))) { 67 | if(strcmp(isdb_t_conv_table[lp].parm_freq, channel) == 0){ 68 | isdb_t_conv_tmp->bon_num = lp; 69 | isdb_t_conv_tmp->type = CHTYPE_SATELLITE; 70 | sprintf(isdb_t_conv_tmp->parm_freq, "BS%d_%d", isdb_t_conv_table[lp].set_freq*2+1, isdb_t_conv_table[lp].add_freq); 71 | goto FIND_EXIT; 72 | } 73 | } 74 | free(isdb_t_conv_tmp); 75 | return NULL; 76 | case ARIB_CS: 77 | node = dwBonChannel & 0x00ffU; 78 | isdb_t_conv_tmp->type = CHTYPE_SATELLITE; 79 | sprintf(isdb_t_conv_tmp->parm_freq, "CS%d", node); 80 | isdb_t_conv_tmp->bon_num = getBonNumber(node/2+11, 0); 81 | break; 82 | case ARIB_TSID: 83 | node = (dwBonChannel & 0x01f0U) >> 4; 84 | isdb_t_conv_tmp->type = CHTYPE_SATELLITE; 85 | if( (dwBonChannel & 0xf008U) == 0x4000U ){ 86 | slot = dwBonChannel & 0x0007U; 87 | if( node == 15 ) 88 | slot--; 89 | sprintf(isdb_t_conv_tmp->parm_freq, "BS%d_%d", node, slot); 90 | isdb_t_conv_tmp->bon_num = getBonNumber(node/2, slot); 91 | }else{ 92 | sprintf(isdb_t_conv_tmp->parm_freq, "CS%d", node); 93 | isdb_t_conv_tmp->bon_num = getBonNumber(node/2+11, 0); 94 | } 95 | break; 96 | } 97 | FIND_EXIT: 98 | return isdb_t_conv_tmp; 99 | } 100 | 101 | int 102 | open_tuner(thread_data *tdata, char *driver) 103 | { 104 | // モジュールロード 105 | tdata->hModule = dlopen(driver, RTLD_LAZY); 106 | if(!tdata->hModule) { 107 | fprintf(stderr, "Cannot open tuner driver: %s\ndlopen error: %s\n", driver, dlerror()); 108 | return -1; 109 | } 110 | 111 | // インスタンス作成 112 | tdata->pIBon = tdata->pIBon2 = NULL; 113 | char *err; 114 | IBonDriver *(*f)() = (IBonDriver *(*)())dlsym(tdata->hModule, "CreateBonDriver"); 115 | if ((err = dlerror()) == NULL) 116 | { 117 | tdata->pIBon = f(); 118 | if (tdata->pIBon) 119 | tdata->pIBon2 = dynamic_cast(tdata->pIBon); 120 | } 121 | else 122 | { 123 | fprintf(stderr, "dlsym error: %s\n", err); 124 | dlclose(tdata->hModule); 125 | return -2; 126 | } 127 | if (!tdata->pIBon || !tdata->pIBon2) 128 | { 129 | fprintf(stderr, "CreateBonDriver error: tdata->pIBon[%p] tdata->pIBon2[%p]\n", tdata->pIBon, tdata->pIBon2); 130 | dlclose(tdata->hModule); 131 | return -3; 132 | } 133 | 134 | // ここから実質のチューナオープン & TS取得処理 135 | BOOL b = tdata->pIBon->OpenTuner(); 136 | if (!b) 137 | { 138 | tdata->pIBon->Release(); 139 | dlclose(tdata->hModule); 140 | return -4; 141 | }else 142 | tdata->tfd = TRUE; 143 | 144 | #if 0 // linuxのBonDriverはOpenTuner()内で自動変更・SetLnbPower()未実装 145 | /* power on LNB */ 146 | if(tdata->lnb != -1 && tdata->table->type == CHTYPE_SATELLITE) { 147 | if(!tdata->pIBon->SetLnbPower(tdata->lnb>0 ? TRUE : FALSE)) { 148 | fprintf(stderr, "Power on LNB failed: %s\n", driver); 149 | } 150 | } 151 | #endif 152 | return 0; 153 | } 154 | 155 | int 156 | close_tuner(thread_data *tdata) 157 | { 158 | int rv = 0; 159 | 160 | if(tdata->table){ 161 | free(tdata->table); 162 | tdata->table = NULL; 163 | } 164 | if(tdata->hModule == NULL) 165 | return rv; 166 | 167 | #if 0 // linuxのBonDriverはCloseTuner()内で自動変更・SetLnbPower()未実装 168 | if(tdata->lnb > 0 && tdata->table->type == CHTYPE_SATELLITE) { 169 | if(!tdata->pIBon->SetLnbPower(FALSE)) { 170 | rv = 1; 171 | } 172 | } 173 | #endif 174 | // チューナクローズ 175 | if(tdata->tfd){ 176 | tdata->pIBon->CloseTuner(); 177 | tdata->tfd = FALSE; 178 | } 179 | // インスタンス解放 & モジュールリリース 180 | tdata->pIBon->Release(); 181 | dlclose(tdata->hModule); 182 | tdata->hModule = NULL; 183 | 184 | return rv; 185 | } 186 | 187 | 188 | void 189 | calc_cn(thread_data *tdata, boolean use_bell) 190 | { 191 | double CNR = (double)tdata->pIBon->GetSignalLevel(); 192 | 193 | if(use_bell) { 194 | int bell = 0; 195 | 196 | if(CNR >= 30.0) 197 | bell = 3; 198 | else if(CNR >= 15.0 && CNR < 30.0) 199 | bell = 2; 200 | else if(CNR < 15.0) 201 | bell = 1; 202 | fprintf(stderr, "\rC/N = %fdB ", CNR); 203 | do_bell(bell); 204 | } 205 | else { 206 | fprintf(stderr, "\rC/N = %fdB", CNR); 207 | } 208 | } 209 | 210 | void 211 | show_channels(void) 212 | { 213 | FILE *f; 214 | char *home; 215 | char buf[255], filename[255]; 216 | 217 | fprintf(stderr, "Available Channels:\n"); 218 | 219 | home = getenv("HOME"); 220 | sprintf(filename, "%s/.recpt1-channels", home); 221 | f = fopen(filename, "r"); 222 | if(f) { 223 | while(fgets(buf, 255, f)) 224 | fprintf(stderr, "%s", buf); 225 | fclose(f); 226 | } 227 | else 228 | fprintf(stderr, "13-62: Terrestrial Channels\n"); 229 | 230 | fprintf(stderr, "101ch: NHK BS1\n"); 231 | fprintf(stderr, "103ch: NHK BS Premium\n"); 232 | fprintf(stderr, "141ch: BS Nittele\n"); 233 | fprintf(stderr, "151ch: BS Asahi\n"); 234 | fprintf(stderr, "161ch: BS-TBS\n"); 235 | fprintf(stderr, "171ch: BS Japan\n"); 236 | fprintf(stderr, "181ch: BS Fuji\n"); 237 | fprintf(stderr, "191ch: WOWOW Prime\n"); 238 | fprintf(stderr, "192ch: WOWOW Live\n"); 239 | fprintf(stderr, "193ch: WOWOW Cinema\n"); 240 | fprintf(stderr, "200ch: Star Channel1\n"); 241 | fprintf(stderr, "201ch: Star Channel2\n"); 242 | fprintf(stderr, "202ch: Star Channel3\n"); 243 | fprintf(stderr, "211ch: BS11 Digital\n"); 244 | fprintf(stderr, "222ch: TwellV\n"); 245 | fprintf(stderr, "231ch: Housou Daigaku 1\n"); 246 | fprintf(stderr, "232ch: Housou Daigaku 2\n"); 247 | fprintf(stderr, "233ch: Housou Daigaku 3\n"); 248 | fprintf(stderr, "234ch: Green Channel\n"); 249 | fprintf(stderr, "236ch: BS Animax\n"); 250 | fprintf(stderr, "238ch: FOX bs238\n"); 251 | fprintf(stderr, "241ch: BS SkyPer!\n"); 252 | fprintf(stderr, "242ch: J SPORTS 1\n"); 253 | fprintf(stderr, "243ch: J SPORTS 2\n"); 254 | fprintf(stderr, "244ch: J SPORTS 3\n"); 255 | fprintf(stderr, "245ch: J SPORTS 4\n"); 256 | fprintf(stderr, "251ch: BS Tsuri Vision\n"); 257 | fprintf(stderr, "252ch: IMAGICA BS\n"); 258 | fprintf(stderr, "255ch: Nihon Eiga Senmon Channel\n"); 259 | fprintf(stderr, "256ch: Disney Channel\n"); 260 | fprintf(stderr, "258ch: Dlife\n"); 261 | fprintf(stderr, "C13-C63: CATV Channels\n"); 262 | fprintf(stderr, "CS2-CS24: CS Channels\n"); 263 | fprintf(stderr, "B0-: BonDriver Channel\n"); 264 | fprintf(stderr, "BS1_0-BS25_1: BS Channels(Transport)\n"); 265 | fprintf(stderr, "0x4000-0x7FFF: BS/CS Channels(TSID)\n"); 266 | } 267 | 268 | 269 | int 270 | parse_time(const char * rectimestr, int *recsec) 271 | { 272 | /* indefinite */ 273 | if(!strcmp("-", rectimestr)) { 274 | *recsec = -1; 275 | return 0; 276 | } 277 | /* colon */ 278 | else if(strchr(rectimestr, ':')) { 279 | int n1, n2, n3; 280 | if(sscanf(rectimestr, "%d:%d:%d", &n1, &n2, &n3) == 3) 281 | *recsec = n1 * 3600 + n2 * 60 + n3; 282 | else if(sscanf(rectimestr, "%d:%d", &n1, &n2) == 2) 283 | *recsec = n1 * 3600 + n2 * 60; 284 | else 285 | return 1; /* unsuccessful */ 286 | 287 | return 0; 288 | } 289 | /* HMS */ 290 | else { 291 | char *tmpstr; 292 | char *p1, *p2; 293 | int flag; 294 | 295 | if( *rectimestr == '-' ){ 296 | rectimestr++; 297 | flag = 1; 298 | }else 299 | flag = 0; 300 | tmpstr = strdup(rectimestr); 301 | p1 = tmpstr; 302 | while(*p1 && !isdigit(*p1)) 303 | p1++; 304 | 305 | /* hour */ 306 | if((p2 = strchr(p1, 'H')) || (p2 = strchr(p1, 'h'))) { 307 | *p2 = '\0'; 308 | *recsec += atoi(p1) * 3600; 309 | p1 = p2 + 1; 310 | while(*p1 && !isdigit(*p1)) 311 | p1++; 312 | } 313 | 314 | /* minute */ 315 | if((p2 = strchr(p1, 'M')) || (p2 = strchr(p1, 'm'))) { 316 | *p2 = '\0'; 317 | *recsec += atoi(p1) * 60; 318 | p1 = p2 + 1; 319 | while(*p1 && !isdigit(*p1)) 320 | p1++; 321 | } 322 | 323 | /* second */ 324 | *recsec += atoi(p1); 325 | if( flag ) 326 | *recsec *= -1; 327 | 328 | free(tmpstr); 329 | 330 | return 0; 331 | } /* else */ 332 | 333 | return 1; /* unsuccessful */ 334 | } 335 | 336 | void 337 | do_bell(int bell) 338 | { 339 | int i; 340 | for(i=0; i < bell; i++) { 341 | fprintf(stderr, "\a"); 342 | usleep(400000); 343 | } 344 | } 345 | 346 | int 347 | tune(char *channel, thread_data *tdata, char *driver) 348 | { 349 | /* get channel */ 350 | BON_CHANNEL_SET *table_tmp = searchrecoff(channel); 351 | if(table_tmp == NULL) { 352 | fprintf(stderr, "Invalid Channel: %s\n", channel); 353 | return 1; 354 | } 355 | DWORD dwSendBonNum; 356 | boolean reqChannel; 357 | if(table_tmp->bon_num != ARIB_CH_ERROR){ 358 | dwSendBonNum = table_tmp->bon_num; 359 | reqChannel = FALSE; 360 | }else{ 361 | dwSendBonNum = table_tmp->set_freq; 362 | reqChannel = TRUE; 363 | } 364 | 365 | /* open tuner */ 366 | char *dri_tmp = driver; 367 | int aera; 368 | char **tuner; 369 | int num_devs; 370 | if(dri_tmp && *dri_tmp == 'P'){ 371 | // proxy 372 | dri_tmp++; 373 | aera = 1; 374 | }else 375 | aera = 0; 376 | if(dri_tmp && *dri_tmp != '\0') { 377 | /* case 1: specified tuner driver */ 378 | int num = 0; 379 | int code; 380 | 381 | if(*dri_tmp == 'S'){ 382 | if(table_tmp->type != CHTYPE_GROUND){ 383 | if(aera == 0){ 384 | tuner = bsdev; 385 | num_devs = NUM_BSDEV; 386 | }else{ 387 | tuner = bsdev_proxy; 388 | num_devs = NUM_BSDEV_PROXY; 389 | } 390 | }else 391 | goto OPEN_TUNER; 392 | }else if(*dri_tmp == 'T'){ 393 | if(table_tmp->type != CHTYPE_SATELLITE){ 394 | if(aera == 0){ 395 | tuner = isdb_t_dev; 396 | num_devs = NUM_ISDB_T_DEV; 397 | }else{ 398 | tuner = isdb_t_dev_proxy; 399 | num_devs = NUM_ISDB_T_DEV_PROXY; 400 | } 401 | }else 402 | goto OPEN_TUNER; 403 | }else 404 | goto OPEN_TUNER; 405 | if(!isdigit(*++dri_tmp)) 406 | goto OPEN_TUNER; 407 | do{ 408 | num = num * 10 + *dri_tmp++ - '0'; 409 | }while(isdigit(*dri_tmp)); 410 | if(*dri_tmp == '\0' && num+1 <= num_devs) 411 | driver = tuner[num]; 412 | OPEN_TUNER:; 413 | if((code = open_tuner(tdata, driver))){ 414 | if(code == -4) 415 | fprintf(stderr, "OpenTuner erro: %s\n", driver); 416 | free(table_tmp); 417 | return 1; 418 | } 419 | #if 0 420 | DWORD m_dwChannel = tdata->pIBon2->GetCurChannel(); 421 | if(m_dwChannel != ARIB_CH_ERROR && m_dwChannel != dwSendBonNum){ 422 | fprintf(stderr, "Tuner has been used: %s\n", driver); 423 | goto err; 424 | } 425 | #endif 426 | /* tune to specified channel */ 427 | while(tdata->pIBon2->SetChannel(tdata->dwSpace, dwSendBonNum) == FALSE) { 428 | if(tdata->tune_persistent) { 429 | if(f_exit) 430 | goto err; 431 | fprintf(stderr, "No signal. Still trying: %s\n", driver); 432 | } 433 | else { 434 | fprintf(stderr, "Cannot tune to the specified channel: %s\n", driver); 435 | goto err; 436 | } 437 | } 438 | fprintf(stderr, "driver = %s\n", driver); 439 | } 440 | else { 441 | /* case 2: loop around available devices */ 442 | int lp; 443 | 444 | switch(table_tmp->type){ 445 | case CHTYPE_BonNUMBER: 446 | default: 447 | fprintf(stderr, "No driver name\n"); 448 | goto err; 449 | case CHTYPE_SATELLITE: 450 | if(aera == 0){ 451 | tuner = bsdev; 452 | num_devs = NUM_BSDEV; 453 | }else{ 454 | tuner = bsdev_proxy; 455 | num_devs = NUM_BSDEV_PROXY; 456 | } 457 | break; 458 | case CHTYPE_GROUND: 459 | if(aera == 0){ 460 | tuner = isdb_t_dev; 461 | num_devs = NUM_ISDB_T_DEV; 462 | }else{ 463 | tuner = isdb_t_dev_proxy; 464 | num_devs = NUM_ISDB_T_DEV_PROXY; 465 | } 466 | break; 467 | } 468 | 469 | for(lp = 0; lp < num_devs; lp++) { 470 | if(open_tuner(tdata, tuner[lp]) == 0) { 471 | // 同CHチェック・BSのCh比較は、局再編があると正しくない可能性がある 472 | DWORD m_dwChannel = tdata->pIBon2->GetCurChannel(); 473 | if(m_dwChannel == dwSendBonNum) 474 | goto SUCCESS_EXIT; 475 | else{ 476 | close_tuner(tdata); 477 | continue; 478 | } 479 | } 480 | } 481 | for(lp = 0; lp < num_devs; lp++) { 482 | int count = 0; 483 | 484 | if(open_tuner(tdata, tuner[lp]) == 0) { 485 | // 使用中チェック・BSのCh比較は、局再編があると正しくない可能性がある 486 | DWORD m_dwChannel = tdata->pIBon2->GetCurChannel(); 487 | if(m_dwChannel != ARIB_CH_ERROR){ 488 | if(m_dwChannel != dwSendBonNum){ 489 | close_tuner(tdata); 490 | continue; 491 | } 492 | }else{ 493 | /* tune to specified channel */ 494 | if(tdata->tune_persistent) { 495 | while(tdata->pIBon2->SetChannel(tdata->dwSpace, dwSendBonNum) == FALSE && count < MAX_RETRY) { 496 | if(f_exit) 497 | goto err; 498 | fprintf(stderr, "No signal. Still trying: %s\n", tuner[lp]); 499 | count++; 500 | } 501 | 502 | if(count >= MAX_RETRY) { 503 | close_tuner(tdata); 504 | count = 0; 505 | continue; 506 | } 507 | } /* tune_persistent */ 508 | else { 509 | if(tdata->pIBon2->SetChannel(tdata->dwSpace, dwSendBonNum) == FALSE) { 510 | close_tuner(tdata); 511 | continue; 512 | } 513 | } 514 | } 515 | 516 | goto SUCCESS_EXIT; /* found suitable tuner */ 517 | } 518 | } 519 | 520 | /* all tuners cannot be used */ 521 | free(table_tmp); 522 | fprintf(stderr, "Cannot tune to the specified channel\n"); 523 | return 1; 524 | 525 | SUCCESS_EXIT: 526 | if(tdata->tune_persistent) 527 | fprintf(stderr, "driver = %s\n", tuner[lp]); 528 | } 529 | tdata->table = table_tmp; 530 | if(reqChannel) 531 | table_tmp->bon_num = tdata->pIBon2->GetCurChannel(); 532 | // TS受信開始待ち 533 | timespec ts; 534 | ts.tv_sec = 0; 535 | ts.tv_nsec = 50 * 1000 * 1000; // 50ms 536 | { 537 | int lop = 0; 538 | do{ 539 | nanosleep(&ts, NULL); 540 | }while(tdata->pIBon->GetReadyCount() < 2 && ++lop < 20); 541 | } 542 | 543 | if(!tdata->tune_persistent) { 544 | /* show signal strength */ 545 | calc_cn(tdata, FALSE); 546 | } 547 | 548 | return 0; /* success */ 549 | err: 550 | free(table_tmp); 551 | close_tuner(tdata); 552 | 553 | return 1; 554 | } 555 | -------------------------------------------------------------------------------- /recpt1core.h: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #ifndef _RECPT1_UTIL_H_ 3 | #define _RECPT1_UTIL_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "../typedef.h" 33 | #include "../IBonDriver2.h" 34 | //#include "pt1_ioctl.h" 35 | #include "config.h" 36 | #include "decoder.h" 37 | #include "recpt1.h" 38 | #include "mkpath.h" 39 | #include "tssplitter_lite.h" 40 | 41 | /* ipc message size */ 42 | #define MSGSZ 255 43 | 44 | /* used in checksigna.c */ 45 | #define MAX_RETRY (2) 46 | 47 | /* type definitions */ 48 | typedef int boolean; 49 | 50 | typedef struct _sock_data { 51 | int sfd; /* socket fd */ 52 | struct sockaddr_in addr; 53 | } SOCK_data; 54 | 55 | typedef struct _msgbuf { 56 | long mtype; 57 | char mtext[MSGSZ]; 58 | } message_buf; 59 | 60 | typedef struct _thread_data { 61 | DWORD dwSpace; // tuner スペース指定(デフォルトは0) 62 | void *hModule; // tuner 動的ライブラリへの内部「ハンドル」 63 | IBonDriver *pIBon; // tuner 64 | IBonDriver2 *pIBon2; // tuner 65 | int tfd; /* tuner fd */ //xxx variable 66 | 67 | int wfd; /* output file fd */ //invariable 68 | int lnb; /* LNB voltage */ //invariable 69 | int msqid; //invariable 70 | time_t start_time; //invariable 71 | 72 | int recsec; //xxx variable 73 | 74 | boolean indefinite; //invaliable 75 | boolean tune_persistent; //invaliable 76 | 77 | QUEUE_T *queue; //invariable 78 | BON_CHANNEL_SET *table; //invariable 79 | SOCK_data *sock_data; //invariable 80 | pthread_t signal_thread; //invariable 81 | DECODER *decoder; //invariable 82 | decoder_options *dopt; //invariable 83 | Splitter *splitter; //invariable 84 | } thread_data; 85 | 86 | extern const char *version; 87 | extern boolean f_exit; 88 | 89 | /* prototypes */ 90 | int tune(char *channel, thread_data *tdata, char *device); 91 | int close_tuner(thread_data *tdata); 92 | void show_channels(void); 93 | BON_CHANNEL_SET *searchrecoff(char *channel); 94 | void calc_cn(thread_data *tdata, boolean use_bell); 95 | int parse_time(const char * rectimestr, int *recsec); 96 | void do_bell(int bell); 97 | 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /recpt1ctl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include "recpt1core.h" 11 | 12 | #define MSGSZ 255 13 | 14 | void 15 | show_usage(char *cmd) 16 | { 17 | fprintf(stderr, "Usage: \n%s --pid pid [--channel channel] [--sid SID1,SID2] [--extend time_to_extend] [--time recording_time]\n", cmd); 18 | fprintf(stderr, "\n"); 19 | } 20 | 21 | void 22 | show_options(void) 23 | { 24 | fprintf(stderr, "Options:\n"); 25 | fprintf(stderr, "--pid: Process id of recpt1 to control\n"); 26 | fprintf(stderr, "--channel: Tune to specified channel\n"); 27 | fprintf(stderr, "--sid SID1,SID2,...: Specify SID number in CSV format (101,102,...)\n"); 28 | fprintf(stderr, "--extend: Extend recording time\n"); 29 | fprintf(stderr, "--time: Set total recording time\n"); 30 | fprintf(stderr, "--help: Show this help\n"); 31 | fprintf(stderr, "--version: Show version\n"); 32 | fprintf(stderr, "--list: Show channel list\n"); 33 | } 34 | 35 | int 36 | main(int argc, char **argv) 37 | { 38 | int msqid; 39 | int msgflg = IPC_CREAT | 0666; 40 | key_t key = 0; 41 | int recsec = 0, extsec=0; 42 | char *channel = NULL; 43 | message_buf sbuf; 44 | size_t buf_length; 45 | char *sid_list = NULL; 46 | 47 | int result; 48 | int option_index; 49 | struct option long_options[] = { 50 | { "pid", 1, NULL, 'p'}, 51 | { "channel", 1, NULL, 'c'}, 52 | { "sid", 1, NULL, 'i'}, 53 | { "extend", 1, NULL, 'e'}, 54 | { "time", 1, NULL, 't'}, 55 | { "help", 0, NULL, 'h'}, 56 | { "version", 0, NULL, 'v'}, 57 | { "list", 0, NULL, 'l'}, 58 | {0, 0, NULL, 0} /* terminate */ 59 | }; 60 | 61 | while((result = getopt_long(argc, argv, "p:c:i:e:t:hvl", 62 | long_options, &option_index)) != -1) { 63 | switch(result) { 64 | case 'h': 65 | fprintf(stderr, "\n"); 66 | show_usage(argv[0]); 67 | fprintf(stderr, "\n"); 68 | show_options(); 69 | fprintf(stderr, "\n"); 70 | show_channels(); 71 | fprintf(stderr, "\n"); 72 | exit(0); 73 | break; 74 | case 'v': 75 | fprintf(stderr, "%s %s\n", argv[0], version); 76 | fprintf(stderr, "control command for recpt1.\n"); 77 | exit(0); 78 | break; 79 | case 'l': 80 | show_channels(); 81 | exit(0); 82 | break; 83 | /* following options require argument */ 84 | case 'p': 85 | key = (key_t)atoi(optarg); 86 | fprintf(stderr, "Pid = %d\n", key); 87 | break; 88 | case 'c': 89 | channel = optarg; 90 | fprintf(stderr, "Channel = %s\n", channel); 91 | break; 92 | case 'e': 93 | parse_time(optarg, &extsec); 94 | fprintf(stderr, "Extend %d sec\n", extsec); 95 | break; 96 | case 't': 97 | parse_time(optarg, &recsec); 98 | fprintf(stderr, "Total recording time = %d sec\n", recsec); 99 | break; 100 | case 'i': 101 | sid_list = optarg; 102 | fprintf(stderr, "Service ID = %s\n", sid_list); 103 | break; 104 | } 105 | } 106 | 107 | if(!key) { 108 | fprintf(stderr, "Arguments are necessary!\n"); 109 | fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]); 110 | exit(1); 111 | } 112 | 113 | if ((msqid = msgget(key, msgflg )) < 0) { 114 | perror("msgget"); 115 | exit(1); 116 | } 117 | 118 | sbuf.mtype = 1; 119 | sprintf(sbuf.mtext, "ch=%s t=%d e=%d sid=%s", channel, recsec, extsec, sid_list); 120 | 121 | buf_length = strlen(sbuf.mtext) + 1 ; 122 | 123 | if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0) { 124 | perror("msgsnd"); 125 | exit(1); 126 | } 127 | 128 | exit(0); 129 | } 130 | -------------------------------------------------------------------------------- /tssplitter_lite.c: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: t -*- */ 2 | /* tssplitter_lite.c -- split TS stream. 3 | 4 | Copyright 2009 querulous 5 | Copyright 2010 Naoya OYAMA 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include "decoder.h" 28 | #include "recpt1.h" 29 | #include "tssplitter_lite.h" 30 | 31 | /* prototypes */ 32 | static int ReadTs(Splitter *sp, ARIB_STD_B25_BUFFER *sbuf); 33 | static int AnalyzePat(Splitter *sp, unsigned char *buf); 34 | static int RecreatePat(Splitter *sp, unsigned char *buf, int *pos); 35 | static char** AnalyzeSid(char *sid); 36 | static int AnalyzePmt(Splitter *sp, unsigned char *buf, unsigned char mark); 37 | static unsigned int GetCrc32(unsigned char *data, int len); 38 | static int GetPid(unsigned char *data); 39 | 40 | /** 41 | * サービスID解析 42 | */ 43 | static char** AnalyzeSid( 44 | char* sid) // [in] サービスID(カンマ区切りテキスト) 45 | { 46 | int i = 0; 47 | char** sid_list = NULL; 48 | char* p; 49 | int CommaNum = 0; 50 | 51 | /* sid は次の形式の引数を許容する */ 52 | /* 指定無し */ 53 | /* SID[0] */ 54 | /* SID[0],SID[1],...,SID[N-1],SID[N] */ 55 | 56 | /*カンマの数を数える*/ 57 | p = sid; 58 | while(*p != '\0') 59 | { 60 | if( *p == C_CHAR_COMMA ){ 61 | CommaNum++; 62 | } 63 | p++; 64 | } 65 | 66 | /* sid_listの数はカンマの数+2(NULL止めするから) */ 67 | sid_list = (char **)malloc(sizeof(char*)*(CommaNum+2)); 68 | if ( sid_list == NULL ) 69 | { 70 | fprintf(stderr, "AnalyzeSid() malloc error.\n"); 71 | return NULL; 72 | } 73 | 74 | /* sidが空である場合 */ 75 | p = sid; 76 | if ( strlen(p) == 0 ) 77 | { 78 | sid_list[0] = NULL; 79 | return sid_list; 80 | } 81 | 82 | /* カンマ無し */ 83 | if ( CommaNum == 0 ) 84 | { 85 | sid_list[0] = sid; 86 | sid_list[1] = NULL; 87 | return sid_list; 88 | } 89 | 90 | /* カンマ区切りで複数指定時 */ 91 | i=0; 92 | p = sid; 93 | /* 文字列端に到達するか、カンマ数が数えた数に達したら終了 */ 94 | while((*p != '\0') || i < CommaNum) 95 | { 96 | /* 現在の処理位置をsid_list[i]にセット */ 97 | /* このタイミングの p は 98 | * ・sid先頭 99 | * ・[,]の次の文字 100 | * いずれかであるので p を sid_list[i] に代入してよい 101 | */ 102 | sid_list[i] = p; 103 | i++; 104 | 105 | /* 最初に現れる[,]をNULL文字で置換する */ 106 | p = strchr(p, C_CHAR_COMMA); 107 | if ( p == NULL ) 108 | { 109 | /* カンマが見つからない場合は最後の処理対象なので終了 */ 110 | break; 111 | } 112 | *p = '\0'; 113 | /* 処理位置をNULLで置換した文字の次の位置に設定する */ 114 | p++; 115 | } 116 | 117 | /* 最後のsid_list[n]はNULLポインタで止める */ 118 | sid_list[i] = NULL; 119 | 120 | i=0; 121 | while( sid_list[i] != NULL ) 122 | { 123 | i++; 124 | } 125 | #if 0 126 | for(i=0; sid_list[i] != NULL; i++) 127 | { 128 | printf("sid_list[%d]=[%s].\n",i, sid_list[i]); 129 | } 130 | #endif 131 | return sid_list; 132 | } 133 | 134 | /** 135 | * 初期化処理 136 | */ 137 | Splitter* split_startup( 138 | char *sid // [in] サービスID(引数で指定した文字列) 139 | ) 140 | { 141 | Splitter* sp; 142 | sp = (Splitter *)malloc(sizeof(Splitter)); 143 | if ( sp == NULL ) 144 | { 145 | fprintf(stderr, "split_startup malloc error.\n"); 146 | return NULL; 147 | } 148 | memset(sp->pids, 0, sizeof(sp->pids)); 149 | memset(sp->pmt_pids, 0, sizeof(sp->pmt_pids)); 150 | 151 | sp->sid_list = NULL; 152 | sp->pat = NULL; 153 | sp->sid_list = AnalyzeSid(sid); 154 | if ( sp->sid_list == NULL ) 155 | { 156 | free(sp); 157 | return NULL; 158 | } 159 | sp->pat_count = 0xFF; 160 | sp->pmt_retain = -1; 161 | sp->pmt_counter = 0; 162 | 163 | memset(sp->section_remain, 0U, sizeof(sp->section_remain)); 164 | memset(sp->packet_seq, 0U, sizeof(sp->packet_seq)); 165 | 166 | return sp; 167 | } 168 | 169 | /** 170 | * 落とすPIDを確定させる 171 | */ 172 | int split_select( 173 | Splitter *sp, // [in/out] splitter構造体 174 | ARIB_STD_B25_BUFFER *sbuf // [in] 入力TS 175 | ) 176 | { 177 | int result; 178 | // TS解析 179 | result = ReadTs(sp, sbuf); 180 | 181 | return result; 182 | } 183 | 184 | /** 185 | * 終了処理 186 | */ 187 | void split_shutdown(Splitter* sp) 188 | { 189 | if ( sp != NULL ) { 190 | if ( sp->pat != NULL ) 191 | { 192 | free(sp->pat); 193 | sp->pat = NULL; 194 | } 195 | if ( sp->sid_list != NULL ) 196 | { 197 | free(sp->sid_list); 198 | sp->sid_list = NULL; 199 | } 200 | free(sp); 201 | sp = NULL; 202 | } 203 | } 204 | 205 | /** 206 | * TS 解析処理 207 | * 208 | * 対象のチャンネル番号のみの PAT の再構築と出力対象 PID の抽出を行う 209 | */ 210 | static int ReadTs(Splitter *sp, ARIB_STD_B25_BUFFER *sbuf) 211 | #if 0 212 | unsigned char **pat, // [out] PAT 情報(再構築後) 213 | unsigned char* pids, // [out] 出力対象 PID 情報 214 | char** sid_list, // [in] 出力対象サービス ID のリスト 215 | unsigned char* pmt_pids, // [in] 出力対象PIDのPMT PID 216 | , // [in] pt1_drvの入力TS 217 | int* pmt_retain, // [in] 残すべきPMTの数 218 | int* pmt_counter // [out] 残したPMTの数 219 | #endif 220 | { 221 | int length = sbuf->size; 222 | int pid; 223 | int result = TSS_ERROR; 224 | int index; 225 | int analyze_result = 0; 226 | 227 | index = 0; 228 | while(length - index - LENGTH_PACKET > 0) { 229 | pid = GetPid(sbuf->data + index + 1); 230 | // PAT 231 | if(0x0000 == pid) { 232 | result = AnalyzePat(sp, sbuf->data + index); 233 | if(result != TSS_SUCCESS) { 234 | /* 下位の関数内部でmalloc error発生 */ 235 | return result; 236 | } 237 | } 238 | 239 | // PMT 240 | /* 残すpmt_pidである場合には、pmtに書かれている 241 | * 残すべきPCR/AUDIO/VIDEO PIDを取得する */ 242 | if(sp->pmt_pids[pid] == 1) { 243 | /* この中にはPMT毎に一度しか入らないようにしておく */ 244 | analyze_result = AnalyzePmt(sp, sbuf->data + index, 1); 245 | if(TSS_SUCCESS == analyze_result) { 246 | sp->pmt_pids[pid]++; 247 | sp->pmt_counter += 1; 248 | *(sbuf->data + index + 1) = 0xff; 249 | *(sbuf->data + index + 2) = 0xff; 250 | } 251 | } 252 | /* 録画する全てのPMTについて、中にあるPCR/AUDIO/VIDEOのPIDを 253 | * 得る */ 254 | /* pmt_counter と pmt_retain が一致する場合に条件は満たされる */ 255 | if(sp->pmt_counter == sp->pmt_retain) { 256 | result = TSS_SUCCESS; 257 | break; 258 | } 259 | else { 260 | result = TSS_ERROR; 261 | } 262 | index += LENGTH_PACKET; 263 | } 264 | 265 | return(result); 266 | } 267 | 268 | static int RescanPID(Splitter *splitter, unsigned char *buf) 269 | { 270 | int result = TSS_NULL; 271 | int i; 272 | 273 | // clear 274 | if (splitter->pmt_counter == splitter->pmt_retain) { 275 | memcpy(splitter->pids, splitter->pmt_pids, sizeof(splitter->pids)); 276 | splitter->pmt_counter = 0; 277 | memset(splitter->section_remain, 0U, sizeof(splitter->section_remain)); 278 | memset(splitter->packet_seq, 0U, sizeof(splitter->packet_seq)); 279 | 280 | fprintf(stderr, "Rescan PID \n"); 281 | } 282 | 283 | if (TSS_SUCCESS == AnalyzePmt(splitter, buf, 2)) { 284 | splitter->pmt_counter += 1; 285 | } 286 | 287 | if (splitter->pmt_retain == splitter->pmt_counter) { 288 | result = TSS_SUCCESS; 289 | for (i = 0; MAX_PID > i; i++) { 290 | if (splitter->pids[i] > 0) { 291 | splitter->pids[i] -= 1; 292 | } 293 | } 294 | fprintf(stderr, "Rescan PID End\n"); 295 | } 296 | 297 | return result; 298 | } 299 | /** 300 | * TS 分離処理 301 | */ 302 | int split_ts( 303 | Splitter *splitter, // [in] splitterパラメータ 304 | ARIB_STD_B25_BUFFER *sbuf, // [in] 入力TS 305 | splitbuf_t *dbuf // [out] 出力TS 306 | ) 307 | { 308 | int pid; 309 | unsigned char *sptr, *dptr; 310 | int s_offset = 0; 311 | int d_offset = 0; 312 | int result = TSS_SUCCESS; 313 | int pmts = 0; 314 | int version = 0; 315 | 316 | /* 初期化 */ 317 | dbuf->buffer_filled = 0; 318 | if (sbuf->size < 0) { 319 | return TSS_ERROR; 320 | } 321 | 322 | sptr = sbuf->data; 323 | dptr = dbuf->buffer; 324 | 325 | while(sbuf->size > s_offset) { 326 | pid = GetPid(sptr + s_offset + 1); 327 | switch(pid) { 328 | 329 | // PAT 330 | case 0x0000: 331 | // 巡回カウンタカウントアップ 332 | if(0xFF == splitter->pat_count) { 333 | splitter->pat_count = splitter->pat[3]; 334 | } 335 | else { 336 | splitter->pat_count += 1; 337 | if(0 == (splitter->pat_count & 0x0fU)) { 338 | splitter->pat_count -= 0x10; 339 | } 340 | } 341 | splitter->pat[3] = splitter->pat_count; 342 | 343 | memcpy(dptr + d_offset, splitter->pat, LENGTH_PACKET); 344 | d_offset += LENGTH_PACKET; 345 | dbuf->buffer_filled += LENGTH_PACKET; 346 | break; 347 | default: 348 | if(0 != splitter->pmt_pids[pid]) { 349 | //PMT 350 | if ((sptr + s_offset)[1] & 0x40) { // PES開始インジケータ 351 | // バージョンチェック 352 | for(pmts = 0; splitter->pmt_retain > pmts; pmts++) { 353 | if (splitter->pmt_version[pmts].pid == pid) { 354 | version = splitter->pmt_version[pmts].version; 355 | break; 356 | } 357 | } 358 | if((version != ((sptr + s_offset)[10] & 0x3e)) 359 | ||(splitter->pmt_retain != splitter->pmt_counter)) { 360 | // 再チェック 361 | result = RescanPID(splitter, sptr + s_offset); 362 | } 363 | } 364 | else { 365 | if (splitter->pmt_retain != splitter->pmt_counter) { 366 | // 再チェック 367 | result = RescanPID(splitter, sptr + s_offset); 368 | } 369 | } 370 | } 371 | /* pids[pid] が 1 は残すパケットなので書き込む */ 372 | if(0 != splitter->pids[pid]) { 373 | memcpy(dptr + d_offset, sptr + s_offset, LENGTH_PACKET); 374 | d_offset += LENGTH_PACKET; 375 | dbuf->buffer_filled += LENGTH_PACKET; 376 | } 377 | break; 378 | } /* switch */ 379 | 380 | s_offset += LENGTH_PACKET; 381 | } 382 | 383 | return result; 384 | } 385 | 386 | #ifdef ENABLE_EXTRA_SID 387 | int caption; 388 | int es_test; 389 | #endif 390 | 391 | /** 392 | * PAT 解析処理 393 | * 394 | * PAT を解析し、出力対象チャンネルが含まれているかチェックを行い、PAT を再構築する 395 | */ 396 | static int AnalyzePat(Splitter *sp, unsigned char *buf) 397 | #if 0 398 | Splitter *sp 399 | unsigned char** pat, // [out] PAT 情報(再構築後) 400 | unsigned char* pids, // [out] 出力対象 PID 情報 401 | char** sid_list, // [in] 出力対象サービス ID のリスト 402 | unsigned char* pmt_pids, // [out] サービス ID に対応する PMT の PID 403 | int* pmt_retain // [out] 残すPMTの数 404 | 405 | unsigned char* buf, // [in] 読み込んだバッファ 406 | #endif 407 | { 408 | int pos[MAX_PID]; 409 | int service_id; 410 | int i, j, k; 411 | int size = 0; 412 | int pid; 413 | int result = TSS_SUCCESS; 414 | char **p; 415 | int sid_found = FALSE; 416 | int avail_sids[MAX_SERVICES]; 417 | 418 | unsigned char *pat = sp->pat; 419 | unsigned char *pids = sp->pids; 420 | char **sid_list = sp->sid_list; 421 | unsigned char *pmt_pids = sp->pmt_pids; 422 | 423 | char chosen_sid[512]; 424 | chosen_sid[0] = '\0'; 425 | 426 | if(pat == NULL) { 427 | /* 初期化 */ 428 | sp->pmt_retain = 0; 429 | memset(pos, 0, sizeof(pos)); 430 | size = buf[7]; 431 | #ifdef ENABLE_EXTRA_SID 432 | caption = FALSE; // 字幕PID保存フラグ初期化 433 | es_test = FALSE; 434 | #endif 435 | 436 | /* prescan SID/PMT */ 437 | for(i = 13, j = 0; i < (size + 8) - 4; i = i + 4) { 438 | 439 | pid = GetPid(&buf[i+2]); 440 | if(pid == 0x0010) 441 | continue; 442 | 443 | avail_sids[j] = (buf[i] << 8) + buf[i+1]; 444 | sp->avail_pmts[j] = pid; 445 | j++; 446 | } 447 | sp->num_pmts = j; 448 | 449 | // 対象チャンネル判定 450 | /* size + 8 = パケット全長 */ 451 | /* 最終 4 バイトはCRCなので飛ばす */ 452 | for(i = 13; i < (size + 8) - 4; i = i + 4) { 453 | 454 | pid = GetPid(&buf[i+2]); 455 | if(pid == 0x0010) 456 | continue; 457 | 458 | service_id = (buf[i] << 8) + buf[i+1]; 459 | p = sid_list; 460 | 461 | while(*p) { 462 | if(service_id == atoi(*p)) { 463 | /* 録画対象の pmt_pids は 1 とする */ 464 | /* 録画対象の pmt の pids は 1 とする */ 465 | pid = GetPid(&buf[i + 2]); 466 | *(pmt_pids+pid) = 1; 467 | *(pids+pid) = 1; 468 | pos[pid] = i; 469 | sid_found = TRUE; 470 | sp->pmt_version[sp->pmt_retain].pid = pid; 471 | sp->pmt_retain += 1; 472 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 473 | } 474 | else if(!strcasecmp(*p, "hd") || !strcasecmp(*p, "sd1")) { 475 | /* hd/sd1 指定時には1番目のサービスを保存する */ 476 | if(service_id == avail_sids[0]) { 477 | pid = GetPid(&buf[i + 2]); 478 | *(pmt_pids+pid) = 1; 479 | *(pids+pid) = 1; 480 | pos[pid] = i; 481 | sid_found = TRUE; 482 | sp->pmt_version[sp->pmt_retain].pid = pid; 483 | sp->pmt_retain += 1; 484 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 485 | } 486 | } 487 | else if(!strcasecmp(*p, "sd2")) { 488 | /* sd2 指定時には2番目のサービスを保存する */ 489 | if(service_id == avail_sids[1]) { 490 | pid = GetPid(&buf[i + 2]); 491 | *(pmt_pids+pid) = 1; 492 | *(pids+pid) = 1; 493 | pos[pid] = i; 494 | sid_found = TRUE; 495 | sp->pmt_version[sp->pmt_retain].pid = pid; 496 | sp->pmt_retain += 1; 497 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 498 | } 499 | } 500 | else if(!strcasecmp(*p, "sd3")) { 501 | /* sd3 指定時には3番目のサービスを保存する */ 502 | if(service_id == avail_sids[2]) { 503 | pid = GetPid(&buf[i + 2]); 504 | *(pmt_pids+pid) = 1; 505 | *(pids+pid) = 1; 506 | pos[pid] = i; 507 | sid_found = TRUE; 508 | sp->pmt_version[sp->pmt_retain].pid = pid; 509 | sp->pmt_retain += 1; 510 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 511 | } 512 | } 513 | else if(!strcasecmp(*p, "1seg")) { 514 | /* 1seg 指定時には PMTPID=0x1FC8 のサービスを保存する */ 515 | pid = GetPid(&buf[i + 2]); 516 | if(pid == 0x1FC8) { 517 | *(pmt_pids+pid) = 1; 518 | *(pids+pid) = 1; 519 | pos[pid] = i; 520 | sid_found = TRUE; 521 | sp->pmt_version[sp->pmt_retain].pid = pid; 522 | sp->pmt_retain += 1; 523 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 524 | } 525 | } 526 | else if(!strcasecmp(*p, "all")) { 527 | /* all指定時には全保存する */ 528 | pid = GetPid(&buf[i + 2]); 529 | *(pmt_pids+pid) = 1; 530 | *(pids+pid) = 1; 531 | pos[pid] = i; 532 | sid_found = TRUE; 533 | sp->pmt_version[sp->pmt_retain].pid = pid; 534 | sp->pmt_retain += 1; 535 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 536 | break; 537 | } 538 | else if(!strcasecmp(*p, "epg")) { 539 | /* epg抽出に必要なPIDのみを保存する */ 540 | sid_found = TRUE; 541 | *(pids+0x11) = 1; 542 | *(pids+0x12) = 1; 543 | *(pids+0x23) = 1; // SDTT 544 | *(pids+0x29) = 1; // CDT 545 | } 546 | else if(!strcasecmp(*p, "epg1seg")) { 547 | /* ワンセグ用epg抽出に必要なPIDのみを保存する */ 548 | sid_found = TRUE; 549 | *(pids+0x11) = 1; 550 | // *(pids+0x26) = 1; // 車載用epg 規格のみで未送出のもよう 551 | *(pids+0x27) = 1; 552 | } 553 | #ifdef ENABLE_EXTRA_SID 554 | else if(!strcasecmp(*p, "caption")) { 555 | /* 字幕PID保存 ES PIDなのでフラグのみ変更 */ 556 | caption = TRUE; 557 | } 558 | else if(!strcasecmp(*p, "esdata")) { 559 | /* ES PIDなのでフラグのみ変更 */ 560 | es_test = TRUE; 561 | } 562 | #endif 563 | p++; 564 | } /* while */ 565 | } 566 | 567 | /* if sid has been specified but no sid found, fall back to all */ 568 | if(*sid_list && !sid_found) { 569 | for(i = 13; i < (size + 8) - 4; i = i + 4) { 570 | 571 | pid = GetPid(&buf[i+2]); 572 | if(pid==0x0010) 573 | continue; 574 | 575 | service_id = (buf[i] << 8) + buf[i+1]; 576 | pid = GetPid(&buf[i + 2]); 577 | *(pmt_pids+pid) = 1; 578 | *(pids+pid) = 1; 579 | pos[pid] = i; 580 | sid_found = TRUE; 581 | sp->pmt_version[sp->pmt_retain].pid = pid; 582 | sp->pmt_retain += 1; 583 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 584 | } 585 | } 586 | 587 | /* print SIDs */ 588 | fprintf(stderr, "Available sid = "); 589 | for(k=0; k < sp->num_pmts; k++) 590 | fprintf(stderr, "%d ", avail_sids[k]); 591 | fprintf(stderr, "\n"); 592 | fprintf(stderr, "Chosen sid =%s\n", chosen_sid); 593 | 594 | #if 1 595 | /* print PMTs */ 596 | fprintf(stderr, "Available PMT = "); 597 | for(k=0; k < sp->num_pmts; k++) 598 | fprintf(stderr, "0x%x ", sp->avail_pmts[k]); 599 | fprintf(stderr, "\n"); 600 | #endif 601 | 602 | // PAT 再構築 603 | result = RecreatePat(sp, buf, pos); 604 | #if 0 605 | int tc; 606 | for(tc=0; tc<188; tc++) 607 | fprintf(stderr, "%02x ", *(sp->pat+tc)); 608 | #endif 609 | } 610 | 611 | return(result); 612 | } 613 | 614 | /** 615 | * PAT 再構築処理 616 | * 617 | * PMT から出力対象チャンネル以外のチャンネル情報を削除し、PAT を再構築する 618 | */ 619 | static int RecreatePat(Splitter *sp, unsigned char *buf, int *pos) 620 | #if 0 621 | splitter *sp // [in/out] 622 | unsigned char** pat, // [out] PAT 情報(再構築後) 623 | unsigned char* pids, // [out] 出力対象 PID 情報 624 | 625 | unsigned char* buf, // [in] 読み込んだバッファ 626 | int *pos // [in] 取得対象 PMT のバッファ中の位置 627 | #endif 628 | { 629 | unsigned char y[LENGTH_CRC_DATA]; 630 | unsigned int crc; 631 | int i; 632 | int j; 633 | int pos_i; 634 | int pid_num = 0; 635 | 636 | // CRC 計算のためのデータ 637 | { 638 | // チャンネルによって変わらない部分 639 | for (i = 0; i < LENGTH_PAT_HEADER - 4; i++) 640 | { 641 | y[i] = buf[i + 5]; 642 | } 643 | 644 | // NIT 645 | y[LENGTH_PAT_HEADER-4] = 0x00; 646 | y[LENGTH_PAT_HEADER-3] = 0x00; 647 | y[LENGTH_PAT_HEADER-2] = 0xe0; 648 | y[LENGTH_PAT_HEADER-1] = 0x10; 649 | 650 | // チャンネルによって変わる部分 651 | for (i = 0; i < MAX_PID; i++) 652 | { 653 | if(pos[i] != 0) 654 | { 655 | /* buf[pos_i] を y にコピー(抽出したPIDの数) */ 656 | pos_i = pos[i]; 657 | for (j = 0; j < 4; j++) 658 | { 659 | y[LENGTH_PAT_HEADER + ((4*pid_num) + j)] = buf[pos_i + j]; 660 | } 661 | pid_num++; 662 | } 663 | } 664 | } 665 | /* パケットサイズ計算 */ 666 | y[2] = pid_num * 4 + 0x0d; 667 | // CRC 計算 668 | crc = GetCrc32(y, LENGTH_PAT_HEADER + pid_num*4); 669 | 670 | // PAT 再構成 671 | sp->pat = (unsigned char*)malloc(LENGTH_PACKET); 672 | if(sp->pat == NULL) 673 | { 674 | fprintf(stderr, "RecreatePat() malloc error.\n"); 675 | return(TSS_NULL); 676 | } 677 | memset(sp->pat, 0xFF, LENGTH_PACKET); 678 | for (i = 0; i < 5; i++) 679 | { 680 | (sp->pat)[i] = buf[i]; 681 | } 682 | for (i = 0; i < LENGTH_PAT_HEADER + pid_num*4; i++) 683 | { 684 | (sp->pat)[i + 5] = y[i]; 685 | } 686 | (sp->pat)[5 + LENGTH_PAT_HEADER + pid_num*4] = (crc >> 24) & 0xFF; 687 | (sp->pat)[6 + LENGTH_PAT_HEADER + pid_num*4] = (crc >> 16) & 0xFF; 688 | (sp->pat)[7 + LENGTH_PAT_HEADER + pid_num*4] = (crc >> 8) & 0xFF; 689 | (sp->pat)[8 + LENGTH_PAT_HEADER + pid_num*4] = (crc ) & 0xFF; 690 | 691 | return(TSS_SUCCESS); 692 | } 693 | 694 | /** 695 | * PMT 解析処理 696 | * 697 | * PMT を解析し、保存対象の PID を特定する 698 | */ 699 | static int AnalyzePmt(Splitter *sp, unsigned char *buf, unsigned char mark) 700 | #if 0 701 | unsigned char* buf, // [in] 読み込んだバッファ 702 | unsigned char* pids // [out] 出力対象 PID 情報 703 | #endif 704 | { 705 | unsigned int Nall; 706 | unsigned int N; 707 | int pcr; 708 | int epid; 709 | int pid; 710 | int retry_count = 0; 711 | int count; 712 | int payload_offset; // offset to payload 713 | 714 | pid = GetPid(&buf[1]); 715 | if (buf[1] & 0x40) { // PES開始インジケータ 716 | sp->section_remain[pid] = ((uint16_t)(buf[6] & 0x0FU) << 8) + buf[7] + 3; // セクションサイズ取得(ヘッダ込) 717 | payload_offset = 5; 718 | 719 | for (count = 0; sp->pmt_retain > count; count++) { 720 | if (sp->pmt_version[count].pid == pid) { 721 | sp->pmt_version[count].version = buf[10] & 0x3e; 722 | } 723 | } 724 | // PCR, 番組情報が先頭からはみ出ることはないだろう 725 | 726 | // PCR 727 | pcr = GetPid(&buf[payload_offset + 8]); 728 | sp->pids[pcr] = mark; 729 | 730 | // ECM 731 | N = ((unsigned int)(buf[payload_offset + 10] & 0x0F) << 8) + buf[payload_offset + 11] + payload_offset + 12; // ES情報開始点 732 | unsigned int p = payload_offset + 12; 733 | 734 | while(p < N) { 735 | uint32_t ca_pid; 736 | uint32_t tag; 737 | uint32_t len; 738 | 739 | tag = buf[p]; 740 | len = buf[p+1]; 741 | p += 2; 742 | 743 | if(tag == 0x09 && len >= 4 && p+len <= N) { 744 | // ca_pid = ((buf[p+2] << 8) | buf[p+3]) & 0x1fff; 745 | ca_pid = GetPid( &buf[p+2] ); 746 | sp->pids[ca_pid] = mark; 747 | } 748 | p += len; 749 | } 750 | } 751 | else { 752 | if (sp->section_remain[pid] == 0) return TSS_ERROR; // セクション先頭が飛んでいる 753 | if ((buf[3] & 0x0F) != ((sp->packet_seq[pid] + 1) & 0x0F)) return TSS_ERROR; // パケットカウンタが飛んだ 754 | payload_offset = 4; 755 | N = payload_offset; 756 | } 757 | sp->packet_seq[pid] = buf[3] & 0x0F; // 巡回カウンタ 758 | 759 | Nall = sp->section_remain[pid]; 760 | if(Nall > LENGTH_PACKET - (unsigned int)payload_offset) 761 | Nall = LENGTH_PACKET - payload_offset; 762 | 763 | // ES PID 764 | while (N <= Nall + payload_offset - 5) 765 | { 766 | #ifdef ENABLE_EXTRA_SID 767 | do{ 768 | if( buf[N] == 0x0d ) 769 | break; 770 | else 771 | if( buf[N] == 0x06 ){ // 字幕 772 | if( caption == FALSE ) 773 | break; 774 | }else 775 | if( buf[N]==0x0a || buf[N]==0x0b || buf[N]==0x0c ) 776 | if( es_test == FALSE ) 777 | break; 778 | epid = GetPid(&buf[N + 1]); 779 | sp->pids[epid] = mark; 780 | fprintf(stderr, "type:0x%02X PID:0x%04x\n", buf[N], epid ); 781 | }while(0); 782 | #else 783 | // ストリーム種別が 0x0D(type D)は出力対象外 784 | if (0x0D != buf[N]) 785 | { 786 | epid = GetPid(&buf[N + 1]); 787 | 788 | sp->pids[epid] = mark; 789 | } 790 | #endif 791 | N += 5 + (((unsigned int)buf[N + 3] & 0x0F) << 8) + buf[N + 4]; 792 | retry_count++; 793 | if((unsigned int)retry_count > Nall) { 794 | return TSS_ERROR; 795 | } 796 | } 797 | sp->section_remain[pid] -= Nall; 798 | 799 | if (sp->section_remain[pid] > 0) 800 | return SECTION_CONTINUE; 801 | else 802 | return TSS_SUCCESS; 803 | } 804 | 805 | /** 806 | * CRC 計算 807 | */ 808 | static unsigned int GetCrc32( 809 | unsigned char* data, // [in] CRC 計算対象データ 810 | int len) // [in] CRC 計算対象データ長 811 | { 812 | unsigned int crc; 813 | int i, j; 814 | unsigned int c; 815 | unsigned int bit; 816 | 817 | crc = 0xFFFFFFFFU; 818 | for (i = 0; i < len; i++) 819 | { 820 | unsigned int x; 821 | x = data[i]; 822 | 823 | for (j = 0; j < 8; j++) 824 | { 825 | 826 | bit = (x >> (7 - j)) & 0x1; 827 | 828 | c = 0; 829 | if (crc & 0x80000000U) 830 | { 831 | c = 1; 832 | } 833 | 834 | crc = crc << 1; 835 | 836 | if (c ^ bit) 837 | { 838 | crc ^= 0x04C11DB7U; 839 | } 840 | 841 | crc &= 0xFFFFFFFFU; 842 | } 843 | } 844 | 845 | return crc; 846 | } 847 | 848 | /** 849 | * PID 取得 850 | */ 851 | static int GetPid( 852 | unsigned char* data) // [in] 取得対象データのポインタ 853 | { 854 | return (int)((((unsigned int)data[0] & 0x1F) << 8) | (unsigned int)data[1]); 855 | } 856 | -------------------------------------------------------------------------------- /tssplitter_lite.h: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: t -*- */ 2 | /* tssplitter_lite.h -- split TS stream program's header. 3 | 4 | Copyright 2009 querulous 5 | Copyright 2010 Naoya OYAMA 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . */ 19 | #ifndef _TS_SPLITTER_LITE_H_ 20 | #define _TS_SPLITTER_LITE_H_ 21 | 22 | #define __STDC_FORMAT_MACROS 23 | #include 24 | #include 25 | 26 | #define LENGTH_PACKET (188) 27 | #define MAX_PID (8192) 28 | #define MAX_SERVICES (50) 29 | #define LENGTH_CRC_DATA (176) 30 | #define false (0) 31 | #define true (1) 32 | 33 | #define TSS_SUCCESS (0) 34 | #define TSS_ERROR (-1) 35 | #define TSS_NULL (-2) 36 | #define LENGTH_PAT_HEADER (12) 37 | #define C_CHAR_COMMA ',' 38 | #define SECTION_CONTINUE (1) 39 | 40 | typedef struct _pmt_version { 41 | int pid; 42 | int version; 43 | int packet; 44 | } PMT_version; 45 | 46 | /** 47 | * splitter構造体 48 | */ 49 | typedef struct _splitter { 50 | unsigned char pids[MAX_PID]; 51 | unsigned char pmt_pids[MAX_PID]; 52 | unsigned char* pat; 53 | char** sid_list; 54 | unsigned char pat_count; 55 | int pmt_retain; 56 | int pmt_counter; 57 | int avail_pmts[MAX_SERVICES]; 58 | PMT_version pmt_version[MAX_SERVICES]; 59 | int num_pmts; 60 | uint16_t section_remain[MAX_PID]; // セクション残りバイト数 61 | uint8_t packet_seq[MAX_PID]; // 巡回カウンタ 62 | } Splitter; 63 | 64 | typedef struct _splitbuf_t 65 | { 66 | u_char* buffer; 67 | int buffer_size; 68 | int buffer_filled; 69 | } splitbuf_t; 70 | 71 | Splitter* split_startup(char *sid); 72 | int split_select(Splitter *sp, ARIB_STD_B25_BUFFER *sbuf); 73 | void split_shutdown(Splitter *sp); 74 | int split_ts(Splitter *splitter, ARIB_STD_B25_BUFFER *sbuf, splitbuf_t *dbuf); 75 | 76 | #endif 77 | --------------------------------------------------------------------------------