├── CMakeLists.txt ├── COPYING ├── Changelog ├── FindIconv.cmake ├── aribstr.c ├── aribstr.h ├── autogen.sh ├── bit.c ├── bit.h ├── config.h.in ├── eit.c ├── eit.h ├── epgdump.c ├── nit.c ├── nit.h ├── readme.txt ├── sdt.c ├── sdt.h ├── tdt.c ├── tdt.h ├── ts.c ├── ts.h ├── ts_ctl.h ├── util.c ├── util.h └── xmldata.c /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/") 4 | 5 | include(CheckIncludeFiles) 6 | include(CheckStructHasMember) 7 | include(CheckSymbolExists) 8 | 9 | PROJECT(epgdump) 10 | 11 | SET(serial "0.2.1") 12 | 13 | find_package (Iconv REQUIRED) 14 | IF( ICONV_FOUND ) 15 | INCLUDE_DIRECTORIES( ${ICONV_INCLUDE_DIR} ) 16 | SET( HAVE_ICONV_H 1 ) 17 | SET( ICONV_REQUIRES_CONST ${ICONV_SECOND_ARGUMENT_IS_CONST} ) 18 | ENDIF( ICONV_FOUND ) 19 | 20 | include_directories (${CMAKE_SOURCE_DIR}/) 21 | 22 | CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/config.h.in ${CMAKE_SOURCE_DIR}/config.h ) 23 | 24 | ADD_EXECUTABLE(epgdump 25 | aribstr.c 26 | eit.c 27 | epgdump.c 28 | nit.c 29 | sdt.c 30 | bit.c 31 | ts.c 32 | tdt.c 33 | util.c) 34 | 35 | 36 | target_link_libraries (epgdump ${ICONV_LIBRARIES}) 37 | 38 | install(TARGETS epgdump RUNTIME DESTINATION "bin") 39 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | version 0.2.1 2 | cmakeによるビルドに変更 3 | version 0.2.0 4 | BSCSGR区別をTSファイルから行うようにした。 5 | 地上はGR+リモコンID(NITから取得) 6 | 引数を変更 7 | JSON形式出力を追加 8 | 番組カテゴリ出力の配列化(最大7)。CS専用カテゴリ追加 9 | 番組付加情報の出力(中断あり、延長ありなど) 10 | チャンネル一覧のCSV出力を追加 11 | BITからEITの送出間隔を取得 12 | TOTと送出間隔から、EITの周期が一回りしたぐらいでEXITするようにした 13 | 14 | version 0.1.1 15 | TSIDからトラポン・スロット・BSCS区別を取得できるようにした。 16 | version 0.1.0 17 | とりあえず最初のリリース 18 | 19 | 20 | -------------------------------------------------------------------------------- /FindIconv.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find Iconv 2 | # Once done this will define 3 | # 4 | # ICONV_FOUND - system has Iconv 5 | # ICONV_INCLUDE_DIR - the Iconv include directory 6 | # ICONV_LIBRARIES - Link these to use Iconv 7 | # ICONV_SECOND_ARGUMENT_IS_CONST - the second argument for iconv() is const 8 | # 9 | include(CheckCXXSourceCompiles) 10 | 11 | IF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) 12 | # Already in cache, be silent 13 | SET(ICONV_FIND_QUIETLY TRUE) 14 | ENDIF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) 15 | 16 | FIND_PATH(ICONV_INCLUDE_DIR iconv.h PATHS /usr/local/include /usr/include) 17 | 18 | FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c PATHS /usr/local/lib /usr/lib) 19 | 20 | IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) 21 | SET(ICONV_FOUND TRUE) 22 | ENDIF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) 23 | 24 | set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) 25 | set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES}) 26 | IF(ICONV_FOUND) 27 | check_cxx_source_compiles(" 28 | #include 29 | int main(){ 30 | iconv_t conv = 0; 31 | const char* in = 0; 32 | size_t ilen = 0; 33 | char* out = 0; 34 | size_t olen = 0; 35 | iconv(conv, &in, &ilen, &out, &olen); 36 | return 0; 37 | } 38 | " ICONV_SECOND_ARGUMENT_IS_CONST ) 39 | ENDIF(ICONV_FOUND) 40 | set(CMAKE_REQUIRED_INCLUDES) 41 | set(CMAKE_REQUIRED_LIBRARIES) 42 | 43 | IF(ICONV_FOUND) 44 | IF(NOT ICONV_FIND_QUIETLY) 45 | MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}") 46 | ENDIF(NOT ICONV_FIND_QUIETLY) 47 | ELSE(ICONV_FOUND) 48 | IF(Iconv_FIND_REQUIRED) 49 | MESSAGE(FATAL_ERROR "Could not find Iconv") 50 | ENDIF(Iconv_FIND_REQUIRED) 51 | ENDIF(ICONV_FOUND) 52 | 53 | MARK_AS_ADVANCED( 54 | ICONV_INCLUDE_DIR 55 | ICONV_LIBRARIES 56 | ICONV_SECOND_ARGUMENT_IS_CONST 57 | ) 58 | -------------------------------------------------------------------------------- /aribstr.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "aribstr.h" 10 | 11 | #define CODE_UNKNOWN 0 // 不明なグラフィックセット(非対応) 12 | #define CODE_KANJI 1 // Kanji 13 | #define CODE_ALPHANUMERIC 2 // Alphanumeric 14 | #define CODE_HIRAGANA 3 // Hiragana 15 | #define CODE_KATAKANA 4 // Katakana 16 | #define CODE_MOSAIC_A 5 // Mosaic A 17 | #define CODE_MOSAIC_B 6 // Mosaic B 18 | #define CODE_MOSAIC_C 7 // Mosaic C 19 | #define CODE_MOSAIC_D 8 // Mosaic D 20 | #define CODE_PROP_ALPHANUMERIC 9 // Proportional Alphanumeric 21 | #define CODE_PROP_HIRAGANA 10 // Proportional Hiragana 22 | #define CODE_PROP_KATAKANA 11 // Proportional Katakana 23 | #define CODE_JIS_X0201_KATAKANA 12 // JIS X 0201 Katakana 24 | #define CODE_JIS_KANJI_PLANE_1 13 // JIS compatible Kanji Plane 1 25 | #define CODE_JIS_KANJI_PLANE_2 14 // JIS compatible Kanji Plane 2 26 | #define CODE_ADDITIONAL_SYMBOLS 15 // Additional symbols 27 | 28 | 29 | #define TCHAR char 30 | #define BYTE char 31 | #define WORD int 32 | #define DWORD int 33 | #define bool int 34 | #define true 1 35 | #define false 0 36 | #define TEXT(a) a 37 | #define _T(a) a 38 | #define CODE_SET int 39 | 40 | static int m_CodeG[4]; 41 | static int *m_pLockingGL; 42 | static int *m_pLockingGR; 43 | static int *m_pSingleGL; 44 | 45 | static BYTE m_byEscSeqCount; 46 | static BYTE m_byEscSeqIndex; 47 | static bool m_bIsEscSeqDrcs; 48 | 49 | 50 | static const DWORD AribToStringInternal(TCHAR *lpszDst, const BYTE *pSrcData, const DWORD dwSrcLen); 51 | static const DWORD ProcessCharCode(TCHAR *lpszDst, const WORD wCode, const CODE_SET CodeSet); 52 | 53 | static const DWORD PutKanjiChar(TCHAR *lpszDst, const WORD wCode); 54 | static const DWORD PutAlphanumericChar(TCHAR *lpszDst, const WORD wCode); 55 | //static const DWORD PutAlphanumericHankakuChar(TCHAR *lpszDst, const WORD wCode); 56 | static const DWORD PutHiraganaChar(TCHAR *lpszDst, const WORD wCode); 57 | static const DWORD PutKatakanaChar(TCHAR *lpszDst, const WORD wCode); 58 | static const DWORD PutJisKatakanaChar(TCHAR *lpszDst, const WORD wCode); 59 | static const DWORD PutSymbolsChar(TCHAR *lpszDst, const WORD wCode); 60 | 61 | static void ProcessEscapeSeq(const BYTE byCode); 62 | 63 | static void LockingShiftGL(const BYTE byIndexG); 64 | static void LockingShiftGR(const BYTE byIndexG); 65 | static void SingleShiftGL(const BYTE byIndexG); 66 | 67 | static const bool DesignationGSET(const BYTE byIndexG, const BYTE byCode); 68 | static const bool DesignationDRCS(const BYTE byIndexG, const BYTE byCode); 69 | 70 | static const bool abCharSizeTable[] = 71 | { 72 | false, // CODE_UNKNOWN 不明なグラフィックセット(非対応) 73 | true, // CODE_KANJI Kanji 74 | false, // CODE_ALPHANUMERIC Alphanumeric 75 | false, // CODE_HIRAGANA Hiragana 76 | false, // CODE_KATAKANA Katakana 77 | false, // CODE_MOSAIC_A Mosaic A 78 | false, // CODE_MOSAIC_B Mosaic B 79 | false, // CODE_MOSAIC_C Mosaic C 80 | false, // CODE_MOSAIC_D Mosaic D 81 | false, // CODE_PROP_ALPHANUMERIC Proportional Alphanumeric 82 | false, // CODE_PROP_HIRAGANA Proportional Hiragana 83 | false, // CODE_PROP_KATAKANA Proportional Katakana 84 | false, // CODE_JIS_X0201_KATAKANA JIS X 0201 Katakana 85 | true, // CODE_JIS_KANJI_PLANE_1 JIS compatible Kanji Plane 1 86 | true, // CODE_JIS_KANJI_PLANE_2 JIS compatible Kanji Plane 2 87 | true // CODE_ADDITIONAL_SYMBOLS Additional symbols 88 | }; 89 | 90 | typedef enum{ 91 | STR_SMALL = 0, //SSZ 92 | STR_MEDIUM, //MSZ 93 | STR_NORMAL, //NSZ 94 | STR_MICRO, //SZX 0x60 95 | STR_HIGH_W, //SZX 0x41 96 | STR_WIDTH_W, //SZX 0x44 97 | STR_W, //SZX 0x45 98 | STR_SPECIAL_1, //SZX 0x6B 99 | STR_SPECIAL_2, //SZX 0x64 100 | } STRING_SIZE; 101 | 102 | STRING_SIZE m_emStrSize; 103 | 104 | bool IsSmallCharMode(void) 105 | { 106 | bool bRet = false; 107 | switch(m_emStrSize){ 108 | case STR_SMALL: 109 | bRet = true; 110 | break; 111 | case STR_MEDIUM: 112 | bRet = true; 113 | break; 114 | case STR_NORMAL: 115 | bRet = false; 116 | break; 117 | case STR_MICRO: 118 | bRet = true; 119 | break; 120 | case STR_HIGH_W: 121 | bRet = false; 122 | break; 123 | case STR_WIDTH_W: 124 | bRet = false; 125 | break; 126 | case STR_W: 127 | bRet = false; 128 | break; 129 | case STR_SPECIAL_1: 130 | bRet = false; 131 | break; 132 | case STR_SPECIAL_2: 133 | bRet = false; 134 | break; 135 | default: 136 | break; 137 | } 138 | return bRet; 139 | } 140 | 141 | int AribToString( 142 | char *lpszDst, 143 | const char *pSrcData, 144 | const int dwSrcLen) { 145 | 146 | return AribToStringInternal(lpszDst, pSrcData, dwSrcLen); 147 | } 148 | 149 | 150 | const DWORD AribToStringInternal(TCHAR *lpszDst, 151 | const BYTE *pSrcData, const DWORD dwSrcLen) 152 | { 153 | if(!pSrcData || !dwSrcLen || !lpszDst)return 0UL; 154 | 155 | DWORD dwSrcPos = 0UL; 156 | DWORD dwDstLen = 0UL; 157 | int dwSrcData; 158 | 159 | // 状態初期設定 160 | m_byEscSeqCount = 0U; 161 | m_pSingleGL = NULL; 162 | 163 | m_CodeG[0] = CODE_KANJI; 164 | m_CodeG[1] = CODE_ALPHANUMERIC; 165 | m_CodeG[2] = CODE_HIRAGANA; 166 | m_CodeG[3] = CODE_KATAKANA; 167 | 168 | m_pLockingGL = &m_CodeG[0]; 169 | m_pLockingGR = &m_CodeG[2]; 170 | 171 | m_emStrSize = STR_NORMAL; 172 | 173 | while(dwSrcPos < dwSrcLen){ 174 | dwSrcData = pSrcData[dwSrcPos] & 0xFF; 175 | 176 | if(!m_byEscSeqCount){ 177 | 178 | // GL/GR領域 179 | if((dwSrcData >= 0x21U) && (dwSrcData <= 0x7EU)){ 180 | // GL領域 181 | const CODE_SET CurCodeSet = (m_pSingleGL)? *m_pSingleGL : *m_pLockingGL; 182 | m_pSingleGL = NULL; 183 | 184 | if(abCharSizeTable[CurCodeSet]){ 185 | // 2バイトコード 186 | if((dwSrcLen - dwSrcPos) < 2UL)break; 187 | 188 | dwDstLen += ProcessCharCode(&lpszDst[dwDstLen], ((WORD)pSrcData[dwSrcPos + 0] << 8) | (WORD)pSrcData[dwSrcPos + 1], CurCodeSet); 189 | dwSrcPos++; 190 | } 191 | else{ 192 | // 1バイトコード 193 | dwDstLen += ProcessCharCode(&lpszDst[dwDstLen], (WORD)dwSrcData, CurCodeSet); 194 | } 195 | } 196 | else if((dwSrcData >= 0xA1U) && (dwSrcData <= 0xFEU)){ 197 | // GR領域 198 | const CODE_SET CurCodeSet = *m_pLockingGR; 199 | 200 | if(abCharSizeTable[CurCodeSet]){ 201 | // 2バイトコード 202 | if((dwSrcLen - dwSrcPos) < 2UL)break; 203 | 204 | dwDstLen += ProcessCharCode(&lpszDst[dwDstLen], ((WORD)(pSrcData[dwSrcPos + 0] & 0x7FU) << 8) | (WORD)(pSrcData[dwSrcPos + 1] & 0x7FU), CurCodeSet); 205 | dwSrcPos++; 206 | } 207 | else{ 208 | // 1バイトコード 209 | dwDstLen += ProcessCharCode(&lpszDst[dwDstLen], (WORD)(dwSrcData & 0x7FU), CurCodeSet); 210 | } 211 | } 212 | else{ 213 | // 制御コード 214 | switch(dwSrcData){ 215 | case 0x0FU : LockingShiftGL(0U); break; // LS0 216 | case 0x0EU : LockingShiftGL(1U); break; // LS1 217 | case 0x19U : SingleShiftGL(2U); break; // SS2 218 | case 0x1DU : SingleShiftGL(3U); break; // SS3 219 | case 0x1BU : m_byEscSeqCount = 1U; break; // ESC 220 | case 0x89U : m_emStrSize = STR_MEDIUM; break; // MSZ 221 | case 0x8AU : m_emStrSize = STR_NORMAL; break; // NSZ 222 | case 0x20U : 223 | case 0xA0U : 224 | //SP 空白 225 | //空白は文字サイズの影響あり 226 | if( IsSmallCharMode() == false ){ 227 | strcpy(&lpszDst[dwDstLen], " "); 228 | dwDstLen += 3U; 229 | } else { 230 | lpszDst[dwDstLen++] = TEXT(' '); 231 | } 232 | break; 233 | default : break; // 非対応 234 | } 235 | } 236 | } 237 | else{ 238 | // エスケープシーケンス処理 239 | ProcessEscapeSeq(dwSrcData); 240 | } 241 | 242 | dwSrcPos++; 243 | } 244 | 245 | // 終端文字 246 | lpszDst[dwDstLen] = TEXT('\0'); 247 | 248 | return dwDstLen; 249 | } 250 | 251 | const DWORD ProcessCharCode(TCHAR *lpszDst, const WORD wCode, const CODE_SET CodeSet) 252 | { 253 | switch(CodeSet){ 254 | case CODE_KANJI : 255 | case CODE_JIS_KANJI_PLANE_1 : 256 | case CODE_JIS_KANJI_PLANE_2 : 257 | // 漢字コード出力 258 | return PutKanjiChar(lpszDst, wCode); 259 | 260 | case CODE_ALPHANUMERIC : 261 | case CODE_PROP_ALPHANUMERIC : 262 | // 英数字コード出力 263 | if( IsSmallCharMode() == false ){ 264 | //全角テーブルコード取得 265 | return PutAlphanumericChar(lpszDst, wCode); 266 | } else { 267 | //半角はそのまま出力 268 | lpszDst[0] = wCode; 269 | return 1UL; 270 | } 271 | 272 | case CODE_HIRAGANA : 273 | case CODE_PROP_HIRAGANA : 274 | // ひらがなコード出力 275 | return PutHiraganaChar(lpszDst, wCode); 276 | 277 | case CODE_PROP_KATAKANA : 278 | case CODE_KATAKANA : 279 | // カタカナコード出力 280 | return PutKatakanaChar(lpszDst, wCode); 281 | 282 | case CODE_JIS_X0201_KATAKANA : 283 | // JISカタカナコード出力 284 | return PutJisKatakanaChar(lpszDst, wCode); 285 | 286 | case CODE_ADDITIONAL_SYMBOLS : 287 | // 追加シンボルコード出力 288 | return PutSymbolsChar(lpszDst, wCode); 289 | 290 | default : 291 | return 0UL; 292 | } 293 | } 294 | 295 | const DWORD PutKanjiChar(TCHAR *lpszDst, const WORD wCode) 296 | { 297 | char code[9]; 298 | char xcode[5]; 299 | iconv_t cd; 300 | 301 | size_t inbyte = 8; 302 | size_t outbyte = sizeof(xcode); 303 | 304 | memset(xcode, '\0', sizeof(xcode)); 305 | 306 | const char *fptr; 307 | char *tptr; 308 | 309 | code[0] = 0x1BU; 310 | code[1] = 0x24U; 311 | code[2] = 0x40U; 312 | code[3] = wCode >> 8; 313 | code[4] = wCode & 0xFF; 314 | code[5] = 0x1BU; 315 | code[6] = 0x28U; 316 | code[7] = 0x4AU; 317 | code[8] = '\0'; 318 | 319 | cd = iconv_open("UTF-8","ISO-2022-JP"); 320 | 321 | fptr = code; 322 | tptr = xcode; 323 | iconv(cd, (ICONV_CONST char **)&fptr, &inbyte, &tptr, &outbyte); 324 | 325 | iconv_close(cd); 326 | 327 | strncpy(lpszDst, xcode, strlen(xcode)); 328 | 329 | return strlen(lpszDst); 330 | } 331 | 332 | const DWORD PutAlphanumericChar(TCHAR *lpszDst, const WORD wCode) 333 | { 334 | // 英数字全角文字コード変換 335 | static const TCHAR *acAlphanumericTable = 336 | TEXT("                ") 337 | TEXT("                ") 338 | TEXT(" !”#$%&’()*+,-./") 339 | TEXT("0123456789:;<=>?") 340 | TEXT("@ABCDEFGHIJKLMNO") 341 | TEXT("PQRSTUVWXYZ[¥]^_") 342 | TEXT(" abcdefghijklmno") 343 | TEXT("pqrstuvwxyz{|} ̄ "); 344 | 345 | #ifdef _UNICODE 346 | lpszDst[0] = acAlphanumericTableZenkaku[wCode]; 347 | 348 | return 1UL; 349 | #else 350 | lpszDst[0] = acAlphanumericTable[wCode * 3U + 0U]; 351 | lpszDst[1] = acAlphanumericTable[wCode * 3U + 1U]; 352 | lpszDst[2] = acAlphanumericTable[wCode * 3U + 2U]; 353 | 354 | return 3UL; 355 | #endif 356 | } 357 | 358 | const DWORD PutHiraganaChar(TCHAR *lpszDst, const WORD wCode) 359 | { 360 | // ひらがな文字コード変換 361 | static const TCHAR *acHiraganaTable = 362 | TEXT("                ") 363 | TEXT("                ") 364 | TEXT(" ぁあぃいぅうぇえぉおかがきぎく") 365 | TEXT("ぐけげこごさざしじすずせぜそぞた") 366 | TEXT("だちぢっつづてでとどなにぬねのは") 367 | TEXT("ばぱひびぴふぶぷへべぺほぼぽまみ") 368 | TEXT("むめもゃやゅゆょよらりるれろゎわ") 369 | TEXT("ゐゑをん   ゝゞー。「」、・ "); 370 | 371 | #ifdef _UNICODE 372 | lpszDst[0] = acHiraganaTable[wCode]; 373 | 374 | return 1UL; 375 | #else 376 | lpszDst[0] = acHiraganaTable[wCode * 3U + 0U]; 377 | lpszDst[1] = acHiraganaTable[wCode * 3U + 1U]; 378 | lpszDst[2] = acHiraganaTable[wCode * 3U + 2U]; 379 | 380 | return 3UL; 381 | #endif 382 | } 383 | 384 | const DWORD PutKatakanaChar(TCHAR *lpszDst, const WORD wCode) 385 | { 386 | // カタカナ英数字文字コード変換 387 | static const TCHAR *acKatakanaTable = 388 | TEXT("                ") 389 | TEXT("                ") 390 | TEXT(" ァアィイゥウェエォオカガキギク") 391 | TEXT("グケゲコゴサザシジスズセゼソゾタ") 392 | TEXT("ダチヂッツヅテデトドナニヌネノハ") 393 | TEXT("バパヒビピフブプヘベペホボポマミ") 394 | TEXT("ムメモャヤュユョヨラリルレロヮワ") 395 | TEXT("ヰヱヲンヴヵヶヽヾー。「」、・ "); 396 | 397 | #ifdef _UNICODE 398 | lpszDst[0] = acKatakanaTable[wCode]; 399 | 400 | return 1UL; 401 | #else 402 | lpszDst[0] = acKatakanaTable[wCode * 3U + 0U]; 403 | lpszDst[1] = acKatakanaTable[wCode * 3U + 1U]; 404 | lpszDst[2] = acKatakanaTable[wCode * 3U + 2U]; 405 | 406 | return 3UL; 407 | #endif 408 | } 409 | 410 | const DWORD PutJisKatakanaChar(TCHAR *lpszDst, const WORD wCode) 411 | { 412 | // JISカタカナ文字コード変換 413 | static const TCHAR *acJisKatakanaTable = 414 | TEXT("                ") 415 | TEXT("                ") 416 | TEXT(" 。「」、・ヲァィゥェォャュョッ") 417 | TEXT("ーアイウエオカキクケコサシスセソ") 418 | TEXT("タチツテトナニヌネノハヒフヘホマ") 419 | TEXT("ミムメモヤユヨラリルレロワン゛゜") 420 | TEXT("                ") 421 | TEXT("                "); 422 | 423 | #ifdef _UNICODE 424 | lpszDst[0] = acJisKatakanaTable[wCode]; 425 | 426 | return 1UL; 427 | #else 428 | lpszDst[0] = acJisKatakanaTable[wCode * 3U + 0U]; 429 | lpszDst[1] = acJisKatakanaTable[wCode * 3U + 1U]; 430 | lpszDst[2] = acJisKatakanaTable[wCode * 3U + 2U]; 431 | 432 | return 3UL; 433 | #endif 434 | } 435 | 436 | const DWORD PutSymbolsChar(TCHAR *lpszDst, const WORD wCode) 437 | { 438 | // 追加シンボル文字コード変換(とりあえず必要そうなものだけ) 439 | static const TCHAR *aszSymbolsTable1[] = 440 | { 441 | _T("【HV】"), _T("【SD】"), _T("【P】"), _T("【W】"), _T("【MV】"), _T("【手】"), _T("【字】"), _T("【双】"), // 0x7A50 - 0x7A57 90/48 - 90/55 442 | _T("【デ】"), _T("【S】"), _T("【二】"), _T("【多】"), _T("【解】"), _T("【SS】"), _T("【B】"), _T("【N】"), // 0x7A58 - 0x7A5F 90/56 - 90/63 443 | _T("■"), _T("●"), _T("【天】"), _T("【交】"), _T("【映】"), _T("【無】"), _T("【料】"), _T("【年齢制限】"), // 0x7A60 - 0x7A67 90/64 - 90/71 444 | _T("【前】"), _T("【後】"), _T("【再】"), _T("【新】"), _T("【初】"), _T("【終】"), _T("【生】"), _T("【販】"), // 0x7A68 - 0x7A6F 90/72 - 90/79 445 | _T("【声】"), _T("【吹】"), _T("【PPV】"), _T("(秘)"), _T("ほか") // 0x7A70 - 0x7A74 90/80 - 90/84 446 | }; 447 | 448 | static const TCHAR *aszSymbolsTable2[] = 449 | { 450 | _T("→"), _T("←"), _T("↑"), _T("↓"), _T("●"), _T("○"), _T("年"), _T("月"), // 0x7C21 - 0x7C28 92/01 - 92/08 451 | _T("日"), _T("円"), _T("㎡"), _T("㎥"), _T("㎝"), _T("㎠"), _T("㎤"), _T("0."), // 0x7C29 - 0x7C30 92/09 - 92/16 452 | _T("1."), _T("2."), _T("3."), _T("4."), _T("5."), _T("6."), _T("7."), _T("8."), // 0x7C31 - 0x7C38 92/17 - 92/24 453 | _T("9."), _T("氏"), _T("副"), _T("元"), _T("故"), _T("前"), _T("[新]"), _T("0,"), // 0x7C39 - 0x7C40 92/25 - 92/32 454 | _T("1,"), _T("2,"), _T("3,"), _T("4,"), _T("5,"), _T("6,"), _T("7,"), _T("8,"), // 0x7C41 - 0x7C48 92/33 - 92/40 455 | _T("9,"), _T("(社)"), _T("(財)"), _T("(有)"), _T("(株)"), _T("(代)"), _T("(問)"), _T("▶"), // 0x7C49 - 0x7C50 92/41 - 92/48 456 | _T("◀"), _T("〖"), _T("〗"), _T("⟐"), _T("^2"), _T("^3"), _T("(CD)"), _T("(vn)"), // 0x7C51 - 0x7C58 92/49 - 92/56 457 | _T("(ob)"), _T("(cb)"), _T("(ce"), _T("mb)"), _T("(hp)"), _T("(br)"), _T("(p)"), _T("(s)"), // 0x7C59 - 0x7C60 92/57 - 92/64 458 | _T("(ms)"), _T("(t)"), _T("(bs)"), _T("(b)"), _T("(tb)"), _T("(tp)"), _T("(ds)"), _T("(ag)"), // 0x7C61 - 0x7C68 92/65 - 92/72 459 | _T("(eg)"), _T("(vo)"), _T("(fl)"), _T("(ke"), _T("y)"), _T("(sa"), _T("x)"), _T("(sy"), // 0x7C69 - 0x7C70 92/73 - 92/80 460 | _T("n)"), _T("(or"), _T("g)"), _T("(pe"), _T("r)"), _T("(R)"), _T("(C)"), _T("(箏)"), // 0x7C71 - 0x7C78 92/81 - 92/88 461 | _T("DJ"), _T("[演]"), _T("Fax") // 0x7C79 - 0x7C7B 92/89 - 92/91 462 | }; 463 | 464 | static const TCHAR *aszSymbolsTable3[] = 465 | { 466 | _T("㈪"), _T("㈫"), _T("㈬"), _T("㈭"), _T("㈮"), _T("㈯"), _T("㈰"), _T("㈷"), // 0x7D21 - 0x7D28 93/01 - 93/08 467 | _T("㍾"), _T("㍽"), _T("㍼"), _T("㍻"), _T("№"), _T("℡"), _T("〶"), _T("○"), // 0x7D29 - 0x7D30 93/09 - 93/16 468 | _T("〔本〕"), _T("〔三〕"), _T("〔二〕"), _T("〔安〕"), _T("〔点〕"), _T("〔打〕"), _T("〔盗〕"), _T("〔勝〕"), // 0x7D31 - 0x7D38 93/17 - 93/24 469 | _T("〔敗〕"), _T("〔S〕"), _T("[投]"), _T("[捕]"), _T("[一]"), _T("[二]"), _T("[三]"), _T("[遊]"), // 0x7D39 - 0x7D40 93/25 - 93/32 470 | _T("[左]"), _T("[中]"), _T("[右]"), _T("[指]"), _T("[走]"), _T("[打]"), _T("㍑"), _T("㎏"), // 0x7D41 - 0x7D48 93/33 - 93/40 471 | _T("㎐"), _T("ha"), _T("㎞"), _T("㎢"), _T("㍱"), _T("・"), _T("・"), _T("1/2"), // 0x7D49 - 0x7D50 93/41 - 93/48 472 | _T("0/3"), _T("1/3"), _T("2/3"), _T("1/4"), _T("3/4"), _T("1/5"), _T("2/5"), _T("3/5"), // 0x7D51 - 0x7D58 93/49 - 93/56 473 | _T("4/5"), _T("1/6"), _T("5/6"), _T("1/7"), _T("1/8"), _T("1/9"), _T("1/10"), _T("☀"), // 0x7D59 - 0x7D60 93/57 - 93/64 474 | _T("☁"), _T("☂"), _T("☃"), _T("☖"), _T("☗"), _T("▽"), _T("▼"), _T("♦"), // 0x7D61 - 0x7D68 93/65 - 93/72 475 | _T("♥"), _T("♣"), _T("♠"), _T("⌺"), _T("⦿"), _T("‼"), _T("⁉"), _T("(曇/晴)"), // 0x7D69 - 0x7D70 93/73 - 93/80 476 | _T("☔"), _T("(雨)"), _T("(雪)"), _T("(大雪)"), _T("⚡"), _T("(雷雨)"), _T(" "), _T("・"), // 0x7D71 - 0x7D78 93/81 - 93/88 477 | _T("・"), _T("♬"), _T("☎") // 0x7D79 - 0x7D7B 93/89 - 93/91 478 | }; 479 | 480 | static const TCHAR *aszSymbolsTable4[] = 481 | { 482 | _T("Ⅰ"), _T("Ⅱ"), _T("Ⅲ"), _T("Ⅳ"), _T("Ⅴ"), _T("Ⅵ"), _T("Ⅶ"), _T("Ⅷ"), // 0x7E21 - 0x7E28 94/01 - 94/08 483 | _T("Ⅸ"), _T("Ⅹ"), _T("Ⅺ"), _T("Ⅻ"), _T("⑰"), _T("⑱"), _T("⑲"), _T("⑳"), // 0x7E29 - 0x7E30 94/09 - 94/16 484 | _T("⑴"), _T("⑵"), _T("⑶"), _T("⑷"), _T("⑸"), _T("⑹"), _T("⑺"), _T("⑻"), // 0x7E31 - 0x7E38 94/17 - 94/24 485 | _T("⑼"), _T("⑽"), _T("⑾"), _T("⑿"), _T("㉑"), _T("㉒"), _T("㉓"), _T("㉔"), // 0x7E39 - 0x7E40 94/25 - 94/32 486 | _T("(A)"), _T("(B)"), _T("(C)"), _T("(D)"), _T("(E)"), _T("(F)"), _T("(G)"), _T("(H)"), // 0x7E41 - 0x7E48 94/33 - 94/40 487 | _T("(I)"), _T("(J)"), _T("(K)"), _T("(L)"), _T("(M)"), _T("(N)"), _T("(O)"), _T("(P)"), // 0x7E49 - 0x7E50 94/41 - 94/48 488 | _T("(Q)"), _T("(R)"), _T("(S)"), _T("(T)"), _T("(U)"), _T("(V)"), _T("(W)"), _T("(X)"), // 0x7E51 - 0x7E58 94/49 - 94/56 489 | _T("(Y)"), _T("(Z)"), _T("㉕"), _T("㉖"), _T("㉗"), _T("㉘"), _T("㉙"), _T("㉚"), // 0x7E59 - 0x7E60 94/57 - 94/64 490 | _T("①"), _T("②"), _T("③"), _T("④"), _T("⑤"), _T("⑥"), _T("⑦"), _T("⑧"), // 0x7E61 - 0x7E68 94/65 - 94/72 491 | _T("⑨"), _T("⑩"), _T("⑪"), _T("⑫"), _T("⑬"), _T("⑭"), _T("⑮"), _T("⑯"), // 0x7E69 - 0x7E70 94/73 - 94/80 492 | _T("❶"), _T("❷"), _T("❸"), _T("❹"), _T("❺"), _T("❻"), _T("❼"), _T("❽"), // 0x7E71 - 0x7E78 94/81 - 94/88 493 | _T("❾"), _T("❿"), _T("⓫"), _T("⓬"), _T("㉛") // 0x7E79 - 0x7E7D 94/89 - 94/93 494 | }; 495 | 496 | static const TCHAR *aszSymbolsTable5[] = 497 | { 498 | _T("㐂"), _T("亭"), _T("份"), _T("仿"), _T("侚"), _T("俉"), _T("傜"), _T("儞"), // 0x7521 - 0x7528 85/01 - 85/08 499 | _T("冼"), _T("㔟"), _T("匇"), _T("卡"), _T("卬"), _T("詹"), _T("吉"), _T("呍"), // 0x7529 - 0x7530 85/09 - 85/16 500 | _T("咖"), _T("咜"), _T("咩"), _T("唎"), _T("啊"), _T("噲"), _T("囤"), _T("圳"), // 0x7531 - 0x7538 85/17 - 85/24 501 | _T("圴"), _T("塚"), _T("墀"), _T("姤"), _T("娣"), _T("婕"), _T("寬"), _T("﨑"), // 0x7539 - 0x7540 85/25 - 85/32 502 | _T("㟢"), _T("庬"), _T("弴"), _T("彅"), _T("德"), _T("怗"), _T("恵"), _T("愰"), // 0x7541 - 0x7548 85/33 - 85/40 503 | _T("昤"), _T("曈"), _T("曙"), _T("曺"), _T("曻"), _T("桒"), _T("・"), _T("椑"), // 0x7549 - 0x7550 85/41 - 85/48 504 | _T("椻"), _T("橅"), _T("檑"), _T("櫛"), _T("・"), _T("・"), _T("・"), _T("毱"), // 0x7551 - 0x7558 85/49 - 85/56 505 | _T("泠"), _T("洮"), _T("海"), _T("涿"), _T("淊"), _T("淸"), _T("渚"), _T("潞"), // 0x7559 - 0x7560 85/57 - 85/64 506 | _T("濹"), _T("灤"), _T("・"), _T("・"), _T("煇"), _T("燁"), _T("爀"), _T("玟"), // 0x7561 - 0x7568 85/65 - 85/72 507 | _T("・"), _T("珉"), _T("珖"), _T("琛"), _T("琡"), _T("琢"), _T("琦"), _T("琪"), // 0x7569 - 0x7570 85/73 - 85/80 508 | _T("琬"), _T("琹"), _T("瑋"), _T("㻚"), _T("畵"), _T("疁"), _T("睲"), _T("䂓"), // 0x7571 - 0x7578 85/81 - 85/88 509 | _T("磈"), _T("磠"), _T("祇"), _T("禮"), _T("・"), _T("・") // 0x7579 - 0x757E 85/89 - 85/94 510 | }; 511 | 512 | static const TCHAR *aszSymbolsTable6[] = 513 | { 514 | _T("・"), _T("秚"), _T("稞"), _T("筿"), _T("簱"), _T("䉤"), _T("綋"), _T("羡"), // 0x7621 - 0x7628 86/01 - 86/08 515 | _T("脘"), _T("脺"), _T("・"), _T("芮"), _T("葛"), _T("蓜"), _T("蓬"), _T("蕙"), // 0x7629 - 0x7630 86/09 - 86/16 516 | _T("藎"), _T("蝕"), _T("蟬"), _T("蠋"), _T("裵"), _T("角"), _T("諶"), _T("跎"), // 0x7631 - 0x7638 86/17 - 86/24 517 | _T("辻"), _T("迶"), _T("郝"), _T("鄧"), _T("鄭"), _T("醲"), _T("鈳"), _T("銈"), // 0x7639 - 0x7640 86/25 - 86/32 518 | _T("錡"), _T("鍈"), _T("閒"), _T("雞"), _T("餃"), _T("饀"), _T("髙"), _T("鯖"), // 0x7641 - 0x7648 86/33 - 86/40 519 | _T("鷗"), _T("麴"), _T("麵") // 0x7649 - 0x764B 86/41 - 86/43 520 | }; 521 | 522 | // シンボルを変換する 523 | if((wCode >= 0x7A50U) && (wCode <= 0x7A74U)){ 524 | strcpy(lpszDst, aszSymbolsTable1[wCode - 0x7A50U]); 525 | } 526 | else if((wCode >= 0x7C21U) && (wCode <= 0x7C7BU)){ 527 | strcpy(lpszDst, aszSymbolsTable2[wCode - 0x7C21U]); 528 | } 529 | else if((wCode >= 0x7D21U) && (wCode <= 0x7D7BU)){ 530 | strcpy(lpszDst, aszSymbolsTable3[wCode - 0x7D21U]); 531 | } 532 | else if((wCode >= 0x7E21U) && (wCode <= 0x7E7DU)){ 533 | strcpy(lpszDst, aszSymbolsTable4[wCode - 0x7E21U]); 534 | } 535 | else if((wCode >= 0x7521U) && (wCode <= 0x757EU)){ 536 | strcpy(lpszDst, aszSymbolsTable5[wCode - 0x7521U]); 537 | } 538 | else if((wCode >= 0x7621U) && (wCode <= 0x764BU)){ 539 | strcpy(lpszDst, aszSymbolsTable6[wCode - 0x7621U]); 540 | } 541 | else{ 542 | strcpy(lpszDst, TEXT("・")); 543 | } 544 | 545 | return strlen(lpszDst); 546 | } 547 | 548 | void ProcessEscapeSeq(const BYTE byCode) 549 | { 550 | // エスケープシーケンス処理 551 | switch(m_byEscSeqCount){ 552 | // 1バイト目 553 | case 1U : 554 | switch(byCode){ 555 | // Invocation of code elements 556 | case 0x6EU : LockingShiftGL(2U); m_byEscSeqCount = 0U; return; // LS2 557 | case 0x6FU : LockingShiftGL(3U); m_byEscSeqCount = 0U; return; // LS3 558 | case 0x7EU : LockingShiftGR(1U); m_byEscSeqCount = 0U; return; // LS1R 559 | case 0x7DU : LockingShiftGR(2U); m_byEscSeqCount = 0U; return; // LS2R 560 | case 0x7CU : LockingShiftGR(3U); m_byEscSeqCount = 0U; return; // LS3R 561 | 562 | // Designation of graphic sets 563 | case 0x24U : 564 | case 0x28U : m_byEscSeqIndex = 0U; break; 565 | case 0x29U : m_byEscSeqIndex = 1U; break; 566 | case 0x2AU : m_byEscSeqIndex = 2U; break; 567 | case 0x2BU : m_byEscSeqIndex = 3U; break; 568 | default : m_byEscSeqCount = 0U; return; // エラー 569 | } 570 | break; 571 | 572 | // 2バイト目 573 | case 2U : 574 | if(DesignationGSET(m_byEscSeqIndex, byCode)){ 575 | m_byEscSeqCount = 0U; 576 | return; 577 | } 578 | 579 | switch(byCode){ 580 | case 0x20 : m_bIsEscSeqDrcs = true; break; 581 | case 0x28 : m_bIsEscSeqDrcs = true; m_byEscSeqIndex = 0U; break; 582 | case 0x29 : m_bIsEscSeqDrcs = false; m_byEscSeqIndex = 1U; break; 583 | case 0x2A : m_bIsEscSeqDrcs = false; m_byEscSeqIndex = 2U; break; 584 | case 0x2B : m_bIsEscSeqDrcs = false; m_byEscSeqIndex = 3U; break; 585 | default : m_byEscSeqCount = 0U; return; // エラー 586 | } 587 | break; 588 | 589 | // 3バイト目 590 | case 3U : 591 | if(!m_bIsEscSeqDrcs){ 592 | if(DesignationGSET(m_byEscSeqIndex, byCode)){ 593 | m_byEscSeqCount = 0U; 594 | return; 595 | } 596 | } 597 | else{ 598 | if(DesignationDRCS(m_byEscSeqIndex, byCode)){ 599 | m_byEscSeqCount = 0U; 600 | return; 601 | } 602 | } 603 | 604 | if(byCode == 0x20U){ 605 | m_bIsEscSeqDrcs = true; 606 | } 607 | else{ 608 | // エラー 609 | m_byEscSeqCount = 0U; 610 | return; 611 | } 612 | break; 613 | 614 | // 4バイト目 615 | case 4U : 616 | DesignationDRCS(m_byEscSeqIndex, byCode); 617 | m_byEscSeqCount = 0U; 618 | return; 619 | } 620 | 621 | m_byEscSeqCount++; 622 | } 623 | 624 | void LockingShiftGL(const BYTE byIndexG) 625 | { 626 | // LSx 627 | m_pLockingGL = &m_CodeG[(int)byIndexG]; 628 | } 629 | 630 | void LockingShiftGR(const BYTE byIndexG) 631 | { 632 | // LSxR 633 | m_pLockingGR = &m_CodeG[(int)byIndexG]; 634 | } 635 | 636 | void SingleShiftGL(const BYTE byIndexG) 637 | { 638 | // SSx 639 | m_pSingleGL = &m_CodeG[(int)byIndexG]; 640 | } 641 | 642 | const bool DesignationGSET(const BYTE byIndexG_arg, const BYTE byCode) 643 | { 644 | int byIndexG = (int)byIndexG_arg; 645 | 646 | // Gのグラフィックセットを割り当てる 647 | switch(byCode){ 648 | case 0x42U : m_CodeG[byIndexG] = CODE_KANJI; return true; // Kanji 649 | case 0x4AU : m_CodeG[byIndexG] = CODE_ALPHANUMERIC; return true; // Alphanumeric 650 | case 0x30U : m_CodeG[byIndexG] = CODE_HIRAGANA; return true; // Hiragana 651 | case 0x31U : m_CodeG[byIndexG] = CODE_KATAKANA; return true; // Katakana 652 | case 0x32U : m_CodeG[byIndexG] = CODE_MOSAIC_A; return true; // Mosaic A 653 | case 0x33U : m_CodeG[byIndexG] = CODE_MOSAIC_B; return true; // Mosaic B 654 | case 0x34U : m_CodeG[byIndexG] = CODE_MOSAIC_C; return true; // Mosaic C 655 | case 0x35U : m_CodeG[byIndexG] = CODE_MOSAIC_D; return true; // Mosaic D 656 | case 0x36U : m_CodeG[byIndexG] = CODE_PROP_ALPHANUMERIC; return true; // Proportional Alphanumeric 657 | case 0x37U : m_CodeG[byIndexG] = CODE_PROP_HIRAGANA; return true; // Proportional Hiragana 658 | case 0x38U : m_CodeG[byIndexG] = CODE_PROP_KATAKANA; return true; // Proportional Katakana 659 | case 0x49U : m_CodeG[byIndexG] = CODE_JIS_X0201_KATAKANA; return true; // JIS X 0201 Katakana 660 | case 0x39U : m_CodeG[byIndexG] = CODE_JIS_KANJI_PLANE_1; return true; // JIS compatible Kanji Plane 1 661 | case 0x3AU : m_CodeG[byIndexG] = CODE_JIS_KANJI_PLANE_2; return true; // JIS compatible Kanji Plane 2 662 | case 0x3BU : m_CodeG[byIndexG] = CODE_ADDITIONAL_SYMBOLS; return true; // Additional symbols 663 | default : return false; // 不明なグラフィックセット 664 | } 665 | } 666 | 667 | const bool DesignationDRCS(const BYTE byIndexG_arg, const BYTE byCode) 668 | { 669 | int byIndexG = (int)byIndexG_arg; 670 | 671 | // DRCSのグラフィックセットを割り当てる 672 | switch(byCode){ 673 | case 0x40U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-0 674 | case 0x41U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-1 675 | case 0x42U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-2 676 | case 0x43U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-3 677 | case 0x44U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-4 678 | case 0x45U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-5 679 | case 0x46U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-6 680 | case 0x47U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-7 681 | case 0x48U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-8 682 | case 0x49U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-9 683 | case 0x4AU : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-10 684 | case 0x4BU : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-11 685 | case 0x4CU : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-12 686 | case 0x4DU : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-13 687 | case 0x4EU : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-14 688 | case 0x4FU : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // DRCS-15 689 | case 0x70U : m_CodeG[byIndexG] = CODE_UNKNOWN; return true; // Macro 690 | default : return false; // 不明なグラフィックセット 691 | } 692 | } 693 | -------------------------------------------------------------------------------- /aribstr.h: -------------------------------------------------------------------------------- 1 | #ifndef ARIBSTR_H 2 | #define ARIBSTR_H 1 3 | 4 | #ifdef __cplusplus 5 | extern "C"{ 6 | #endif /* __cplusplus */ 7 | 8 | int AribToString(char *lpszDst, const char *pSrcData, const int dwSrcLen); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif /* __cplusplus */ 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cmake . 3 | -------------------------------------------------------------------------------- /bit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "bit.h" 6 | #include "ts_ctl.h" 7 | 8 | int parseBIThead(unsigned char *data, BIThead *h) { 9 | int boff = 0; 10 | 11 | memset(h, 0, sizeof(BIThead)); 12 | 13 | boff = 0; 14 | h->table_id = getBit(data, &boff, 8); 15 | h->section_syntax_indicator = getBit(data, &boff, 1); 16 | h->reserved_future_use = getBit(data, &boff, 1); 17 | h->reserved = getBit(data, &boff, 2); 18 | h->section_length = getBit(data, &boff, 12); 19 | h->original_network_id = getBit(data, &boff, 16); 20 | h->reserved = getBit(data, &boff, 2); 21 | h->version_number = getBit(data, &boff, 5); 22 | h->current_next_indicator = getBit(data, &boff, 1); 23 | h->section_number = getBit(data, &boff, 8); 24 | h->last_section_number = getBit(data, &boff, 8); 25 | h->reserved_future_use1 = getBit(data, &boff, 3); 26 | h->broadcast_view_propriety = getBit(data, &boff, 1); 27 | h->first_descriptors_length = getBit(data, &boff, 12); 28 | 29 | return boff/8; 30 | } 31 | 32 | int parseBITbody(unsigned char *data, BITbody *b) { 33 | int boff = 0; 34 | 35 | memset(b, 0, sizeof(BITbody)); 36 | 37 | b->transport_stream_id = getBit(data, &boff, 16); 38 | b->original_network_id = getBit(data, &boff, 16); 39 | b->service_id = getBit(data, &boff, 16); 40 | b->event_id = getBit(data, &boff, 16); 41 | b->reserved_future_use = getBit(data, &boff, 5); 42 | b->running_status = getBit(data, &boff, 3); 43 | 44 | return boff/8; 45 | } 46 | int parseSIParameterDescriptor(unsigned char *data, SIParameterDescriptor *d,int onid,int *maxcycle) { 47 | int boff = 0; 48 | int i,j,k,tag,alen,len,looplen,wk; 49 | HEITParam basiceitparam[5]; 50 | unsigned char *ptr; 51 | 52 | memset(d,0,sizeof(SIParameterDescriptor)); 53 | memset(basiceitparam,0,sizeof(HEITParam)*5); 54 | 55 | tag = getBit(data, &boff, 8); 56 | len = getBit(data, &boff, 8); 57 | 58 | d->parameter_version = getBit(data, &boff, 8); 59 | d->update_time = getBit(data, &boff, 16); 60 | 61 | looplen = len - 3; 62 | ptr = data + 5; 63 | i=0; 64 | while(looplen > 0) { 65 | boff = 0; 66 | d->sipt[i].table_id = getBit(ptr, &boff, 8); 67 | d->sipt[i].table_description_length = getBit(ptr, &boff, 8); 68 | switch(d->sipt[i].table_id) 69 | { 70 | #ifdef DEBUG 71 | case 0x40: //NIT 72 | wk = getBit(ptr, &boff, 8); 73 | printf("NIT CYCLE %d\n",wk); 74 | break; 75 | case 0xc4: //BIT 76 | wk = getBit(ptr, &boff, 8); 77 | printf("BIT CYCLE %d\n",wk); 78 | break; 79 | case 0xc3: //SDTT 80 | wk = getBit(ptr, &boff, 16); 81 | printf("SDTT CYCLE %d\n",wk); 82 | break; 83 | case 0xc8: //CDT 84 | wk = getBit(ptr, &boff, 16); 85 | printf("CDT CYCLE %d\n",wk); 86 | break; 87 | case 0x42: //SDT 88 | case 0x46: 89 | wk = getBit(ptr, &boff, 8); 90 | printf("SDT CYCLE %d\n",wk); 91 | break; 92 | case 0x4E: //HEIT(GR) Or (EIT p/f actual) 93 | case 0x4F: //BSCS (EIT p/f other) 94 | if (onid > 0x0010) { 95 | wk = getBit(ptr, &boff, 8); 96 | printf("HEIT CYCLE %d\n",wk); 97 | wk = getBit(ptr, &boff, 8); 98 | printf("MEIT CYCLE %d\n",wk); 99 | wk = getBit(ptr, &boff, 8); 100 | printf("LEIT CYCLE %d\n",wk); 101 | wk = getBit(ptr, &boff, 4); 102 | printf("MEIT EvNUM %d\n",wk); 103 | wk = getBit(ptr, &boff, 4); 104 | printf("LEIT EvNUM %d\n",wk); 105 | } 106 | else { 107 | wk = getBit(ptr, &boff, 8); 108 | printf("EITpf CYCLE %d\n",wk); 109 | } 110 | break; 111 | #endif 112 | case 0x50: //HEIT 113 | case 0x58: //EIText 114 | case 0x60: //EIT(sche) 115 | for(j=0;jsipt[i].table_description_length/6;j++) { 116 | basiceitparam[j].media_type = getBit(ptr, &boff, 2); 117 | basiceitparam[j].pattern = getBit(ptr, &boff, 2); 118 | basiceitparam[j].reserved = getBit(ptr, &boff, 4); 119 | basiceitparam[j].schedule_range = getBit(ptr, &boff, 4) *10 + getBit(ptr,&boff,4); 120 | basiceitparam[j].base_cycle = getBit(ptr, &boff, 4) * 100 + getBit(ptr,&boff,4) * 10 + getBit(ptr,&boff,4); 121 | if (basiceitparam[j].media_type == 0x01) { 122 | if (basiceitparam[j].base_cycle > *maxcycle) 123 | *maxcycle = basiceitparam[j].base_cycle; 124 | } 125 | #ifdef DEBUG 126 | printf("HEIT%x Basic media %d schedule_range %d base_cycle %d\n",d->sipt[i].table_id,basiceitparam[j].media_type ,basiceitparam[j].schedule_range,basiceitparam[j].base_cycle); 127 | #endif 128 | basiceitparam[j].reserved2 = getBit(ptr, &boff, 2); 129 | basiceitparam[j].cycle_group_count = getBit(ptr, &boff, 2); 130 | for(k=0;ksipt[i].table_description_length - 2; 138 | ptr += d->sipt[i].table_description_length + 2; 139 | i++; 140 | } 141 | return len + 2; 142 | } 143 | 144 | int parseBroadcasterLoop(unsigned char *data,BroadcasterLoop *l) 145 | { 146 | int boff = 0; 147 | 148 | memset(l,0,sizeof(BroadcasterLoop)); 149 | 150 | l->broadcaster_id = getBit(data,&boff,8); 151 | getBit(data,&boff,4); 152 | l->broadcaster_descriptors_length = getBit(data,&boff,12); 153 | 154 | return 3; 155 | 156 | } 157 | 158 | void dumpBIT(unsigned char *ptr, int *maxcycle) 159 | { 160 | 161 | BIThead bith; 162 | BITbody bitb; 163 | SIParameterDescriptor sipd; 164 | BroadcasterLoop bl; 165 | int rc ; 166 | unsigned char tag; 167 | static unsigned char version = 0xff; 168 | 169 | int len = 0; 170 | int loop_len = 0; 171 | int boff = 0; 172 | 173 | /* BIT */ 174 | len = parseBIThead(ptr, &bith); 175 | ptr += len; 176 | loop_len = bith.section_length - (len - 3 + 4); // 3は共通ヘッダ長 4はCRC 177 | 178 | if (bith.version_number == version) return; 179 | 180 | version = bith.version_number; 181 | 182 | len = parseSIParameterDescriptor(ptr,&sipd,bith.original_network_id, maxcycle); 183 | ptr += len; 184 | loop_len = loop_len - len; 185 | while(loop_len > 0) { 186 | int loop_len2; 187 | // broadcaster loop 188 | len = parseBroadcasterLoop(ptr,&bl); 189 | loop_len2 = bl.broadcaster_descriptors_length; 190 | ptr += len; 191 | loop_len -= len; 192 | while(loop_len2 > 0) { 193 | len = parseOTHERdesc(ptr,&tag); 194 | if (tag == 0xd7) 195 | parseSIParameterDescriptor(ptr,&sipd,bith.original_network_id, maxcycle); 196 | #ifdef DEBUG 197 | if (tag == 0xd8) { 198 | int boff1=0; 199 | char name[40]; 200 | memset(name,0,40); 201 | getStr(name, ptr+2, &boff1, len-2); 202 | printf("%s\n",name); 203 | } 204 | #endif 205 | ptr += len; 206 | loop_len2 -= len; 207 | loop_len -= len; 208 | } 209 | } 210 | 211 | return; 212 | } 213 | -------------------------------------------------------------------------------- /bit.h: -------------------------------------------------------------------------------- 1 | #ifndef BIT_H 2 | #define BIT_H 1 3 | 4 | #include 5 | #include 6 | 7 | #include "util.h" 8 | #include "ts_ctl.h" 9 | 10 | typedef struct _BIThead { 11 | char table_id; 12 | int section_syntax_indicator; 13 | int reserved_future_use; 14 | int reserved; 15 | int section_length; 16 | int original_network_id; 17 | int reserved1; 18 | int version_number; 19 | int current_next_indicator; 20 | int section_number; 21 | int last_section_number; 22 | int reserved_future_use1; 23 | int broadcast_view_propriety; 24 | int first_descriptors_length; 25 | } BIThead; 26 | 27 | typedef struct _BITbody { 28 | int transport_stream_id; 29 | int original_network_id; 30 | int service_id; 31 | int event_id; 32 | char reserved_future_use; 33 | char running_status; 34 | } BITbody; 35 | 36 | typedef struct _SIParameterTable { 37 | unsigned char table_id; 38 | unsigned char table_description_length; 39 | unsigned char table_description_byte[256]; 40 | }SIParameterTable; 41 | 42 | typedef struct _SIParameterDescriptor { 43 | unsigned char parameter_version; 44 | unsigned short update_time; 45 | SIParameterTable sipt[256]; 46 | }SIParameterDescriptor; 47 | 48 | typedef struct _HEITCycle { 49 | unsigned char num_of_segment; 50 | unsigned char cycle; 51 | }HEITCycle; 52 | 53 | typedef struct _HEITParam { 54 | unsigned char media_type; 55 | unsigned char pattern; 56 | unsigned char reserved; 57 | unsigned char schedule_range; 58 | unsigned char base_cycle; 59 | unsigned char reserved2; 60 | unsigned char cycle_group_count; 61 | HEITCycle cycle[4]; 62 | }HEITParam; 63 | 64 | typedef struct _BroadcasterLoop 65 | { 66 | unsigned char broadcaster_id; 67 | short broadcaster_descriptors_length; 68 | }BroadcasterLoop; 69 | 70 | #ifdef __cplusplus 71 | extern "C"{ 72 | #endif /* __cplusplus */ 73 | 74 | int parseBIThead(unsigned char *data, BIThead *h); 75 | int parseBITbody(unsigned char *data, BITbody *b); 76 | void dumpBIT(unsigned char *data, int *maxcycle); 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif /* __cplusplus */ 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | #cmakedefine ICONV_REQUIRES_CONST 1 5 | 6 | #ifdef ICONV_REQUIRES_CONST 7 | #define ICONV_CONST const 8 | #else 9 | #define ICONV_CONST 10 | #endif 11 | #endif 12 | 13 | #define VERSION "@serial@" 14 | -------------------------------------------------------------------------------- /eit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "eit.h" 6 | 7 | char *subtitle_cnv_str[] = { 8 | NULL 9 | }; 10 | int parseEIThead(unsigned char *data, EIThead *h) { 11 | int boff = 0; 12 | 13 | memset(h, 0, sizeof(EIThead)); 14 | 15 | h->table_id = getBit(data, &boff, 8); 16 | h->section_syntax_indicator = getBit(data, &boff, 1); 17 | h->reserved_future_use = getBit(data, &boff, 1); 18 | h->reserved1 = getBit(data, &boff, 2); 19 | h->section_length =getBit(data, &boff,12); 20 | h->service_id = getBit(data, &boff, 16); 21 | h->reserved2 = getBit(data, &boff, 2); 22 | h->version_number = getBit(data, &boff, 5); 23 | h->current_next_indicator = getBit(data, &boff, 1); 24 | h->section_number = getBit(data, &boff, 8); 25 | h->last_section_number = getBit(data, &boff, 8); 26 | h->transport_stream_id = getBit(data, &boff, 16); 27 | h->original_network_id = getBit(data, &boff, 16); 28 | h->segment_last_section_number = getBit(data, &boff, 8); 29 | h->last_table_id = getBit(data, &boff, 8); 30 | #ifdef DEBUG 31 | printf("EIT Table id 0x%x current %d\n",h->table_id,h->section_number); 32 | #endif 33 | 34 | return 14; 35 | } 36 | 37 | int parseEITbody(unsigned char *data, EITbody *b) 38 | { 39 | int boff = 0; 40 | int tnum; 41 | char buf[4]; 42 | 43 | memset(b, 0, sizeof(EITbody)); 44 | 45 | b->event_id = getBit(data, &boff, 16); 46 | 47 | memcpy(b->start_time, data + boff / 8, 5); 48 | /* b->start_time = getBit(data, &boff, 40); */ 49 | boff += 40; 50 | memcpy(b->duration, data + boff / 8, 3); 51 | /* b->duration = getBit(data, &boff, 24); */ 52 | boff += 24; 53 | b->running_status = getBit(data, &boff, 3); 54 | b->free_CA_mode = getBit(data, &boff, 1); 55 | b->descriptors_loop_length = getBit(data, &boff, 12); 56 | 57 | return 12; 58 | } 59 | 60 | /* 短形式イベント記述子 */ 61 | int parseSEVTdesc(unsigned char *data, SEVTdesc *desc) { 62 | int boff = 0; 63 | 64 | memset(desc, 0, sizeof(SEVTdesc)); 65 | 66 | desc->descriptor_tag = getBit(data, &boff, 8); 67 | if((desc->descriptor_tag & 0xFF) != 0x4D) { 68 | return -1; 69 | } 70 | desc->descriptor_length = getBit(data, &boff, 8); 71 | memcpy(desc->ISO_639_language_code, data + boff / 8, 3); 72 | /* desc->ISO_639_language_code = getBit(data, &boff, 24); */ 73 | boff += 24; 74 | desc->event_name_length = getBit(data, &boff, 8); 75 | getStr(desc->event_name, data, &boff, desc->event_name_length); 76 | desc->text_length = getBit(data, &boff, 8); 77 | getStr(desc->text, data, &boff, desc->text_length); 78 | #ifdef DEBUG 79 | printf("EventName [%s]\n",desc->event_name); 80 | printf("ShortDesc [%s]\n",desc->text); 81 | #endif 82 | 83 | return desc->descriptor_length + 2; 84 | } 85 | 86 | int parseComponentDesc(unsigned char *data, ComponentDesc *desc) { 87 | int boff = 0; 88 | 89 | memset(desc, 0, sizeof(ComponentDesc)); 90 | 91 | desc->descriptor_tag = getBit(data, &boff, 8); 92 | if((desc->descriptor_tag & 0xFF) != 0x50) { 93 | return -1; 94 | } 95 | desc->descriptor_length = getBit(data, &boff, 8); 96 | desc->reserved_future_use = getBit(data, &boff, 4); 97 | desc->stream_content = getBit(data, &boff, 4); 98 | desc->component_type = getBit(data, &boff, 8); 99 | desc->component_tag = getBit(data, &boff, 8); 100 | memcpy(desc->ISO_639_language_code, data + boff / 8, 3); 101 | boff += 24; 102 | memcpy(desc->content, data+(boff/8), desc->descriptor_length); 103 | //getStr(desc->content, data, &boff, desc->descriptor_length); 104 | #ifdef DEBUG 105 | switch(desc->component_type) { 106 | case 0x03: 107 | printf(" 映像480i(525i)、アスペクト比16:9 パンベクトルなし\n"); 108 | break; 109 | case 0xb3: 110 | printf(" 映像1080i(1125i)、アスペクト比16:9 パンベクトルなし\n"); 111 | break; 112 | default: 113 | printf(" 映像type 0x%x stream %x\n",desc->component_type,desc->stream_content); 114 | break; 115 | } 116 | #endif 117 | return desc->descriptor_length + 2; 118 | } 119 | 120 | int parseAudioComponentDesc(unsigned char *data,AudioComponentDesc *desc) { 121 | int boff = 0; 122 | 123 | memset(desc, 0, sizeof(AudioComponentDesc)); 124 | 125 | desc->descriptor_tag = getBit(data, &boff, 8); 126 | if((desc->descriptor_tag & 0xFF) != 0xC4) { 127 | return -1; 128 | } 129 | desc->descriptor_length = getBit(data, &boff, 8); 130 | desc->reserved_future_use = getBit(data, &boff, 4); 131 | desc->stream_content = getBit(data, &boff, 4); 132 | desc->component_type = getBit(data, &boff, 8); 133 | desc->component_tag = getBit(data, &boff, 8); 134 | desc->stream_type = getBit(data, &boff, 8); 135 | desc->simulcast_group_tag = getBit(data, &boff, 8); 136 | desc->ES_multi_lingual_flag = getBit(data, &boff, 1); 137 | desc->main_component_flag = getBit(data, &boff, 1); 138 | desc->quality_indicator = getBit(data, &boff, 2); 139 | desc->sampling_rate = getBit(data, &boff, 3); 140 | desc->reserved_future_use2 = getBit(data, &boff, 1); 141 | memcpy(desc->ISO_639_language_code, data + boff / 8, 3); 142 | boff += 24; 143 | if (desc->ES_multi_lingual_flag==0x01) { 144 | memcpy(desc->ISO_639_language_code2, data + boff / 8, 3); 145 | boff += 24; 146 | } 147 | if (desc->descriptor_length+2>(boff/8)) { 148 | getStr(desc->content, data, &boff, desc->descriptor_length+2-(boff/8)); 149 | } 150 | #ifdef DEBUG 151 | printf(" Audio %s%s",desc->main_component_flag?"":"副",desc->main_component_flag?"":desc->ISO_639_language_code); 152 | switch (desc->component_type) { 153 | case 0x01: 154 | printf("シングルモノ"); 155 | break; 156 | case 0x02: 157 | printf("デュアルモノ"); 158 | break; 159 | case 0x03: 160 | printf("ステレオ "); 161 | break; 162 | case 0x09: 163 | printf("3/2.1mode "); 164 | break; 165 | default: 166 | printf("Unknown "); 167 | break; 168 | } 169 | 170 | printf(" streamtype 0x%x samplerate 0x%x ",desc->component_type,desc->stream_type,desc->sampling_rate); 171 | if (desc->ES_multi_lingual_flag==0x01) { 172 | printf("二ヶ国語"); 173 | } 174 | printf("\n"); 175 | #endif 176 | return desc->descriptor_length + 2; 177 | 178 | } 179 | 180 | int parseContentDesc(unsigned char *data, ContentDesc *desc) { 181 | int boff = 0,i,j; 182 | 183 | memset(desc, 0, sizeof(ContentDesc)); 184 | 185 | desc->descriptor_tag = getBit(data, &boff, 8); 186 | if((desc->descriptor_tag & 0xFF) != 0x54) { 187 | return -1; 188 | } 189 | desc->descriptor_length = getBit(data, &boff, 8); 190 | desc->numcontent = desc->descriptor_length/2; 191 | for(i=0,j=0;inumcontent;i++) { 192 | desc->content[j] = getBit(data, &boff,8); 193 | desc->usernibble[j] = getBit(data, &boff, 8); 194 | if (desc->content[j] == 0xe0) { 195 | desc->attachinfo[desc->numattachinfo] = desc->usernibble[j]; 196 | desc->numattachinfo = desc->numattachinfo + 1; 197 | desc->content[j] = 0x00; 198 | desc->usernibble[j] = 0x00; 199 | continue; 200 | } 201 | j++; 202 | } 203 | desc->numcontent = desc->numcontent - desc->numattachinfo; 204 | #ifdef DEBUG 205 | unsigned char cn; 206 | printf(" Content 0x%02x\n",desc->content[0]); 207 | #endif 208 | return desc->descriptor_length + 2; 209 | } 210 | 211 | int parseSeriesDesc(unsigned char *data, SeriesDesc *desc) { 212 | int boff = 0; 213 | 214 | memset(desc, 0, sizeof(SeriesDesc)); 215 | 216 | desc->descriptor_tag = getBit(data, &boff, 8); 217 | if((desc->descriptor_tag & 0xFF) != 0xD5) { 218 | return -1; 219 | } 220 | desc->descriptor_length = getBit(data, &boff, 8); 221 | desc->series_id = getBit(data, &boff, 16); 222 | desc->repeat_label = getBit(data, &boff, 4); 223 | desc->program_pattern = getBit(data, &boff, 3); 224 | desc->expire_date_valid_flag = getBit(data, &boff, 1); 225 | 226 | desc->expire_date = getBit(data, &boff, 16); 227 | //memcpy(desc->expire_date, data + boff / 8, 2); 228 | //boff += 16; 229 | 230 | desc->episode_number = getBit(data, &boff, 12); 231 | desc->last_episode_number = getBit(data, &boff, 12); 232 | 233 | getStr(desc->series_name_char, data, &boff, desc->descriptor_length - 8); 234 | #ifdef DEBUG 235 | printf("SERI [%d] [%s]\n",desc->repeat_label,desc->series_name_char); 236 | #endif 237 | return desc->descriptor_length + 2; 238 | } 239 | 240 | /* 拡張形式イベント記述子 */ 241 | int parseEEVTDhead(unsigned char *data, EEVTDhead *desc) { 242 | int boff = 0; 243 | 244 | memset(desc, 0, sizeof(EEVTDhead)); 245 | 246 | desc->descriptor_tag = getBit(data, &boff, 8); 247 | if((desc->descriptor_tag & 0xFF) != 0x4E) { 248 | return -1; 249 | } 250 | desc->descriptor_length = getBit(data, &boff, 8); 251 | desc->descriptor_number = getBit(data, &boff, 4); 252 | desc->last_descriptor_number = getBit(data, &boff, 4); 253 | memcpy(desc->ISO_639_language_code, data + boff / 8, 3); 254 | /* desc->ISO_639_language_code = getBit(data, &boff, 24); */ 255 | boff += 24; 256 | 257 | desc->length_of_items = getBit(data, &boff, 8); 258 | 259 | return 7; 260 | } 261 | 262 | int parseEEVTDitem(unsigned char *data, EEVTDitem *desc,EIT_CONTROL *eitcur) { 263 | int boff = 0; 264 | 265 | memset(desc, 0, sizeof(EEVTDitem)); 266 | 267 | desc->item_description_length = getBit(data, &boff, 8); 268 | getStr(desc->item_description, data, &boff, desc->item_description_length); 269 | 270 | desc->item_length = getBit(data, &boff, 8); 271 | memcpy(desc->item, data + (boff / 8), desc->item_length); 272 | /* getStr(desc->item, data, &boff, desc->item_length); */ 273 | #ifdef DEBUG 274 | char *tmpbuf; 275 | int len,extlen; 276 | tmpbuf = malloc(1024*1024); 277 | getStr(tmpbuf,data,&boff,desc->item_length); 278 | printf("desc[%d][%s]\nitem[%d]strlenitem[%d]\n [%s]\n",desc->item_description_length,desc->item_description,desc->item_length,strlen(tmpbuf),tmpbuf); 279 | free(tmpbuf); 280 | #endif 281 | return desc->item_description_length + desc->item_length + 2; 282 | } 283 | 284 | int parseEEVTDtail(unsigned char *data, EEVTDtail *desc) { 285 | int boff = 0; 286 | 287 | memset(desc, 0, sizeof(EEVTDtail)); 288 | 289 | desc->text_length = getBit(data, &boff, 8); 290 | getStr(desc->text, data, &boff, desc->text_length); 291 | 292 | return desc->text_length + 1; 293 | } 294 | 295 | int checkEEVTDitem(EEVTDitem *save, EEVTDitem *new, int descriptor_number) { 296 | 297 | EEVTDitem swap; 298 | int boff = 0; 299 | 300 | if(new == NULL) { /* 最後のチェック*/ 301 | if(save->item_length != 0) { 302 | swap = *save; 303 | memset(save->item,0,MAXSECLEN); 304 | getStr(save->item, (unsigned char*)swap.item, &boff, swap.item_length); 305 | return 1; 306 | } else { 307 | return 0; 308 | } 309 | } 310 | 311 | if(new->item_description_length == 0) { 312 | /* 続き 保存 */ 313 | memcpy(save->item + save->item_length, new->item, new->item_length); 314 | save->item_length += new->item_length; 315 | return 0; 316 | } else { 317 | /* ブレーク。saveを印刷対象にする。saveをクリア? */ 318 | if(save->item_length != 0) { 319 | /* 退避済みがあり */ 320 | swap = *save; 321 | memset(save->item,0,MAXSECLEN); 322 | getStr(save->item, (unsigned char*)swap.item, &boff, swap.item_length); 323 | swap = *new; 324 | *new = *save; 325 | *save = swap; 326 | save->descriptor_number = descriptor_number; 327 | } else { 328 | *save = *new; 329 | save->descriptor_number = descriptor_number; 330 | return 0; 331 | } 332 | } 333 | 334 | return 1; 335 | } 336 | EIT_CONTROL *searcheit(EIT_CONTROL *top, int servid, int eventid) 337 | { 338 | EIT_CONTROL *cur ; 339 | cur = top ; 340 | 341 | while(cur != NULL){ 342 | if((cur->event_id == eventid) && (cur->servid == servid)){ 343 | return cur ; 344 | } 345 | 346 | cur = cur->next ; 347 | } 348 | return NULL ; 349 | } 350 | char *strstr_eucjp(const char *str, const char *search) 351 | { 352 | char *pos ; 353 | pos = (char *)str ; 354 | 355 | while (*pos != '\0') { 356 | if (*pos == *search) { 357 | if (strncmp(pos, search, strlen(search)) == 0) { 358 | return pos ; 359 | } 360 | } 361 | if ((unsigned char)*pos == 0x8Fu) { 362 | pos += 3 ; 363 | } else if ((unsigned char)*pos >= 0x80u) { 364 | pos += 2 ; 365 | } else { 366 | pos += 1 ; 367 | } 368 | } 369 | 370 | return NULL ; 371 | } 372 | void conv_title_subtitle(EIT_CONTROL *eitptr) 373 | { 374 | int lp = 0 ; 375 | // size_t addsize ; 376 | char *ptr ; 377 | char *ptr2 ; 378 | char *newsubtitle ; 379 | 380 | for(lp = 0 ; subtitle_cnv_str[lp] != NULL ; lp++){ 381 | ptr = strstr(eitptr->title, subtitle_cnv_str[lp]); 382 | if(ptr == NULL){ 383 | continue ; 384 | } 385 | // タイトルがなくならないように 386 | if(ptr == eitptr->title){ 387 | continue ; 388 | } 389 | ptr2 = ptr ; 390 | for( ; (unsigned char)*ptr2 == 0x20u ; ptr2++ ); 391 | for( ; (unsigned char)*ptr2 == 0xA1u && (unsigned char)*(ptr2+1) == 0xA1u ; ptr2 += 2); 392 | for( ; (unsigned char)*ptr2 == 0x20u ; ptr2++ ); 393 | newsubtitle = calloc(1, ((strlen(ptr2) + 3) + (strlen(eitptr->subtitle) + 1))); 394 | memcpy(newsubtitle, ptr2, strlen(ptr2)); 395 | // *(newsubtitle+strlen(ptr)) = ' '; 396 | strcat(newsubtitle, "▽"); 397 | *ptr = '\0'; 398 | strcat(newsubtitle, eitptr->subtitle); 399 | free(eitptr->subtitle); 400 | eitptr->subtitle = newsubtitle ; 401 | return ; 402 | } 403 | } 404 | void enqueue(EIT_CONTROL *top, EIT_CONTROL *eitptr) 405 | { 406 | EIT_CONTROL *cur ; 407 | cur = top ; 408 | time_t rc ; 409 | 410 | if(top->next == NULL){ 411 | top->next = eitptr ; 412 | eitptr->prev = top ; 413 | return ; 414 | } 415 | cur = top->next ; 416 | while(cur != NULL){ 417 | rc = cur->start_time - eitptr->start_time; 418 | if(rc == 0){ 419 | free(eitptr->title); 420 | free(eitptr->subtitle); 421 | free(eitptr); 422 | return ; 423 | } 424 | if(rc > 0){ 425 | if(cur->prev != 0){ 426 | cur->prev->next = eitptr ; 427 | eitptr->prev = cur->prev ; 428 | } 429 | else { 430 | top->next = eitptr; 431 | } 432 | cur->prev = eitptr ; 433 | eitptr->next = cur ; 434 | conv_title_subtitle(eitptr); 435 | return ; 436 | } 437 | if(cur->next == NULL){ 438 | cur->next = eitptr ; 439 | eitptr->prev = cur ; 440 | conv_title_subtitle(eitptr); 441 | return ; 442 | } 443 | cur = cur->next ; 444 | } 445 | return ; 446 | 447 | } 448 | 449 | int dumpEIT2(unsigned char *ptr, SVT_CONTROL *svttop,EITCHECK *chk) 450 | { 451 | EIThead eith; 452 | EITbody eitb; 453 | SEVTdesc sevtd; 454 | 455 | EEVTDhead eevthead; 456 | EEVTDitem eevtitem; 457 | EEVTDtail eevttail; 458 | 459 | EEVTDitem save_eevtitem; 460 | 461 | EIT_CONTROL *cur ; 462 | EIT_CONTROL *eittop; 463 | SVT_CONTROL *svtcur; 464 | 465 | int len = 0; 466 | int loop_len = 0; 467 | int loop_blen = 0; 468 | int loop_elen = 0; 469 | 470 | /* EIT */ 471 | len = parseEIThead(ptr, &eith); 472 | /* EIT ヘッダから、どのSVTのEIT情報か特定する */ 473 | svtcur=svttop->next; 474 | eittop = NULL; 475 | while(svtcur) { 476 | if ((eith.transport_stream_id == svtcur->transport_stream_id) && 477 | (eith.original_network_id == svtcur->original_network_id) && 478 | (eith.service_id == svtcur->event_id)) { 479 | eittop = svtcur->eit; 480 | break; 481 | } 482 | svtcur = svtcur->next; 483 | } 484 | if (eittop == NULL) { 485 | #ifdef DEBUG 486 | printf("Not Match %x %x %x \n",eith.transport_stream_id,eith.original_network_id,eith.service_id); 487 | #endif 488 | // 別のストリーム?? 489 | return EIT_SDTNOTFOUND; 490 | } 491 | #ifdef DEBUG 492 | printf("SV 0x%x Table [0x%x] \n",eith.service_id,eith.table_id); 493 | #endif 494 | ptr += len; 495 | loop_len = eith.section_length - (len - 3 + 4); // 3は共通ヘッダ長 4はCRC 496 | while(loop_len > 0) { 497 | /* 連続する拡張イベントは、漢字コードが泣き別れして 498 | 分割されるようだ。連続かどうかは、item_description_lengthが 499 | 設定されているかどうかで判断できるようだ。 */ 500 | memset(&save_eevtitem, 0, sizeof(EEVTDitem)); 501 | 502 | len = parseEITbody(ptr, &eitb); 503 | if (eith.table_id == 0x4e) { 504 | if (chk) { 505 | if (eith.section_number < 2) { 506 | if ((svtcur->cnev[eith.section_number].event_id != (short)eitb.event_id) || 507 | (memcmp(svtcur->cnev[eith.section_number].start_time,eitb.start_time,5)!=0) || 508 | (memcmp(svtcur->cnev[eith.section_number].duration,eitb.duration,3)!=0) || 509 | (eitb.running_status == 0x02)) { 510 | // Event Changed 511 | printf("sv[%d]%s [%d] [%s][%d] state %x\n",svtcur->event_id,eith.section_number?"next":"curr", 512 | eitb.event_id, 513 | strTime(getStartTime(eitb.start_time),"%Y/%m/%d %H:%M:%S"), 514 | getDurationSec(eitb.duration), 515 | eitb.running_status); 516 | svtcur->cnev[eith.section_number].event_id = (short)eitb.event_id; 517 | 518 | memcpy(svtcur->cnev[eith.section_number].start_time,eitb.start_time,5); 519 | memcpy(svtcur->cnev[eith.section_number].duration,eitb.duration,3); 520 | if ((svtcur->event_id == chk->svid) && (eitb.event_id == chk->evid)) { 521 | if (eith.section_number == 0) { 522 | // 現在のイベント=チェックイベント(すでに始まっている) 523 | return EIT_CHECKOK; 524 | } 525 | if (eith.section_number == 1) { // 次のイベントとマッチ 526 | if (chk->starttime > 0) { //check 527 | printf("%d\n",getStartTime(eitb.start_time)-chk->starttime); 528 | return EIT_CHECKOK; 529 | } 530 | } 531 | } 532 | if (chk->starttime > 0 && svtcur->event_id == chk->svid && svtcur->cnev[1].event_id>0) { 533 | //次のイベント情報を取得してもマッチしていない 534 | return EIT_CHECKNG; 535 | } 536 | } //event changed 537 | else { 538 | if ((svtcur->event_id == chk->svid) && (svtcur->cnev[1].event_id == chk->evid)) { 539 | if (chk->tdttime > 0) { // TDT時刻とチェックして35秒以内ならOK 540 | if (getStartTime(svtcur->cnev[1].start_time) < chk->tdttime + 35) { 541 | return EIT_CHECKOK; 542 | } 543 | } 544 | } 545 | } 546 | } 547 | } 548 | return EIT_OK; 549 | } 550 | cur = searcheit(eittop, eith.service_id, eitb.event_id); 551 | 552 | ptr += len; 553 | loop_len -= len; 554 | 555 | loop_blen = eitb.descriptors_loop_length; 556 | loop_len -= loop_blen; 557 | while(loop_blen > 0) { 558 | unsigned char desctag; 559 | int sboff,ix; 560 | ContentDesc contentDesc; 561 | ComponentDesc componentDesc; 562 | AudioComponentDesc audioComponentDesc; 563 | sboff=0; 564 | desctag = getBit(ptr,&sboff,8); 565 | #ifdef DEBUG 566 | printf("Event 0x%x desctag [0x%x] savelen %d\n",eitb.event_id,desctag,save_eevtitem.item_length); 567 | #endif 568 | switch (desctag) { 569 | case 0x50: 570 | len = parseComponentDesc(ptr, &componentDesc); 571 | if (cur) cur->video = componentDesc.component_type; 572 | break; 573 | case 0xC4: 574 | len = parseAudioComponentDesc(ptr, &audioComponentDesc); 575 | if (cur) { // XXX 2track only 576 | if (audioComponentDesc.main_component_flag) ix = 0; //主音声 577 | else ix = 1; 578 | if (cur->audiodesc[ix].audiotype == 0) { 579 | cur->audiodesc[ix].audiotype = audioComponentDesc.component_type; 580 | strncpy(cur->audiodesc[ix].langcode,audioComponentDesc.ISO_639_language_code,3); 581 | if (audioComponentDesc.ES_multi_lingual_flag) { 582 | strcat(cur->audiodesc[ix].langcode,"_"); 583 | strncat(cur->audiodesc[ix].langcode,audioComponentDesc.ISO_639_language_code2,3); 584 | } 585 | if (audioComponentDesc.content) 586 | cur->audiodesc[ix].audiodesc = strdup(audioComponentDesc.content); 587 | } 588 | } 589 | break; 590 | case 0x4D: 591 | len = parseSEVTdesc(ptr, &sevtd); 592 | if(len > 0) { 593 | if(cur == NULL){ 594 | cur = calloc(1, sizeof(EIT_CONTROL)); 595 | cur->event_id = eitb.event_id ; 596 | cur->servid = eith.service_id ; 597 | cur->title = calloc(1, (strlen(sevtd.event_name) + 1)); 598 | memcpy(cur->title, sevtd.event_name, strlen(sevtd.event_name)); 599 | cur->subtitle = calloc(1, (strlen(sevtd.text) + 1)); 600 | memcpy(cur->subtitle, sevtd.text, strlen(sevtd.text)); 601 | cur->table_id = eith.table_id ; 602 | cur->freeCA = eitb.free_CA_mode; 603 | cur->duration = getDurationSec(eitb.duration); 604 | cur->start_time = getStartTime(eitb.start_time); 605 | enqueue(eittop, cur); 606 | if ((eith.table_id >= 0x50) && (!svtcur->haveeitschedule)) { 607 | svtcur->haveeitschedule=1; 608 | #ifdef DEBUG 609 | printf("HAVE SCH\n"); 610 | #endif 611 | } 612 | } 613 | } 614 | break; 615 | case 0x4E: 616 | len = parseEEVTDhead(ptr, &eevthead); 617 | if(len > 0) { 618 | ptr += len; 619 | loop_blen -= len; 620 | 621 | loop_elen = eevthead.length_of_items; 622 | loop_len -= loop_elen; 623 | 624 | if (cur && cur->eitextcnt == 0 && eevthead.last_descriptor_number > 0) { 625 | cur->eitextcnt = eevthead.last_descriptor_number+1; 626 | cur->eitextdesc = calloc(cur->eitextcnt,sizeof(EITEXTDESC)); 627 | } 628 | while(loop_elen > 0) { 629 | len = parseEEVTDitem(ptr, &eevtitem,cur); 630 | 631 | ptr += len; 632 | loop_elen -= len; 633 | loop_blen -= len; 634 | 635 | if(checkEEVTDitem(&save_eevtitem, &eevtitem, 636 | eevthead.descriptor_number)) { 637 | if (cur && cur->eitextdesc) { 638 | if (!cur->eitextdesc[eevtitem.descriptor_number].item_description) 639 | cur->eitextdesc[eevtitem.descriptor_number].item_description = strdup(eevtitem.item_description); 640 | if (!cur->eitextdesc[eevtitem.descriptor_number].item) 641 | cur->eitextdesc[eevtitem.descriptor_number].item = strdup(eevtitem.item); 642 | 643 | } 644 | 645 | } 646 | } 647 | 648 | len = parseEEVTDtail(ptr, &eevttail); 649 | 650 | } 651 | break; 652 | 653 | case 0x54: 654 | len = parseContentDesc(ptr, &contentDesc); 655 | if (len > 0 && cur) { 656 | cur->numcontent = contentDesc.numcontent; 657 | memcpy(cur->content,contentDesc.content,7); 658 | memcpy(cur->usernibble,contentDesc.usernibble,7); 659 | cur->numattachinfo = contentDesc.numattachinfo; 660 | memcpy(cur->attachinfo,contentDesc.attachinfo,7); 661 | } 662 | default: 663 | len = parseOTHERdesc(ptr,NULL); 664 | break; 665 | } 666 | 667 | ptr += len; 668 | loop_blen -= len; 669 | } 670 | /* 最後のブレークチェック */ 671 | 672 | if(checkEEVTDitem(&save_eevtitem, NULL, 0)) { 673 | if (cur && cur->eitextdesc) { 674 | if (!cur->eitextdesc[save_eevtitem.descriptor_number].item_description) 675 | cur->eitextdesc[save_eevtitem.descriptor_number].item_description = strdup(save_eevtitem.item_description); 676 | if (!cur->eitextdesc[save_eevtitem.descriptor_number].item) 677 | cur->eitextdesc[save_eevtitem.descriptor_number].item = strdup(save_eevtitem.item); 678 | } 679 | 680 | } 681 | } 682 | 683 | return EIT_OK; 684 | } 685 | 686 | -------------------------------------------------------------------------------- /eit.h: -------------------------------------------------------------------------------- 1 | #ifndef EIT_H 2 | #define EIT_H 1 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.h" 9 | #include "ts_ctl.h" 10 | 11 | typedef struct _EIThead { 12 | char table_id; 13 | int section_syntax_indicator; 14 | int reserved_future_use; 15 | int reserved1; 16 | int section_length; 17 | int service_id; 18 | int reserved2; 19 | int version_number; 20 | int current_next_indicator; 21 | int section_number; 22 | int last_section_number; 23 | int transport_stream_id; 24 | int original_network_id; 25 | int segment_last_section_number; 26 | int last_table_id; 27 | } EIThead; 28 | 29 | typedef struct _EITbody { 30 | int event_id; 31 | unsigned char start_time[5]; 32 | unsigned char duration[3]; 33 | int running_status; 34 | int free_CA_mode; 35 | int descriptors_loop_length; 36 | } EITbody; 37 | 38 | typedef struct _SEVTdesc { 39 | int descriptor_tag; 40 | int descriptor_length; 41 | char ISO_639_language_code[3]; 42 | int event_name_length; 43 | char event_name[MAXSECLEN]; 44 | int text_length; 45 | char text[MAXSECLEN]; 46 | } SEVTdesc; 47 | 48 | typedef struct _ComponentDesc { 49 | int descriptor_tag; 50 | int descriptor_length; 51 | char reserved_future_use; 52 | char stream_content; 53 | int component_type; 54 | int component_tag; 55 | char ISO_639_language_code[3]; 56 | char content[MAXSECLEN]; 57 | } ComponentDesc; 58 | 59 | 60 | typedef struct _AudioComponentDesc { 61 | int descriptor_tag; 62 | int descriptor_length; 63 | char reserved_future_use; 64 | char stream_content; 65 | int component_type; 66 | int component_tag; 67 | int stream_type; 68 | char simulcast_group_tag; 69 | char ES_multi_lingual_flag; 70 | char main_component_flag; 71 | char quality_indicator; 72 | char sampling_rate; 73 | char reserved_future_use2; 74 | char ISO_639_language_code[3]; 75 | char ISO_639_language_code2[3]; 76 | char content[MAXSECLEN]; 77 | }AudioComponentDesc; 78 | 79 | 80 | typedef struct _ContentDesc { 81 | int descriptor_tag; 82 | int descriptor_length; 83 | unsigned char numcontent; 84 | unsigned char content[7]; 85 | unsigned char usernibble[7]; 86 | unsigned char numattachinfo; 87 | unsigned char attachinfo[7]; 88 | } ContentDesc; 89 | 90 | typedef struct _SeriesDesc { 91 | int descriptor_tag; 92 | int descriptor_length; 93 | int series_id; 94 | int repeat_label; 95 | int program_pattern; 96 | int expire_date_valid_flag; 97 | int expire_date; 98 | int episode_number; 99 | int last_episode_number; 100 | char series_name_char[MAXSECLEN]; 101 | } SeriesDesc; 102 | 103 | typedef struct _EEVTDhead { 104 | int descriptor_tag; 105 | int descriptor_length; 106 | int descriptor_number; 107 | int last_descriptor_number; 108 | char ISO_639_language_code[3]; 109 | int length_of_items; 110 | } EEVTDhead; 111 | 112 | typedef struct _EEVTDitem { 113 | int item_description_length; 114 | char item_description[MAXSECLEN]; 115 | int item_length; 116 | char item[MAXSECLEN]; 117 | /* 退避用 */ 118 | int descriptor_number; 119 | } EEVTDitem; 120 | 121 | typedef struct _EEVTDtail { 122 | int text_length; 123 | char text[MAXSECLEN]; 124 | } EEVTDtail; 125 | 126 | #ifdef __cplusplus 127 | extern "C"{ 128 | #endif /* __cplusplus */ 129 | 130 | int parseEIThead(unsigned char *data, EIThead *h); 131 | int parseEITbody(unsigned char *data, EITbody *b); 132 | int parseSEVTdesc(unsigned char *data, SEVTdesc *desc) ; 133 | 134 | int parseContentDesc(unsigned char *data, ContentDesc *desc); 135 | int parseSeriesDesc(unsigned char *data, SeriesDesc *desc); 136 | 137 | int parseEEVTDhead(unsigned char *data, EEVTDhead *desc) ; 138 | int parseEEVTDitem(unsigned char *data, EEVTDitem *desc, EIT_CONTROL *eitcur) ; 139 | int parseEEVTDtail(unsigned char *data, EEVTDtail *desc) ; 140 | 141 | int dumpEIT2(unsigned char *data, SVT_CONTROL *svt,EITCHECK *chk); 142 | 143 | 144 | #ifdef __cplusplus 145 | } 146 | #endif /* __cplusplus */ 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /epgdump.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "ts.h" 13 | #include "sdt.h" 14 | #include "eit.h" 15 | #include "nit.h" 16 | #include "tdt.h" 17 | #include "bit.h" 18 | #include "ts_ctl.h" 19 | 20 | #include "xmldata.c" 21 | 22 | 23 | SVT_CONTROL *svttop = NULL; 24 | #define SECCOUNT 10 25 | char title[1024]; 26 | char subtitle[1024]; 27 | char Category[1024]; 28 | char *extdesc; 29 | char ServiceName[1024]; 30 | 31 | static EITCHECK chk; 32 | 33 | void signalhandler() 34 | { 35 | SVT_CONTROL *svtcur; 36 | EIT_CONTROL *eitcur; 37 | int cnt,extcnt,rest; 38 | svtcur=svttop->next; 39 | while(svtcur != NULL) { 40 | if (!svtcur->haveeitschedule) { 41 | svtcur = svtcur->next; 42 | continue; 43 | } 44 | cnt=extcnt=rest=0; 45 | eitcur = svtcur->eit; 46 | while(eitcur != NULL){ 47 | if(!eitcur->servid){ 48 | eitcur = eitcur->next ; 49 | continue ; 50 | } 51 | cnt++; 52 | if (eitcur->eitextcnt>0) { 53 | extcnt++; 54 | } 55 | eitcur = eitcur->next; 56 | } 57 | if (chk.starttime > 0 && chk.maxcycle > 0) { 58 | rest = chk.starttime + chk.maxcycle - chk.tdttime; 59 | } 60 | fprintf(stderr,"sid %d programs %d(ext %d) rest %d(%d)\n",svtcur->event_id,cnt,extcnt,rest,chk.maxcycle); 61 | svtcur = svtcur->next; 62 | } 63 | } 64 | void xmlspecialchars(char *str) 65 | { 66 | strrep(str, "&", "&"); 67 | strrep(str, "'", "'"); 68 | strrep(str, "\"", """); 69 | strrep(str, "<", "<"); 70 | strrep(str, ">", ">"); 71 | } 72 | 73 | 74 | int CheckEIT(FILE *infile,SECcache *secs,int count,EITCHECK *echk) 75 | { 76 | SVT_CONTROL *svtcur ; 77 | int pid,ret,sdtflg; 78 | SECcache *bsecs; 79 | 80 | svttop = calloc(1, sizeof(SVT_CONTROL)); 81 | sdtflg = 0; 82 | 83 | while((bsecs = readTS(infile, secs, count)) != NULL) { 84 | pid = bsecs->pid & 0xFF; 85 | switch (pid) { 86 | case 0x11: //SDT 87 | if (sdtflg==0) { 88 | sdtflg=1; 89 | dumpSDT(bsecs->buf, svttop); 90 | svtcur = svttop->next; 91 | while(svtcur) { 92 | if (svtcur->eit == NULL) { 93 | svtcur->eit = calloc(1, sizeof(EIT_CONTROL)); 94 | } 95 | svtcur = svtcur->next; 96 | } 97 | } 98 | break; 99 | case 0x12: // EIT 100 | ret = dumpEIT2(bsecs->buf,svttop,echk); 101 | if (ret == EIT_CHECKOK || ret == EIT_CHECKNG) { //CHECK COMPLETE 102 | return ret - EIT_CHECKOK; 103 | } 104 | if (ret == EIT_SDTNOTFOUND) sdtflg=0; 105 | break; 106 | case 0x14: // TDT 107 | dumpTDT(bsecs->buf,echk); 108 | break; 109 | case 0x13: // RST 110 | printf("RST\n"); 111 | break; 112 | } 113 | if (echk->waitend < time(NULL)) {return 1;} 114 | } 115 | return 1; // EOF 116 | } 117 | int GetSDTEITInfo(FILE *infile,SECcache *secs,int count) 118 | { 119 | SVT_CONTROL *svtcur ; 120 | int pid; 121 | SECcache *bsecs; 122 | int sdtflg,numsdt; 123 | int ret; 124 | 125 | memset(&chk,0,sizeof(EITCHECK)); 126 | sdtflg=numsdt=0; 127 | 128 | chk.waitend = time(NULL) + 10; 129 | 130 | #ifdef DEBUGSIGNAL 131 | signal(SIGINFO,signalhandler); 132 | #endif 133 | 134 | /* 135 | XXX BITが取れないときはどうするか? 136 | */ 137 | 138 | while((bsecs = readTS(infile, secs, count)) != NULL) { 139 | pid = bsecs->pid & 0xFF; 140 | switch (pid) { 141 | case 0x10: //NIT 142 | dumpNIT(bsecs->buf,svttop); 143 | break; 144 | 145 | case 0x11: // SDT 146 | if (sdtflg==0) { 147 | sdtflg=1; 148 | dumpSDT(bsecs->buf, svttop); 149 | 150 | numsdt=0; 151 | svtcur = svttop->next; 152 | while(svtcur) { 153 | if (svtcur->eit == NULL) { 154 | svtcur->eit = calloc(1, sizeof(EIT_CONTROL)); 155 | } 156 | svtcur = svtcur->next; 157 | numsdt++; 158 | } 159 | 160 | } 161 | break; 162 | case 0x12: // EIT 163 | case 0x26: // EIT(地デジ) 164 | case 0x27: // EIT(地デジ) 165 | if (sdtflg) { 166 | ret = dumpEIT2(bsecs->buf,svttop,NULL); 167 | if (ret == 0) sdtflg = 0; 168 | } 169 | break; 170 | case 0x14: // TDT 171 | dumpTDT(bsecs->buf,&chk); 172 | if (chk.starttime > 0 && chk.maxcycle > 0) { 173 | if (chk.starttime + chk.maxcycle < chk.tdttime) { 174 | #ifdef DEBUG 175 | printf("start %s cycle %d\n",strTime(chk.starttime,"%Y/%m/%d %H:%M:%S"),chk.maxcycle); 176 | printf("tdt %s\n",strTime(chk.tdttime,"%Y/%m/%d %H:%M:%S")); 177 | #endif 178 | return 0; 179 | } 180 | } 181 | break; 182 | case 0x23: // SDTT 183 | // ret = dumpSDTT(bsecs->buf); 184 | break; 185 | case 0x13: // RST 186 | printf("RST\n"); 187 | break; 188 | case 0x24: // BIT 189 | if (chk.maxcycle == 0 && chk.tdttime > 0) { 190 | dumpBIT(bsecs->buf,&chk.maxcycle); 191 | chk.starttime = chk.tdttime; 192 | /* XXX 環境変数等でオーバーライド可能にしたい 193 | * 周期どおりで基本番組情報は十分だが、拡張のほうは 194 | * なかなか埋まらない 195 | */ 196 | chk.maxcycle = chk.maxcycle * 1.6; 197 | } 198 | break; 199 | } 200 | if (numsdt == 0 && time(NULL) > chk.waitend) return 1; 201 | } 202 | return 0; 203 | } 204 | void dumpChannel(FILE *outfile) 205 | { 206 | SVT_CONTROL *svtcur ; 207 | char *p; 208 | svtcur=svttop->next; 209 | while(svtcur != NULL) { 210 | if (!svtcur->haveeitschedule) { 211 | svtcur = svtcur->next; 212 | continue; 213 | } 214 | fprintf(outfile,"%d,", svtcur->event_id); 215 | p = getBSCSGR(svtcur); 216 | switch (p[0]) { 217 | case 'G': 218 | fprintf(outfile,"%s,",p); 219 | break; 220 | case 'B': 221 | fprintf(outfile,"%s%d_%d,",p, 222 | getTSID2TP(svtcur->transport_stream_id), 223 | getTSID2SLOT(svtcur->transport_stream_id)); 224 | break; 225 | case 'C': 226 | fprintf(outfile,"%s%d,",p, 227 | getTSID2TP(svtcur->transport_stream_id)); 228 | break; 229 | } 230 | fprintf(outfile,"%s\n",svtcur->servicename); 231 | svtcur = svtcur->next; 232 | } 233 | } 234 | void dumpCSV(FILE *outfile) 235 | { 236 | SVT_CONTROL *svtcur ; 237 | EIT_CONTROL *eitcur ; 238 | int i; 239 | 240 | svtcur=svttop->next; 241 | while(svtcur != NULL) { 242 | if (!svtcur->haveeitschedule) { 243 | svtcur = svtcur->next; 244 | continue; 245 | } 246 | eitcur = svtcur->eit; 247 | while(eitcur != NULL){ 248 | if(!eitcur->servid){ 249 | eitcur = eitcur->next ; 250 | continue ; 251 | } 252 | fprintf(outfile,"%s,0x%x,0x%x,%d,%d,",svtcur->servicename,svtcur->original_network_id,svtcur->transport_stream_id,svtcur->event_id,svtcur->frequency); 253 | fprintf(outfile,"0x%x,0x%x,%s,%s,%s,%d,\"%s\",\"%s\",", 254 | eitcur->event_id, 255 | eitcur->content[0], 256 | ContentCatList[(eitcur->content[0] >> 4)].japanese, 257 | ContentMiddleCatList[eitcur->content[0]].japanese, 258 | strTime(eitcur->start_time,"%Y/%m/%d %H:%M:%S"), 259 | eitcur->duration, 260 | eitcur->title, 261 | eitcur->subtitle); 262 | if (eitcur->eitextcnt>0) { 263 | fprintf(outfile,"\""); 264 | for(i=0;ieitextcnt;i++) { 265 | if (eitcur->eitextdesc[i].item_description) 266 | fprintf(outfile, "%s\n",eitcur->eitextdesc[i].item_description); 267 | if (eitcur->eitextdesc[i].item) 268 | fprintf(outfile, "%s\n", eitcur->eitextdesc[i].item); 269 | } 270 | fprintf(outfile,"\","); 271 | } 272 | else { 273 | fprintf(outfile,","); 274 | } 275 | fprintf(outfile,"0x%x,%s,", 276 | (unsigned char)eitcur->video, 277 | getVideoComponentDescStr((unsigned char)eitcur->video)); 278 | for(i=0;i<2;i++) { 279 | if (eitcur->audiodesc[i].audiotype > 0) { 280 | fprintf(outfile,"0x%x-%s-%s-%s,", 281 | eitcur->audiodesc[i].audiotype, 282 | getAudioComponentDescStr(eitcur->audiodesc[i].audiotype), 283 | eitcur->audiodesc[i].langcode, 284 | eitcur->audiodesc[i].audiodesc?eitcur->audiodesc[i].audiodesc:""); 285 | } 286 | else { 287 | fprintf(outfile,","); 288 | } 289 | } 290 | fprintf(outfile,"%s\n",eitcur->freeCA?"有料":""); 291 | eitcur=eitcur->next; 292 | } 293 | svtcur=svtcur->next; 294 | } 295 | return ; 296 | } 297 | void dumpXML(FILE *outfile) 298 | { 299 | SVT_CONTROL *svtcur ; 300 | EIT_CONTROL *eitcur ; 301 | time_t l_time ; 302 | time_t end_time ; 303 | struct tm tl ; 304 | struct tm *endtl ; 305 | char cendtime[32]; 306 | char cstarttime[32]; 307 | int i; 308 | 309 | 310 | fprintf(outfile, "\n"); 311 | fprintf(outfile, "\n\n"); 312 | fprintf(outfile, "\n"); 313 | 314 | svtcur=svttop->next; 315 | while(svtcur != NULL) { 316 | if (!svtcur->haveeitschedule) { 317 | svtcur = svtcur->next; 318 | continue; 319 | } 320 | memset(ServiceName, '\0', sizeof(ServiceName)); 321 | strcpy(ServiceName, svtcur->servicename); 322 | xmlspecialchars(ServiceName); 323 | 324 | fprintf(outfile, " \n",getBSCSGR(svtcur), svtcur->event_id,svtcur->transport_stream_id,svtcur->original_network_id,svtcur->event_id); 325 | fprintf(outfile, " %s\n", ServiceName); 326 | if (svtcur->original_network_id < 0x0010) { 327 | fprintf(outfile, " \n"); 328 | if (svtcur->frequency > 0) { 329 | fprintf(outfile, " %d\n",svtcur->frequency); 330 | } 331 | fprintf(outfile, " %s%d\n",getTSID2BSCS(svtcur->transport_stream_id),getTSID2TP(svtcur->transport_stream_id)); 332 | fprintf(outfile, " %d\n",getTSID2SLOT(svtcur->transport_stream_id)); 333 | fprintf(outfile, " \n"); 334 | } 335 | fprintf(outfile, " \n"); 336 | svtcur=svtcur->next; 337 | } 338 | svtcur=svttop->next; 339 | while(svtcur != NULL) { 340 | if (!svtcur->haveeitschedule) { 341 | svtcur = svtcur->next; 342 | continue; 343 | } 344 | eitcur = svtcur->eit; 345 | while(eitcur != NULL){ 346 | if(!eitcur->servid){ 347 | eitcur = eitcur->next ; 348 | continue ; 349 | } 350 | memset(title, '\0', sizeof(title)); 351 | if (eitcur->title) strcpy(title, eitcur->title); 352 | xmlspecialchars(title); 353 | 354 | memset(subtitle, '\0', sizeof(subtitle)); 355 | if (eitcur->subtitle) strcpy(subtitle, eitcur->subtitle); 356 | xmlspecialchars(subtitle); 357 | 358 | memset(cendtime, '\0', sizeof(cendtime)); 359 | memset(cstarttime, '\0', sizeof(cstarttime)); 360 | strcpy(cendtime, strTime(eitcur->start_time + eitcur->duration , "%Y%m%d%H%M%S")); 361 | strcpy(cstarttime, strTime(eitcur->start_time, "%Y%m%d%H%M%S")); 362 | 363 | fprintf(outfile, " event_id); 365 | fprintf(outfile, "event_id=\"%d\" duration=\"%d\">\n", 366 | eitcur->event_id,eitcur->duration); 367 | 368 | fprintf(outfile, " %s\n", title); 369 | 370 | fprintf(outfile, " %s\n", subtitle); 371 | 372 | for(i=0;inumcontent;i++) { 373 | fprintf(outfile, " %s\n",getContentStr(eitcur->content[i],eitcur->usernibble[i],CONTENT_LARGE,CONTENT_LANG_JA) ); 374 | 375 | fprintf(outfile, " %s\n", getContentStr(eitcur->content[i],eitcur->usernibble[i],CONTENT_LARGE,CONTENT_LANG_EN)); 376 | 377 | fprintf(outfile, " %s\n",getContentStr(eitcur->content[i],eitcur->usernibble[i],CONTENT_MIDDLE,CONTENT_LANG_JA)); 378 | fprintf(outfile, " %s\n",getContentStr(eitcur->content[i],eitcur->usernibble[i],CONTENT_MIDDLE,CONTENT_LANG_EN)); 379 | } 380 | for(i=0;inumattachinfo;i++) { 381 | fprintf(outfile, " %s\n",getAttachInfo(eitcur->attachinfo[i])); 382 | } 383 | fprintf(outfile, " %d\n",eitcur->freeCA); 384 | 385 | fprintf(outfile, " \n"); 389 | for(i=0;i<2;i++) { 390 | if (eitcur->audiodesc[i].audiotype > 0) { 391 | fprintf(outfile, " \n"); 396 | } 397 | } 398 | if (eitcur->eitextcnt>0) { 399 | char *p; 400 | fprintf(outfile, " \n"); 401 | for(i=0;ieitextcnt;i++) { 402 | if (eitcur->eitextdesc[i].item_description) { 403 | p = realloc(eitcur->eitextdesc[i].item_description,(strlen(eitcur->eitextdesc[i].item_description)*2)+1); 404 | xmlspecialchars(p); 405 | fprintf(outfile, " %s\n",p); 406 | free(p); 407 | } 408 | if (eitcur->eitextdesc[i].item) { 409 | p = realloc(eitcur->eitextdesc[i].item,(strlen(eitcur->eitextdesc[i].item)*2)+1); 410 | xmlspecialchars(p); 411 | fprintf(outfile, " %s\n",p); 412 | free(p); 413 | } 414 | } 415 | fprintf(outfile, " \n"); 416 | } 417 | 418 | fprintf(outfile, " \n"); 419 | eitcur=eitcur->next; 420 | } 421 | svtcur=svtcur->next; 422 | } 423 | fprintf(outfile, "\n"); 424 | } 425 | 426 | void dumpJSON(FILE *outfile) 427 | { 428 | SVT_CONTROL *svtcur ; 429 | EIT_CONTROL *eitcur ; 430 | int i; 431 | char *svtcanma=""; 432 | char *eitcanma; 433 | char *eitextcanma; 434 | 435 | fprintf(outfile,"["); 436 | svtcur=svttop->next; 437 | while(svtcur != NULL) { 438 | if (!svtcur->haveeitschedule) { 439 | svtcur = svtcur->next; 440 | continue; 441 | } 442 | fprintf(outfile,"%s{",svtcanma); 443 | fprintf(outfile,"\"id\":\"%s_%d\",",getBSCSGR(svtcur),svtcur->event_id); 444 | fprintf(outfile,"\"transport_stream_id\":%d,",svtcur->transport_stream_id); 445 | fprintf(outfile,"\"original_network_id\":%d,",svtcur->original_network_id); 446 | fprintf(outfile,"\"service_id\":%d,",svtcur->event_id); 447 | fprintf(outfile,"\"name\":\"%s\",",svtcur->servicename); 448 | if (svtcur->original_network_id < 0x0010) { 449 | fprintf(outfile,"\"satelliteinfo\":{"); 450 | fprintf(outfile,"\"TP\":\"%s%d\",",getTSID2BSCS(svtcur->transport_stream_id),getTSID2TP(svtcur->transport_stream_id)); 451 | fprintf(outfile,"\"SLOT\":%d},",getTSID2SLOT(svtcur->transport_stream_id)); 452 | } 453 | eitcur = svtcur->eit; 454 | fprintf(outfile,"\"programs\":["); 455 | eitcanma=""; 456 | while(eitcur != NULL){ 457 | if(!eitcur->servid){ 458 | eitcur = eitcur->next ; 459 | continue ; 460 | } 461 | fprintf(outfile,"%s{",eitcanma); 462 | fprintf(outfile,"\"channel\":\"%s_%d\",",getBSCSGR(svtcur),svtcur->event_id); 463 | memset(title, '\0', sizeof(title)); 464 | if (eitcur->title) strcpy(title, eitcur->title); 465 | strrep(title, "\"", "\\\""); 466 | fprintf(outfile,"\"title\":\"%s\",",title); 467 | memset(subtitle, '\0', sizeof(subtitle)); 468 | if (eitcur->subtitle) strcpy(subtitle, eitcur->subtitle); 469 | strrep(subtitle, "\"", "\\\""); 470 | fprintf(outfile,"\"detail\":\"%s\",",subtitle); 471 | 472 | fprintf(outfile,"\"extdetail\":["); 473 | eitextcanma=""; 474 | for(i=0;ieitextcnt;i++) { 475 | if (eitcur->eitextdesc[i].item_description && eitcur->eitextdesc[i].item) { 476 | strcpy(subtitle, eitcur->eitextdesc[i].item_description); 477 | strrep(subtitle, "\"", "\\\""); 478 | fprintf(outfile,"%s{\"item_description\":\"%s\",",eitextcanma,subtitle); 479 | memset(subtitle, '\0', sizeof(subtitle)); 480 | strcpy(subtitle, eitcur->eitextdesc[i].item); 481 | strrep(subtitle, "\"", "\\\""); 482 | fprintf(outfile,"\"item\":\"%s\"}",subtitle); 483 | eitextcanma=","; 484 | } 485 | } 486 | fprintf(outfile,"],"); 487 | 488 | fprintf(outfile,"\"start\":%d000,",eitcur->start_time); 489 | fprintf(outfile,"\"end\":%d000,",eitcur->start_time+eitcur->duration); 490 | fprintf(outfile,"\"duration\":%d,",eitcur->duration); 491 | 492 | eitextcanma=""; 493 | fprintf(outfile,"\"category\":["); 494 | for(i=0;inumcontent;i++) { 495 | fprintf(outfile,"%s{",eitextcanma); 496 | fprintf(outfile,"\"large\": { \"ja_JP\" : \"%s\", \"en\" : \"%s\"},",getContentStr(eitcur->content[i],eitcur->usernibble[i],CONTENT_LARGE,CONTENT_LANG_JA),getContentStr(eitcur->content[i],eitcur->usernibble[i],CONTENT_LARGE,CONTENT_LANG_EN)); 497 | fprintf(outfile,"\"middle\": { \"ja_JP\" : \"%s\", \"en\" : \"%s\"}}",getContentStr(eitcur->content[i],eitcur->usernibble[i],CONTENT_MIDDLE,CONTENT_LANG_JA),getContentStr(eitcur->content[i],eitcur->usernibble[i],CONTENT_MIDDLE,CONTENT_LANG_EN)); 498 | eitextcanma=","; 499 | } 500 | fprintf(outfile,"],"); 501 | 502 | eitextcanma=""; 503 | fprintf(outfile,"\"attachinfo\":["); 504 | for(i=0;inumattachinfo;i++) { 505 | fprintf(outfile,"%s\"%s\"",eitextcanma,getAttachInfo(eitcur->attachinfo[i])); 506 | eitextcanma=","; 507 | } 508 | fprintf(outfile,"],"); 509 | 510 | fprintf(outfile,"\"video\":{"); 511 | fprintf(outfile,"\"resolution\":\"%s\",",getVideoResolution(eitcur->video)); 512 | fprintf(outfile,"\"aspect\":\"%s\"},",getVideoAspect(eitcur->video)); 513 | 514 | eitextcanma=""; 515 | fprintf(outfile,"\"audio\":["); 516 | for(i=0;i<2;i++) { 517 | if (eitcur->audiodesc[i].audiotype > 0) { 518 | fprintf(outfile,"%s{\"type\":\"%s\",",eitextcanma,getAudioComponentDescStr(eitcur->audiodesc[i].audiotype)); 519 | fprintf(outfile,"\"langcode\":\"%s\",", eitcur->audiodesc[i].langcode); 520 | fprintf(outfile,"\"extdesc\":\"%s\"}", eitcur->audiodesc[i].audiodesc?eitcur->audiodesc[i].audiodesc:""); 521 | eitextcanma=","; 522 | } 523 | } 524 | fprintf(outfile,"],"); 525 | 526 | fprintf(outfile,"\"freeCA\":%s,",eitcur->freeCA?"true":"false"); 527 | fprintf(outfile,"\"event_id\":%d",eitcur->event_id); 528 | eitcur = eitcur->next ; 529 | fprintf(outfile,"}"); 530 | eitcanma=","; 531 | } 532 | fprintf(outfile,"]"); 533 | svtcur = svtcur->next; 534 | fprintf(outfile,"}"); 535 | svtcanma=","; 536 | } 537 | fprintf(outfile,"]"); 538 | } 539 | 540 | 541 | int main(int argc, char *argv[]) 542 | { 543 | FILE *infile = stdin; 544 | FILE *outfile = stdout; 545 | char *file,*fileout; 546 | int inclose = 0; 547 | int outclose = 0; 548 | int ret; 549 | SECcache secs[SECCOUNT]; 550 | 551 | 552 | /* 興味のあるpidを指定 */ 553 | memset(secs, 0, sizeof(SECcache) * SECCOUNT); 554 | secs[0].pid = 0x11; /* SDT */ 555 | secs[1].pid = 0x12; /* EIT */ 556 | secs[2].pid = 0x14; /* TDT */ 557 | secs[3].pid = 0x23; /* SDTT */ 558 | secs[4].pid = 0x28; /* SDTT */ 559 | secs[5].pid = 0x10; /* NIT */ 560 | secs[6].pid = 0x13; /* RST */ 561 | secs[7].pid = 0x24; /* BIT */ 562 | 563 | file = NULL; 564 | fileout= NULL; 565 | if (argc > 2) { 566 | if (argc == 3) { 567 | file = argv[1]; 568 | fileout = argv[2]; 569 | } 570 | else { 571 | file = argv[2]; 572 | fileout = argv[3]; 573 | } 574 | if(strcmp(file, "-")) { 575 | infile = fopen(file, "r"); 576 | inclose = 1; 577 | } 578 | if(infile == NULL){ 579 | fprintf(stderr, "Can't open file: %s\n", file); 580 | return 1; 581 | } 582 | } 583 | 584 | if(argc == 6 && ((strcmp(argv[1], "check") == 0)||(strcmp(argv[1],"wait"))==0)){ 585 | memset(&chk,0,sizeof(EITCHECK)); 586 | chk.svid = atoi(argv[3]); 587 | chk.evid = atoi(argv[4]); 588 | if (strcmp(argv[1],"check")==0) { 589 | chk.starttime = str2timet(argv[5]); 590 | chk.waitend = time(NULL) + 11; 591 | } 592 | else { 593 | chk.waitend = time(NULL) + atoi(argv[5]); 594 | } 595 | ret = CheckEIT(infile,secs, SECCOUNT,&chk); 596 | if (inclose) fclose(infile); 597 | // 0..ok 1..fail 598 | return ret; 599 | } 600 | 601 | if(argc >= 3){ 602 | if(strcmp(fileout, "-")) { 603 | outfile = fopen(fileout, "w+"); 604 | outclose = 1; 605 | } 606 | }else{ 607 | fprintf(stdout, "Usage : %s \n", argv[0]); 608 | fprintf(stdout, "Usage : %s csv \n", argv[0]); 609 | fprintf(stdout, "Usage : %s json \n", argv[0]); 610 | fprintf(stdout, "Usage : %s check \n", argv[0]); 611 | fprintf(stdout, "Usage : %s wait \n", argv[0]); 612 | fprintf(stdout, " csv csv output mode\n"); 613 | fprintf(stdout, " json json output mode\n"); 614 | fprintf(stdout, " check check event\n"); 615 | fprintf(stdout, " wait wait event\n"); 616 | fprintf(stdout, "VERSION : %s\n",VERSION); 617 | return 0; 618 | } 619 | 620 | svttop = calloc(1, sizeof(SVT_CONTROL)); 621 | 622 | ret = GetSDTEITInfo(infile, secs, SECCOUNT); 623 | 624 | if(strcmp(argv[1], "csv") == 0){ 625 | dumpCSV(outfile); 626 | }else if (strcmp(argv[1], "csvc") == 0){ 627 | dumpChannel(outfile); 628 | }else if (strcmp(argv[1], "json") == 0){ 629 | dumpJSON(outfile); 630 | }else{ 631 | dumpXML(outfile); 632 | } 633 | if(inclose) fclose(infile); 634 | if(outclose) fclose(outfile); 635 | 636 | return ret; 637 | } 638 | -------------------------------------------------------------------------------- /nit.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Piro77/epgdump/590b6154fb436b56c683a29a9b7b832b8b33e0bf/nit.c -------------------------------------------------------------------------------- /nit.h: -------------------------------------------------------------------------------- 1 | #ifndef NIT_H 2 | #define NIT_H 1 3 | 4 | #include 5 | #include 6 | 7 | #include "util.h" 8 | #include "ts_ctl.h" 9 | 10 | typedef struct _NIThead { 11 | char table_id; 12 | int section_syntax_indicator; 13 | int reserved_future_use1; 14 | int reserved1; 15 | int section_length; 16 | int network_id; 17 | int reserved2; 18 | int version_number; 19 | int current_next_indicator; 20 | int section_number; 21 | int last_section_number; 22 | int reserved_future_use2; 23 | int network_descriptors_length; 24 | char network_descriptor[MAXSECLEN]; 25 | int reserved_future_use3; 26 | int transport_stream_loop_length; 27 | 28 | } NIThead; 29 | 30 | typedef struct _NITbody { 31 | int transport_stream_id; 32 | int original_network_id; 33 | int reserved_future_use; 34 | int transport_descriptors_loop_length; 35 | char transport_descriptor[MAXSECLEN]; 36 | } NITbody; 37 | 38 | typedef struct _ServiceListDescriptor { 39 | short service_id; 40 | char service_type; 41 | }ServiceListDescriptor; 42 | 43 | typedef struct _ServiceList { 44 | int length; 45 | ServiceListDescriptor sld[256]; 46 | }ServiceList; 47 | 48 | typedef struct _SatelliteDeliverySystemDescriptor { 49 | int frequency; 50 | int orbital_position; 51 | unsigned char west_east_flag; 52 | unsigned char polarisation; 53 | unsigned char modulation; 54 | int symbol_rate; 55 | unsigned char FEC_inner; 56 | }SatelliteDeliverySystemDescriptor; 57 | 58 | typedef struct _TerrestrialDeliverySystemDescriptor { 59 | short area_code; 60 | unsigned char guard_interval; 61 | unsigned char transmission_mode; 62 | unsigned short frequency; 63 | }TerrestrialDeliverySystemDescriptor; 64 | 65 | typedef struct _TSInformationTransmissionType { 66 | unsigned char transmission_type_info; 67 | unsigned char num_of_service; 68 | unsigned short service_id[256]; 69 | }TSInformationTransmissionType; 70 | 71 | typedef struct _TSInformationDescriptor { 72 | unsigned char remote_control_key_id; 73 | unsigned char length_of_ts_name; 74 | unsigned char transmission_type_count; 75 | char ts_name_char[MAXSECLEN]; 76 | TSInformationTransmissionType tstype[4]; 77 | }TSInformationDescriptor; 78 | 79 | #ifdef __cplusplus 80 | extern "C"{ 81 | #endif /* __cplusplus */ 82 | 83 | int parseNIThead(unsigned char *data, NIThead *h); 84 | int parseNITbody(unsigned char *data, NITbody *b); 85 | void dumpNIT(unsigned char *data, SVT_CONTROL *top); 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif /* __cplusplus */ 90 | 91 | #endif 92 | 93 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | epgdump改良版 2 | 3 | https://github.com/Piro77/epgdump 4 | 5 | ビルドにcmakeが必要 6 | cmake .(もしくは./autogen.sh) 7 | make 8 | 9 | 使い方 10 | epgdump cs.ts cs.xml 11 | epgdump bs.ts bs.xml 12 | epgdump gr32.ts gr32.xml 13 | 14 | 引数1・TSファイル名 15 | 引数2・出力XMLファイル名(−で標準出力) 16 | 17 | TSを読み込んでxmlを出力します。xmlの形式は独自なので他のepgdump 18 | の置き換えには使えません。 19 | 以前の第一引数だったCS,BS,GRの区別は廃止されTSファイルから識別します。 20 | GRはチャンネル番号の変わりにリモコンIDを出力します。 21 | 22 | 例:CS_101 23 | BS_237 24 | GR2_23122 25 | 26 | epgdump csv gr32.ts gr32.csv 27 | epgdump json gr32.ts gr32.json 28 | 29 | 引数1・csv|csvc|json 30 | 引数2・TSファイル名 31 | 引数3・出力ファイル名(−で標準出力) 32 | 33 | XMLの代わりにCSV形式、JSON形式で出力します。 34 | csvcの場合チャンネル一覧をcsvで出力します。 35 | 引数が3つあり、第一引数が有効でない場合xml出力として動作します。 36 | 37 | epgdump check /dev/ptx0.t0 21234 4384 2012-07-15T11:30:00 38 | 39 | 引数1・check(固定) 40 | 引数2・デバイス名 41 | 引数3・EITサービスID 42 | 引数4・EITイベントID 43 | 引数5・EITイベント開始時刻 44 | 45 | デバイスからTSを読み出し、引数で渡されたサービスIDのイベントIDが 46 | EITの次のイベントにあるかチェックします。 47 | 次のイベントにある場合0で終了します。 48 | 次のイベントにない場合1で終了します。 49 | EIT情報が取得できない場合等含めて最長約10秒で終了します。 50 | 第5引数とイベント開始時刻差を秒数で標準出力に出力します。 51 | 52 | epgdump wait /dev/ptx0.t0 21234 4384 3600 53 | 54 | 引数1・wait(固定) 55 | 引数2・デバイス名 56 | 引数3・EITサービスID 57 | 引数4・EITイベントID 58 | 引数5・最大待ち秒数 59 | 60 | デバイスからTSを読み出し、引数で渡されたサービスIDのイベントIDの開始を待機します。 61 | 待機が成功した場合0で終了します。(該当イベントの開始、または約30秒で開始) 62 | 待機が失敗した場合1で終了します 63 | 64 | 65 | 変更点 66 | ・2chのスレのパッチ取り込み 67 | ・読み込み時にseekしないようにした 68 | ・取得EIT情報の増加 69 | ・BS/CSのテーブル不要化 70 | ・スケジュール対応コード(イベント待ち) 71 | ・xml出力変更 72 | ・番組カテゴリの複数対応 73 | ・JSON形式出力 74 | ・EITの送出周期が経過したらEXIT 75 | 76 | 77 | TODO 78 | ・ジャンルコードの取り込み 79 | ・TOTによる時刻合わせ 80 | ・CSV廃止? 81 | ・XMLもうちょっと何とかしたいけど 82 | 83 | 以下オリジナルreadme 84 | ------ 85 | xmltv-epg 86 | 87 | MPEG-TSに含まれるepgをxmlで出力するプログラムです。 88 | ◆N/E9PqspSk氏がrecfriio Solaris版(http://2sen.dip.jp/cgi-bin/friioup/source/up0737.zip)に含まれるepgdumpを 89 | Linux版を改造したものをベースにxmltv用のxmlファイルを作成します。 90 | 91 | また、タイトル内に含まれる 92 | " 第"や、" 「"、" #"、"("、"「"、をサブタイトルとして扱う様に修正しています。 93 | 例: 94 | 95 | タイトルが、 96 | 明日のよいち!「あの時君はワルかった」 97 | の場合 98 | 明日のよいち!がタイトルに、「あの時君はワルかった」がサブタイトルに追加されます。 99 | 100 | サブタイトルとして扱うものを増やす場合は、eit.cにあるsubtitle_cnv_strに追加してください。 101 | 102 | 使用方法は以下の通りです。 103 | 104 | Usage : ./epgdump /BS 105 | Usage : ./epgdump 106 | ontvcode チャンネル識別子。****.ontvjapan.com など 107 | /BS BSモード。一つのTSからBS全局のデータを読み込みます。 108 | /CS CSモード。一つのTSから複数局のデータを読み込みます。 109 | 110 | makeするとepgdumpがビルドされます。 111 | 112 | epgdumpライセンス(Solaris版より引用): 113 | >epgdumpに関しては、BonTest Ver.1.40からそのままソースを持ってきている部分も 114 | >あるため、そのライセンスに従いします。 115 | >BonTestのReadme.txtより 116 | >> 117 | >>3.ライセンスについて 118 | >>  ・本パッケージに含まれる全てのソースコード、バイナリについて著作権は一切主張しません。 119 | >>  ・オリジナルのまま又は改変し、各自のソフトウェアに自由に添付、組み込むことができます。 120 | >>  ・但しGPLに従うことを要求しますのでこれらを行う場合はソースコードの開示が必須となります。 121 | >>  ・このとき本ソフトウェアの著作権表示を行うかどうかは任意です。 122 | >>  ・本ソフトウェアはFAAD2のライブラリ版バイナリを使用しています。 123 | >> 124 | >>   "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" 125 | >> 126 | >>  ・ビルドに必要な環境 127 | >>   - Microsoft Visual Studio 2005 以上 ※MFCが必要 128 | >>   - Microsoft Windows SDK v6.0 以上  ※DirectShow基底クラスのコンパイル済みライブラリが必要 129 | >>   - Microsoft DirectX 9.0 SDK 以上 130 | 131 | Special Thanks: 132 | ・Solaris版開発者の方 133 | ・拡張ツール中の人 134 | ・◆N/E9PqspSk氏 135 | ・ARIB(資料の無料ダウンロードに対して) 136 | 137 | 動作確認環境: 138 | Debian GNU/Linux sid 139 | Linux 2.6.27.19 SMP PREEMPT x86_64 140 | 141 | tomy ◆CfWlfzSGyg 142 | -------------------------------------------------------------------------------- /sdt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "sdt.h" 6 | #include "ts_ctl.h" 7 | 8 | int parseSDThead(unsigned char *data, SDThead *h) { 9 | int boff = 0; 10 | 11 | memset(h, 0, sizeof(SDThead)); 12 | 13 | boff = 0; 14 | h->table_id = getBit(data, &boff, 8); 15 | h->section_syntax_indicator = getBit(data, &boff, 1); 16 | h->reserved_future_use1 = getBit(data, &boff, 1); 17 | h->reserved1 = getBit(data, &boff, 2); 18 | h->section_length = getBit(data, &boff, 12); 19 | h->transport_stream_id = getBit(data, &boff, 16); 20 | h->reserved2 = getBit(data, &boff, 2); 21 | h->version_number = getBit(data, &boff, 5); 22 | h->current_next_indicator = getBit(data, &boff, 1); 23 | h->section_number = getBit(data, &boff, 8); 24 | h->last_section_number = getBit(data, &boff, 8); 25 | h->original_network_id = getBit(data, &boff, 16); 26 | h->reserved_future_use2 = getBit(data, &boff, 8); 27 | 28 | return 11; 29 | } 30 | 31 | int parseSDTbody(unsigned char *data, SDTbody *b) { 32 | int boff = 0; 33 | 34 | memset(b, 0, sizeof(SDTbody)); 35 | 36 | b->service_id = getBit(data, &boff, 16); 37 | b->reserved_future_use1 = getBit(data, &boff, 3); 38 | b->EIT_user_defined_flags = getBit(data, &boff, 3); 39 | b->EIT_schedule_flag = getBit(data, &boff, 1); 40 | b->EIT_present_following_flag = getBit(data, &boff, 1); 41 | b->running_status = getBit(data, &boff, 3); 42 | b->free_CA_mode = getBit(data, &boff, 1); 43 | b->descriptors_loop_length = getBit(data, &boff, 12); 44 | 45 | return 5; 46 | } 47 | 48 | int parseSVCdesc(unsigned char *data, SVCdesc *desc) { 49 | int boff = 0; 50 | 51 | memset(desc, 0, sizeof(SVCdesc)); 52 | 53 | desc->descriptor_tag = getBit(data, &boff, 8); 54 | desc->descriptor_length = getBit(data, &boff, 8); 55 | desc->service_type = getBit(data, &boff, 8); 56 | desc->service_provider_name_length = getBit(data, &boff, 8); 57 | getStr(desc->service_provider_name, data, &boff, desc->service_provider_name_length); 58 | desc->service_name_length = getBit(data, &boff, 8); 59 | getStr(desc->service_name, data, &boff, desc->service_name_length); 60 | 61 | return desc->descriptor_length + 2; 62 | } 63 | int searchid(SVT_CONTROL *top, int service_id) 64 | { 65 | SVT_CONTROL *cur = top ; 66 | while(cur != NULL){ 67 | if(cur->event_id == service_id){ 68 | return 1 ; 69 | } 70 | cur = cur->next ; 71 | } 72 | return 0 ; 73 | } 74 | 75 | void enqueue_sdt(SVT_CONTROL *top, SVT_CONTROL *sdtptr) 76 | { 77 | SVT_CONTROL *cur ; 78 | 79 | if(top->next == NULL){ 80 | top->next = sdtptr ; 81 | sdtptr->prev = top ; 82 | return ; 83 | } 84 | cur = top->next ; 85 | while(cur != NULL){ 86 | if(sdtptr->event_id < cur->event_id){ 87 | if(cur->prev != NULL){ 88 | cur->prev->next = sdtptr ; 89 | sdtptr->prev = cur->prev ; 90 | } 91 | else { 92 | /* XXX why??? */ 93 | top->next = sdtptr; 94 | } 95 | cur->prev = sdtptr ; 96 | sdtptr->next = cur ; 97 | return ; 98 | } 99 | if(cur->next == NULL){ 100 | cur->next = sdtptr ; 101 | sdtptr->prev = cur ; 102 | return ; 103 | } 104 | cur = cur->next ; 105 | } 106 | return ; 107 | 108 | } 109 | 110 | void dumpSDT(unsigned char *ptr, SVT_CONTROL *top) 111 | { 112 | 113 | SDThead sdth; 114 | SDTbody sdtb; 115 | SVCdesc desc; 116 | SVT_CONTROL *svtptr ; 117 | int rc ; 118 | 119 | int len = 0; 120 | int loop_len = 0; 121 | 122 | /* SDT */ 123 | len = parseSDThead(ptr, &sdth); 124 | ptr += len; 125 | loop_len = sdth.section_length - (len - 3 + 4); // 3は共通ヘッダ長 4はCRC 126 | while(loop_len > 0) { 127 | len = parseSDTbody(ptr, &sdtb); 128 | ptr += len; 129 | loop_len -= len; 130 | parseSVCdesc(ptr, &desc); 131 | 132 | rc = searchid(top, sdtb.service_id); 133 | if(rc == 0){ 134 | svtptr = calloc(1, sizeof(SVT_CONTROL)); 135 | svtptr->event_id = sdtb.service_id; 136 | svtptr->original_network_id = sdth.original_network_id; 137 | svtptr->transport_stream_id = sdth.transport_stream_id; 138 | svtptr->event_id = sdtb.service_id; 139 | memcpy(svtptr->servicename, desc.service_name, strlen(desc.service_name)); 140 | enqueue_sdt(top, svtptr); 141 | #if DEBUG 142 | printf("SDT=%s,%d,%x,%x,%x,%x,%x,%x,%x\n", 143 | desc.service_name, sdtb.service_id, sdtb.reserved_future_use1, 144 | sdtb.EIT_user_defined_flags, sdtb.EIT_schedule_flag, sdtb.EIT_present_following_flag, 145 | sdtb.running_status, sdtb.free_CA_mode, sdtb.descriptors_loop_length); 146 | /* 147 | #else 148 | 0x01:デジタルTVサービス 149 | 0xA5:プロモーション映像サービス 150 | 0x0C:データサービス 151 | */ 152 | printf("SDT=(%x:%x)%s,%d,%d,%d,%d,%d(%d,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x)\n", 153 | sdth.table_id, desc.service_type, 154 | desc.service_name, sdtb.service_id, 155 | desc.descriptor_tag, desc.descriptor_length, desc.service_type, 156 | desc.service_provider_name_length, desc.service_name_length, 157 | sdth.table_id, sdth.section_syntax_indicator, sdth.reserved_future_use1, 158 | sdth.reserved1, sdth.section_length, sdth.transport_stream_id, 159 | sdth.reserved2, sdth.version_number, sdth.current_next_indicator, 160 | sdth.section_number, sdth.last_section_number, sdth.original_network_id, 161 | sdth.reserved_future_use2); 162 | #endif 163 | } 164 | 165 | ptr += sdtb.descriptors_loop_length; 166 | loop_len -= sdtb.descriptors_loop_length; 167 | } 168 | 169 | return; 170 | } 171 | -------------------------------------------------------------------------------- /sdt.h: -------------------------------------------------------------------------------- 1 | #ifndef SDT_H 2 | #define SDT_H 1 3 | 4 | #include 5 | #include 6 | 7 | #include "util.h" 8 | #include "ts_ctl.h" 9 | 10 | typedef struct _SDThead { 11 | char table_id; 12 | int section_syntax_indicator; 13 | int reserved_future_use1; 14 | int reserved1; 15 | int section_length; 16 | int transport_stream_id; 17 | int reserved2; 18 | int version_number; 19 | int current_next_indicator; 20 | int section_number; 21 | int last_section_number; 22 | int original_network_id; 23 | int reserved_future_use2; 24 | } SDThead; 25 | 26 | typedef struct _SDTbody { 27 | int service_id; 28 | int reserved_future_use1; 29 | int EIT_user_defined_flags; 30 | int EIT_schedule_flag; 31 | int EIT_present_following_flag; 32 | int running_status; 33 | int free_CA_mode; 34 | int descriptors_loop_length; 35 | } SDTbody; 36 | 37 | typedef struct _SVCdesc { 38 | int descriptor_tag; 39 | int descriptor_length; 40 | int service_type; 41 | int service_provider_name_length; 42 | char service_provider_name[MAXSECLEN]; 43 | int service_name_length; 44 | char service_name[MAXSECLEN]; 45 | } SVCdesc; 46 | 47 | 48 | #ifdef __cplusplus 49 | extern "C"{ 50 | #endif /* __cplusplus */ 51 | 52 | int parseSDThead(unsigned char *data, SDThead *h); 53 | int parseSDTbody(unsigned char *data, SDTbody *b); 54 | int parseSVCdesc(unsigned char *data, SVCdesc *desc); 55 | void dumpSDT(unsigned char *data, SVT_CONTROL *top); 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif /* __cplusplus */ 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /tdt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "tdt.h" 6 | 7 | void dumpTDT(unsigned char *ptr,EITCHECK *chk) 8 | { 9 | 10 | int rc ; 11 | 12 | int len = 0; 13 | int loop_len = 0; 14 | int boff; 15 | int table_id,section_length,wk; 16 | unsigned char JST_time[6]; 17 | 18 | boff = 0; 19 | table_id = getBit(ptr, &boff, 8); 20 | if (table_id != 0x70 && table_id != 0x73) return; 21 | wk = getBit(ptr, &boff, 4); 22 | section_length = getBit(ptr,&boff,12); 23 | memcpy(JST_time, ptr + (boff / 8),5); 24 | boff += 40; 25 | 26 | if (chk) { 27 | chk->tdttime = getStartTime(JST_time); 28 | } 29 | #ifdef DEBUG 30 | printf("[%s]\n",strTime(getStartTime(JST_time),"%Y/%m/%d %H:%M:%S")); 31 | #endif 32 | return; 33 | } 34 | -------------------------------------------------------------------------------- /tdt.h: -------------------------------------------------------------------------------- 1 | #ifndef TDT_H 2 | #define TDT_H 1 3 | 4 | #include 5 | #include 6 | 7 | #include "util.h" 8 | #include "ts_ctl.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C"{ 12 | #endif /* __cplusplus */ 13 | 14 | void dumpTDT(unsigned char *data,EITCHECK *eitcheck); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif /* __cplusplus */ 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /ts.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ts.h" 6 | 7 | static unsigned int CalcCrc(unsigned int crc, unsigned char *buf, int len); 8 | static int checkcrc(SECcache *secs); 9 | 10 | SECcache *readTS(FILE *in, SECcache secs[], int size) { 11 | static int chkcount; 12 | static int rcount = 0; 13 | static int ridx = -1; 14 | 15 | TSpacket pk; 16 | 17 | unsigned char buf[1024]; 18 | 19 | int boff; 20 | int len; 21 | unsigned char *payptr; 22 | 23 | int inchar; 24 | int i; 25 | 26 | chkcount=0; 27 | /* syncバイトまで読み飛ばし */ 28 | if(rcount == 0) { 29 | while((inchar = fgetc(in)) != EOF) { 30 | if((inchar & 0xFF) == 0x47) { 31 | //fseek(in, -1, SEEK_CUR); 32 | ungetc(inchar, in); 33 | break; 34 | } 35 | } 36 | if(inchar == EOF) { 37 | return NULL; 38 | } 39 | } 40 | 41 | retry: 42 | 43 | /* 戻すべき残りがあるか? */ 44 | if(ridx >= 0 && secs[ridx].cont) { 45 | /* バッファチェック */ 46 | if((secs[ridx].cur.payload[secs[ridx].curlen] & 0xFF) == 0xFF) { 47 | secs[ridx].cont = 0; 48 | secs[ridx].seclen = 0; 49 | secs[ridx].setlen = 0; 50 | secs[ridx].curlen = 0; 51 | } else { 52 | len = secs[ridx].cur.payloadlen - secs[ridx].curlen; 53 | /* 全部設定済みチェック */ 54 | if(len <= 0) { // XXX lenが-になることがある。なぜだろう 55 | secs[ridx].cont = 0; 56 | secs[ridx].seclen = 0; 57 | secs[ridx].setlen = 0; 58 | secs[ridx].curlen = 0; 59 | } else { 60 | /* ここでseclenが跨るようにTS分割されていると困るな @@ 61 | if(secs[ridx].pid == 0x12) { 62 | int check = secs[ridx].cur.payload[secs[ridx].curlen] & 0xFF; 63 | if(!(check == 0x4E || 64 | check == 0x4F || 65 | (check >= 0x50 && check <= 0x6F))) { 66 | secs[ridx].curlen -= 3; 67 | } 68 | } 69 | */ 70 | 71 | boff = 12; 72 | secs[ridx].seclen = getBit(&secs[ridx].cur.payload[secs[ridx].curlen], &boff, 12) + 3; // ヘッダ 73 | 74 | 75 | if(secs[ridx].seclen > MAXSECLEN){ 76 | // セクションが MAXSECLEN より大きい時はこのセクションをスキップ 77 | secs[ridx].cont = 0; 78 | goto retry; 79 | } 80 | 81 | /* 82 | if(secs[ridx].seclen == 2334) { 83 | printf("aa"); 84 | } 85 | */ 86 | 87 | /* TSデータ長-設定済みデータ長 */ 88 | if(secs[ridx].seclen > len) { 89 | memcpy(secs[ridx].buf, &secs[ridx].cur.payload[secs[ridx].curlen], len); 90 | secs[ridx].setlen = len; 91 | secs[ridx].curlen = 0; 92 | secs[ridx].cont = 1; 93 | /* 次のレコード読み込み */ 94 | } else { 95 | memcpy(secs[ridx].buf, 96 | &secs[ridx].cur.payload[secs[ridx].curlen], secs[ridx].seclen); 97 | secs[ridx].setlen = secs[ridx].seclen; 98 | secs[ridx].curlen += secs[ridx].seclen; 99 | secs[ridx].cont = 1; 100 | 101 | /* CRCのチェック */ 102 | if(checkcrc(&(secs[ridx]))) { 103 | return &(secs[ridx]); /* 戻る */ 104 | } 105 | goto retry; /* もう一回 */ 106 | } 107 | } 108 | } 109 | } 110 | 111 | int roffset = 0; 112 | while(1) { 113 | if(fread(buf+roffset, 188-roffset, 1, in) != 1) { 114 | /* 残りの処理? */ 115 | return NULL; 116 | } 117 | roffset = 0; 118 | rcount++; 119 | chkcount++; 120 | 121 | if((buf[0] & 0xFF) != 0x47) { 122 | /* 最初はbuf中に0x47があるかチェック */ 123 | for(i = 1; i < 188; i++) { 124 | if((buf[i] & 0xFF) == 0x47) { 125 | break; 126 | } 127 | } 128 | 129 | if(i < 188) { 130 | /* そこから再読み込みして欲しいのでseek */ 131 | //fseek(in, (188 - i) * -1, SEEK_CUR); 132 | roffset = i; 133 | memmove(buf, buf + i, 188 - i); 134 | continue; 135 | } 136 | 137 | while((inchar = fgetc(in)) != EOF) { 138 | if((inchar & 0xFF) == 0x47) { 139 | //fseek(in, -1, SEEK_CUR); 140 | ungetc(inchar, in); 141 | break; 142 | } 143 | } 144 | if(inchar == EOF) { 145 | return NULL; 146 | } 147 | continue; 148 | } 149 | 150 | /* 151 | if(rcount == 406502) { 152 | printf("aa"); 153 | } 154 | */ 155 | if (chkcount>100000) { 156 | /* XXX 157 | 不正なデータ等を読み込むとreadTSから処理が帰ってこないのでタイムアウトしない。 158 | 適当なサイズ読み込んでだめなら一度リターンする。 159 | */ 160 | return &(secs[0]); /* 取り合えず戻る */ 161 | } 162 | 163 | 164 | pk.rcount = rcount; 165 | 166 | boff = 0; 167 | pk.sync = getBit(buf, &boff, 8); 168 | pk.transport_error_indicator = getBit(buf, &boff, 1); 169 | pk.payload_unit_start_indicator = getBit(buf, &boff, 1); 170 | pk.transport_priority = getBit(buf, &boff, 1); 171 | pk.pid = getBit(buf, &boff, 13); 172 | pk.transport_scrambling_control = getBit(buf, &boff, 2); 173 | pk.adaptation_field_control = getBit(buf, &boff, 2); 174 | pk.continuity_counter = getBit(buf, &boff, 4); 175 | 176 | /* 177 | adaptation_field_control 2 bslbf 178 | continuity_counter 4 uimsbf 179 | if(adaptation_field_control = = '10' || adaptation_field_control = = '11'){ 180 | adaptation_field() 181 | } 182 | ... 183 | adaptation_field() { 184 | adaptation_field_length 8 uimsbf 185 | if (adaptation_field_length > 0) { 186 | discontinuity_indicator.... 187 | 188 | 00 Reserved for future use by ISO/IEC 189 | 01 No adaptation_field, payload only 190 | 10 Adaptation_field only, no payload 191 | 11 Adaptation_field followed by payload 192 | 193 | */ 194 | 195 | pk.payloadlen = 184; 196 | 197 | if(pk.adaptation_field_control == 2) { 198 | continue; 199 | } 200 | 201 | if(pk.adaptation_field_control == 3) { 202 | len = getBit(buf, &boff, 8); 203 | payptr = buf + (boff / 8) + len; 204 | pk.payloadlen -= (len + 1); 205 | } else { 206 | payptr = buf + (boff / 8); 207 | } 208 | if(pk.payloadlen < 0){ 209 | continue ; 210 | } 211 | 212 | /* 213 | if the Transport Stream packet carries the first byte of a PSI section, the payload_unit_start_indicator value 214 | shall be '1', indicating that the first byte of the payload of this Transport Stream packet carries the pointer_field. 215 | */ 216 | if(pk.payload_unit_start_indicator == 1) { 217 | /* pointer_fieldはいらない */ 218 | payptr += 1; 219 | pk.payloadlen -= 1; 220 | } 221 | memset(pk.payload, 0xFF, sizeof(pk.payload)); 222 | if(pk.payloadlen > sizeof(pk.payload)) 223 | continue; 224 | memcpy(pk.payload, payptr, pk.payloadlen); 225 | 226 | 227 | /* 228 | if(pk.rcount == 62) { 229 | printf("62\n"); 230 | } 231 | 232 | if(pk.rcount == 63) { 233 | printf("63\n"); 234 | } 235 | */ 236 | 237 | /* 興味のあるpidか確認 */ 238 | for(i = 0;i < size; i++) { 239 | if(secs[i].pid == pk.pid) { 240 | secs[i].cur = pk; 241 | /* 途中処理中か最初か? */ 242 | if(!secs[i].cont) { 243 | /* 最初 セクション長を調べる */ 244 | boff = 12; 245 | secs[i].seclen = getBit(secs[i].cur.payload, &boff, 12) + 3; // ヘッダ; 246 | if(secs[i].seclen > MAXSECLEN){ 247 | /* セクション長が MAXSECLEN より長いときはこのセクションをスキップ */ 248 | secs[i].cont = 0; 249 | goto retry; 250 | } 251 | /* 252 | if(secs[i].seclen == 2334) { 253 | printf("aa"); 254 | } 255 | */ 256 | 257 | if(secs[i].seclen > secs[i].cur.payloadlen) { 258 | memcpy(secs[i].buf, secs[i].cur.payload, secs[i].cur.payloadlen); 259 | secs[i].setlen = secs[i].cur.payloadlen; 260 | secs[i].cont = 1; 261 | continue; 262 | } 263 | memcpy(secs[i].buf, secs[i].cur.payload, secs[i].seclen); 264 | secs[i].setlen = secs[i].seclen; 265 | secs[i].curlen = secs[i].seclen; 266 | secs[i].cont = 1; 267 | ridx = i; 268 | /* CRCのチェック */ 269 | if(checkcrc(&(secs[ridx]))) { 270 | return &(secs[i]); /* 取り合えず戻る */ 271 | } 272 | goto retry; /* 残り処理へ */ 273 | } 274 | /* セクション長-設定済み長 */ 275 | len = secs[i].seclen - secs[i].setlen; 276 | if(len > secs[i].cur.payloadlen) { 277 | /* 全体転送 */ 278 | memcpy(&secs[i].buf[secs[i].setlen], 279 | secs[i].cur.payload, secs[i].cur.payloadlen); 280 | secs[i].setlen += secs[i].cur.payloadlen; 281 | continue; 282 | } 283 | /* セクション長の残りを設定 */ 284 | memcpy(&secs[i].buf[secs[i].setlen], secs[i].cur.payload, len); 285 | secs[i].setlen = secs[i].seclen; 286 | secs[i].curlen += len; 287 | secs[i].cont = 1; 288 | ridx = i; 289 | /* CRCのチェック */ 290 | if(checkcrc(&(secs[ridx]))) { 291 | return &(secs[i]); 292 | } 293 | goto retry; /* 残り処理へ */ 294 | } 295 | } 296 | } 297 | 298 | //return NULL; 299 | } 300 | 301 | /* BonTest/TsStream.cppからのパクリ */ 302 | unsigned int CalcCrc(unsigned int crc, unsigned char *buf, int len) { 303 | unsigned int c = crc; 304 | int n; 305 | 306 | static const unsigned int CrcTable[256] = { 307 | 0x00000000UL, 0x04C11DB7UL, 0x09823B6EUL, 0x0D4326D9UL, 0x130476DCUL, 0x17C56B6BUL, 0x1A864DB2UL, 0x1E475005UL, 0x2608EDB8UL, 0x22C9F00FUL, 0x2F8AD6D6UL, 0x2B4BCB61UL, 0x350C9B64UL, 0x31CD86D3UL, 0x3C8EA00AUL, 0x384FBDBDUL, 308 | 0x4C11DB70UL, 0x48D0C6C7UL, 0x4593E01EUL, 0x4152FDA9UL, 0x5F15ADACUL, 0x5BD4B01BUL, 0x569796C2UL, 0x52568B75UL, 0x6A1936C8UL, 0x6ED82B7FUL, 0x639B0DA6UL, 0x675A1011UL, 0x791D4014UL, 0x7DDC5DA3UL, 0x709F7B7AUL, 0x745E66CDUL, 309 | 0x9823B6E0UL, 0x9CE2AB57UL, 0x91A18D8EUL, 0x95609039UL, 0x8B27C03CUL, 0x8FE6DD8BUL, 0x82A5FB52UL, 0x8664E6E5UL, 0xBE2B5B58UL, 0xBAEA46EFUL, 0xB7A96036UL, 0xB3687D81UL, 0xAD2F2D84UL, 0xA9EE3033UL, 0xA4AD16EAUL, 0xA06C0B5DUL, 310 | 0xD4326D90UL, 0xD0F37027UL, 0xDDB056FEUL, 0xD9714B49UL, 0xC7361B4CUL, 0xC3F706FBUL, 0xCEB42022UL, 0xCA753D95UL, 0xF23A8028UL, 0xF6FB9D9FUL, 0xFBB8BB46UL, 0xFF79A6F1UL, 0xE13EF6F4UL, 0xE5FFEB43UL, 0xE8BCCD9AUL, 0xEC7DD02DUL, 311 | 0x34867077UL, 0x30476DC0UL, 0x3D044B19UL, 0x39C556AEUL, 0x278206ABUL, 0x23431B1CUL, 0x2E003DC5UL, 0x2AC12072UL, 0x128E9DCFUL, 0x164F8078UL, 0x1B0CA6A1UL, 0x1FCDBB16UL, 0x018AEB13UL, 0x054BF6A4UL, 0x0808D07DUL, 0x0CC9CDCAUL, 312 | 0x7897AB07UL, 0x7C56B6B0UL, 0x71159069UL, 0x75D48DDEUL, 0x6B93DDDBUL, 0x6F52C06CUL, 0x6211E6B5UL, 0x66D0FB02UL, 0x5E9F46BFUL, 0x5A5E5B08UL, 0x571D7DD1UL, 0x53DC6066UL, 0x4D9B3063UL, 0x495A2DD4UL, 0x44190B0DUL, 0x40D816BAUL, 313 | 0xACA5C697UL, 0xA864DB20UL, 0xA527FDF9UL, 0xA1E6E04EUL, 0xBFA1B04BUL, 0xBB60ADFCUL, 0xB6238B25UL, 0xB2E29692UL, 0x8AAD2B2FUL, 0x8E6C3698UL, 0x832F1041UL, 0x87EE0DF6UL, 0x99A95DF3UL, 0x9D684044UL, 0x902B669DUL, 0x94EA7B2AUL, 314 | 0xE0B41DE7UL, 0xE4750050UL, 0xE9362689UL, 0xEDF73B3EUL, 0xF3B06B3BUL, 0xF771768CUL, 0xFA325055UL, 0xFEF34DE2UL, 0xC6BCF05FUL, 0xC27DEDE8UL, 0xCF3ECB31UL, 0xCBFFD686UL, 0xD5B88683UL, 0xD1799B34UL, 0xDC3ABDEDUL, 0xD8FBA05AUL, 315 | 0x690CE0EEUL, 0x6DCDFD59UL, 0x608EDB80UL, 0x644FC637UL, 0x7A089632UL, 0x7EC98B85UL, 0x738AAD5CUL, 0x774BB0EBUL, 0x4F040D56UL, 0x4BC510E1UL, 0x46863638UL, 0x42472B8FUL, 0x5C007B8AUL, 0x58C1663DUL, 0x558240E4UL, 0x51435D53UL, 316 | 0x251D3B9EUL, 0x21DC2629UL, 0x2C9F00F0UL, 0x285E1D47UL, 0x36194D42UL, 0x32D850F5UL, 0x3F9B762CUL, 0x3B5A6B9BUL, 0x0315D626UL, 0x07D4CB91UL, 0x0A97ED48UL, 0x0E56F0FFUL, 0x1011A0FAUL, 0x14D0BD4DUL, 0x19939B94UL, 0x1D528623UL, 317 | 0xF12F560EUL, 0xF5EE4BB9UL, 0xF8AD6D60UL, 0xFC6C70D7UL, 0xE22B20D2UL, 0xE6EA3D65UL, 0xEBA91BBCUL, 0xEF68060BUL, 0xD727BBB6UL, 0xD3E6A601UL, 0xDEA580D8UL, 0xDA649D6FUL, 0xC423CD6AUL, 0xC0E2D0DDUL, 0xCDA1F604UL, 0xC960EBB3UL, 318 | 0xBD3E8D7EUL, 0xB9FF90C9UL, 0xB4BCB610UL, 0xB07DABA7UL, 0xAE3AFBA2UL, 0xAAFBE615UL, 0xA7B8C0CCUL, 0xA379DD7BUL, 0x9B3660C6UL, 0x9FF77D71UL, 0x92B45BA8UL, 0x9675461FUL, 0x8832161AUL, 0x8CF30BADUL, 0x81B02D74UL, 0x857130C3UL, 319 | 0x5D8A9099UL, 0x594B8D2EUL, 0x5408ABF7UL, 0x50C9B640UL, 0x4E8EE645UL, 0x4A4FFBF2UL, 0x470CDD2BUL, 0x43CDC09CUL, 0x7B827D21UL, 0x7F436096UL, 0x7200464FUL, 0x76C15BF8UL, 0x68860BFDUL, 0x6C47164AUL, 0x61043093UL, 0x65C52D24UL, 320 | 0x119B4BE9UL, 0x155A565EUL, 0x18197087UL, 0x1CD86D30UL, 0x029F3D35UL, 0x065E2082UL, 0x0B1D065BUL, 0x0FDC1BECUL, 0x3793A651UL, 0x3352BBE6UL, 0x3E119D3FUL, 0x3AD08088UL, 0x2497D08DUL, 0x2056CD3AUL, 0x2D15EBE3UL, 0x29D4F654UL, 321 | 0xC5A92679UL, 0xC1683BCEUL, 0xCC2B1D17UL, 0xC8EA00A0UL, 0xD6AD50A5UL, 0xD26C4D12UL, 0xDF2F6BCBUL, 0xDBEE767CUL, 0xE3A1CBC1UL, 0xE760D676UL, 0xEA23F0AFUL, 0xEEE2ED18UL, 0xF0A5BD1DUL, 0xF464A0AAUL, 0xF9278673UL, 0xFDE69BC4UL, 322 | 0x89B8FD09UL, 0x8D79E0BEUL, 0x803AC667UL, 0x84FBDBD0UL, 0x9ABC8BD5UL, 0x9E7D9662UL, 0x933EB0BBUL, 0x97FFAD0CUL, 0xAFB010B1UL, 0xAB710D06UL, 0xA6322BDFUL, 0xA2F33668UL, 0xBCB4666DUL, 0xB8757BDAUL, 0xB5365D03UL, 0xB1F740B4UL 323 | }; 324 | 325 | for (n = 0; n < len; n++) { 326 | c = (c << 8) ^ CrcTable[((((c >> 24) & 0xFF) ^ buf[n]) & 0XFF)]; 327 | } 328 | 329 | return c; 330 | } 331 | 332 | 333 | int checkcrc(SECcache *secs) { 334 | 335 | /* regard a section with more than MAXSECLEN data as an error. */ 336 | if(secs->seclen > MAXSECLEN) { 337 | return 0; 338 | } 339 | 340 | /* セクションの終りに置かれる4バイトのCRC32は、 341 | CRC計算の結果0になるように設定される。 342 | 値が発生した場合は、エラーなので対象外にする */ 343 | if(CalcCrc(0xffffffffU, secs->buf, secs->seclen)) { 344 | // fprintf(stderr, "tblid:0x%x CRC error\n", secs->buf[0]); 345 | return 0; 346 | } 347 | return 1; 348 | } 349 | -------------------------------------------------------------------------------- /ts.h: -------------------------------------------------------------------------------- 1 | #ifndef TS_H 2 | #define TS_H 1 3 | 4 | #include 5 | #include 6 | 7 | #include "util.h" 8 | 9 | #define TSPAYLOADMAX 184 10 | 11 | typedef struct _TSpacket { 12 | char sync; 13 | int transport_error_indicator; 14 | int payload_unit_start_indicator; 15 | int transport_priority; 16 | int pid; 17 | int transport_scrambling_control; 18 | int adaptation_field_control; 19 | int continuity_counter; 20 | int adaptation_field; 21 | unsigned char payload[TSPAYLOADMAX]; 22 | int payloadlen; 23 | int rcount; 24 | } TSpacket; 25 | 26 | typedef struct _SECcache { 27 | int pid; 28 | unsigned char buf[MAXSECLEN]; 29 | int seclen; 30 | int setlen; 31 | TSpacket cur; 32 | int curlen; 33 | int cont; 34 | } SECcache; 35 | 36 | #ifdef __cplusplus 37 | extern "C"{ 38 | #endif /* __cplusplus */ 39 | 40 | SECcache *readTS(FILE *in, SECcache secs[], int secscount); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif /* __cplusplus */ 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /ts_ctl.h: -------------------------------------------------------------------------------- 1 | #ifndef __TS_CONTROL_H__ 2 | #define __TS_CONTROL_H__ 3 | 4 | #include "util.h" 5 | 6 | #define EIT_SDTNOTFOUND 0 7 | #define EIT_OK 1 8 | #define EIT_CHECKOK 2 9 | #define EIT_CHECKNG 3 10 | 11 | typedef struct _NIT_CONTROL NIT_CONTROL; 12 | typedef struct _SVT_CONTROL SVT_CONTROL; 13 | typedef struct _EIT_CONTROL EIT_CONTROL; 14 | typedef struct _CURRENTNEXT CURRENTNEXT; 15 | typedef struct _EITEXTDESC EITEXTDESC; 16 | typedef struct _AUDIODESC AUDIODESC; 17 | typedef struct _EITCHECK EITCHECK; 18 | 19 | struct _EITCHECK { //イベントチェック用構造体 20 | int svid; // 対象サービスID 21 | int evid; // 対象イベントID 22 | time_t starttime; // 対象イベント開始時刻(check時のみ設定) 23 | time_t tdttime; // 現在のTDT(wait時の時刻チェック用) 24 | time_t waitend; // 最大待機時間(check時は11秒固定) 25 | int maxcycle; // BITにあるEIT送出周期で一番大きな値 26 | }; 27 | 28 | struct _AUDIODESC { 29 | char audiotype; // AudioType 30 | char langcode[8]; // 言語コード(jpn) 二ヶ国語の場合(jpn eng) 31 | char *audiodesc; // text 32 | }; 33 | 34 | struct _EITEXTDESC { 35 | char *item_description; 36 | char *item; 37 | }; 38 | struct _CURRENTNEXT { 39 | short event_id; 40 | unsigned char start_time[5]; 41 | char duration[3]; 42 | char running_status; 43 | }; 44 | 45 | struct _SVT_CONTROL{ 46 | SVT_CONTROL *next ; 47 | SVT_CONTROL *prev ; 48 | int event_id ; // イベントID 49 | int original_network_id ; // OriginalNetworkID 50 | int transport_stream_id ; // TransporrtStreamID 51 | char servicename[MAXSECLEN] ; // サービス名 52 | EIT_CONTROL *eit; // EIT テーブル 53 | CURRENTNEXT cnev[2]; 54 | char haveeitschedule; // EITスケジュールがあるか。 55 | int frequency; 56 | int remote_control_key_id; // リモコンID(地デジ) 57 | }; 58 | 59 | struct _EIT_CONTROL{ 60 | EIT_CONTROL *next ; 61 | EIT_CONTROL *prev ; 62 | int table_id ; 63 | int servid ; 64 | int event_id ; // イベントID 65 | unsigned char numcontent; 66 | unsigned char content[7]; //コンテントタイプ 67 | unsigned char usernibble[7]; 68 | unsigned char numattachinfo; 69 | unsigned char attachinfo[7]; //番組付属情報 70 | char *title ; // タイトル 71 | char *subtitle ; // サブタイトル 72 | short eitextcnt; 73 | EITEXTDESC *eitextdesc; 74 | char video; // 映像情報 75 | AUDIODESC audiodesc[2]; // 音声情報 76 | char freeCA; // スクランブル 77 | int duration; // 時間 78 | time_t start_time; // 開始時刻 79 | }; 80 | #endif 81 | -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "aribstr.h" 8 | #include "util.h" 9 | 10 | int strrep(char *buf, char *mae, char *ato) 11 | { 12 | char *mitsuke, *findpos; 13 | size_t maelen, atolen; 14 | int shift; 15 | 16 | findpos = buf; 17 | maelen = strlen(mae); 18 | atolen = strlen(ato); 19 | shift = (int)(strlen(ato)-strlen(mae)); 20 | 21 | if (maelen == 0 || strstr(findpos, mae) == NULL) return 0; 22 | while ((mitsuke = strstr(findpos, mae)) != NULL) { 23 | if (shift > 0) { 24 | memmove(mitsuke + shift, mitsuke, strlen(mitsuke) + 1); 25 | } else if (shift < 0) { 26 | memmove(mitsuke, mitsuke - shift, strlen(mitsuke) + shift + 1); 27 | } 28 | memmove(mitsuke, ato, atolen); 29 | findpos = mitsuke + atolen; 30 | } 31 | return 1; 32 | } 33 | 34 | int getBit(unsigned char *byte, int *pbit, int gbit) { 35 | int pbyte = *pbit / 8; 36 | unsigned char *fbyte = byte + pbyte; 37 | 38 | int cutbit = *pbit - (pbyte * 8); 39 | int lcutbit = 32 - (cutbit + gbit); 40 | 41 | unsigned char tbuf[4]; /* intの最大32bit */ 42 | unsigned int tnum; 43 | 44 | tnum = fbyte[0] << 24 | fbyte[1] << 16 | fbyte[2] << 8 | fbyte[3]; 45 | tnum = ((tnum >> lcutbit) & ~(~0 << gbit)); 46 | *pbit += gbit; 47 | return tnum; 48 | 49 | 50 | //memcpy(tbuf, fbyte, sizeof(unsigned char) * 4); 51 | tbuf[0]=fbyte[0]; 52 | tbuf[1]=fbyte[1]; 53 | tbuf[2]=fbyte[2]; 54 | tbuf[3]=fbyte[3]; 55 | 56 | /* 先頭バイトから不要bitをカット */ 57 | tbuf[0] = tbuf[0] << cutbit; 58 | tbuf[0] = tbuf[0] >> cutbit; 59 | 60 | /* intにしてしまう */ 61 | tnum = tbuf[0] << 24 | tbuf[1] << 16 | tbuf[2] << 8 | tbuf[3]; 62 | 63 | /* 後ろの不要バイトをカット */ 64 | tnum = tnum >> lcutbit; 65 | 66 | *pbit += gbit; 67 | 68 | return tnum; 69 | 70 | } 71 | 72 | void getStr(char *tostr, unsigned char *byte, int *pbit, int len) { 73 | char str[MAXSECLEN]; 74 | int pbyte = *pbit / 8; 75 | unsigned char *fbyte = byte + pbyte; 76 | 77 | memset(str, 0, sizeof(char) * MAXSECLEN); 78 | memcpy(str, fbyte, len); 79 | 80 | *pbit += (len * 8); 81 | 82 | AribToString(tostr, str, len); 83 | 84 | return; 85 | 86 | } 87 | 88 | int parseOTHERdesc(unsigned char *data,unsigned char *tag) { 89 | int boff = 0; 90 | int descriptor_tag; 91 | int descriptor_length; 92 | 93 | descriptor_tag = getBit(data, &boff, 8); 94 | descriptor_length = getBit(data, &boff, 8); 95 | 96 | if (tag) { 97 | *tag = descriptor_tag; 98 | #ifdef DEBUG 99 | printf("other desc_tag:0x%x len %d\n", descriptor_tag,descriptor_length); 100 | #endif 101 | } 102 | 103 | return descriptor_length + 2; 104 | } 105 | 106 | 107 | void* allocCopy(void* src, int *boff, size_t size) { 108 | void* mem = NULL; 109 | if ( size == 0 ) return NULL; 110 | 111 | mem = malloc(size); 112 | memcpy(mem, src + *boff / 8, size); 113 | *boff += size * 8; 114 | return mem; 115 | } 116 | 117 | time_t getStartTime(unsigned char *starttime) 118 | { 119 | 120 | int tnum,yy,mm,dd; 121 | char buf[10]; 122 | time_t l_time ; 123 | time_t end_time ; 124 | struct tm tl ; 125 | struct tm *endtl ; 126 | char cendtime[32]; 127 | char cstarttime[32]; 128 | 129 | tnum = (starttime[0] & 0xFF) << 8 | (starttime[1] & 0xFF); 130 | 131 | yy = (tnum - 15078.2) / 365.25; 132 | mm = ((tnum - 14956.1) - (int)(yy * 365.25)) / 30.6001; 133 | dd = (tnum - 14956) - (int)(yy * 365.25) - (int)(mm * 30.6001); 134 | 135 | if(mm == 14 || mm == 15) { 136 | yy += 1; 137 | mm = mm - 1 - (1 * 12); 138 | } else { 139 | mm = mm - 1; 140 | } 141 | 142 | tl.tm_year = yy; 143 | tl.tm_mon = mm - 1; 144 | tl.tm_mday = dd; 145 | memset(buf, '\0', sizeof(buf)); 146 | sprintf(buf, "%x", starttime[2]); 147 | tl.tm_hour = atoi(buf); 148 | memset(buf, '\0', sizeof(buf)); 149 | sprintf(buf, "%x", starttime[3]); 150 | tl.tm_min = atoi(buf); 151 | memset(buf, '\0', sizeof(buf)); 152 | sprintf(buf, "%x", starttime[4]); 153 | tl.tm_sec = atoi(buf); 154 | 155 | tl.tm_wday = 0; 156 | tl.tm_isdst = 0; 157 | tl.tm_yday = 0; 158 | 159 | l_time = mktime(&tl); 160 | return l_time; 161 | 162 | } 163 | 164 | int getDurationSec(unsigned char *duration) 165 | { 166 | int hh,mm,ss; 167 | char buf[24]; 168 | if((duration[0] == 0xFF) && (duration[1] == 0xFF) && (duration[2] == 0xFF)){ 169 | // 終了未定 170 | hh = mm = ss = 0; 171 | ss = -1; 172 | }else{ 173 | memset(buf, '\0', sizeof(buf)); 174 | sprintf(buf, "%x", duration[0]); 175 | hh = atoi(buf)*3600; 176 | memset(buf, '\0', sizeof(buf)); 177 | sprintf(buf, "%x", duration[1]); 178 | mm = atoi(buf)*60; 179 | memset(buf, '\0', sizeof(buf)); 180 | sprintf(buf, "%x", duration[2]); 181 | ss = atoi(buf); 182 | } 183 | 184 | return hh+mm+ss; 185 | } 186 | 187 | char *strTime(time_t tx,char *format) 188 | { 189 | static char tstr[32]; 190 | struct tm *tl; 191 | 192 | memset(tstr,0,sizeof(tstr)); 193 | tl = localtime(&tx); 194 | strftime(tstr, (sizeof(tstr) - 1), format, tl); 195 | return tstr; 196 | } 197 | 198 | double getTimeDiff(time_t tottime) 199 | { 200 | struct timeval timeofday; 201 | 202 | gettimeofday( &timeofday, NULL ); 203 | return (double)tottime-(double)timeofday.tv_sec+(double)timeofday.tv_usec*1e-6; 204 | } 205 | 206 | 207 | /* 208 | * YYYY/MM/DD HH:MM:SS -> time_t 209 | * YYYY-MM-DDTHH:MM:SS -> time_t 210 | * 211 | */ 212 | time_t str2timet(char *str) 213 | { 214 | int len; 215 | struct tm tms; 216 | 217 | if (!str) return 0; 218 | len = strlen(str); 219 | if (len == 0) return 0; 220 | 221 | memset(&tms, 0, sizeof(struct tm)); 222 | 223 | if((len >= 19) && ((str[4] == '-')||(str[4] == '/'))) { 224 | tms.tm_year = atoi(str) - 1900; 225 | tms.tm_mon = atoi(str+5)-1; 226 | tms.tm_mday = atoi(str+8); 227 | tms.tm_hour = atoi(str+11); 228 | tms.tm_min = atoi(str+14); 229 | tms.tm_sec = atoi(str+17); 230 | return mktime(&tms); 231 | } 232 | return 0; 233 | } 234 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTILH 1 3 | 4 | #include 5 | 6 | #define MAXSECLEN 4096 7 | 8 | #ifdef __cplusplus 9 | extern "C"{ 10 | #endif /* __cplusplus */ 11 | 12 | int strrep(char *, char *, char *); 13 | int getBit(unsigned char *byte, int *pbit, int gbit); 14 | void getStr(char *tostr, unsigned char *byte, int *pbit, int len); 15 | int parseOTHERdesc(unsigned char *data,unsigned char *tag); 16 | 17 | time_t getStartTime(unsigned char *starttime); 18 | int getDurationSec(unsigned char *duration); 19 | char *strTime(time_t tx,char *format); 20 | double getTimeDiff(time_t); 21 | time_t str2timet(char *str); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif /* __cplusplus */ 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /xmldata.c: -------------------------------------------------------------------------------- 1 | #ifndef XMLDATA_C 2 | #define XMLDATA_C 1 3 | 4 | #define CONTENT_LARGE 0 5 | #define CONTENT_MIDDLE 1 6 | #define CONTENT_EX_CS 2 7 | #define CONTENT_EX_BS 3 8 | #define CONTENT_EX_GR 4 9 | #define CONTENT_LANG_JA 0 10 | #define CONTENT_LANG_EN 1 11 | 12 | typedef struct _ContentTYPE{ 13 | char *japanese ; 14 | char *english ; 15 | }CONTENT_TYPE; 16 | 17 | typedef struct _ContentTYPEA { 18 | char *lang[2]; 19 | }CONTENT_TYPEA; 20 | 21 | #define CAT_COUNT 16 22 | static CONTENT_TYPE ContentCatList[CAT_COUNT] = { 23 | { "ニュース/報道", "news" }, 24 | { "スポーツ", "sports" }, 25 | { "情報/ワイドショー", "information" }, 26 | { "ドラマ", "drama" }, 27 | { "音楽", "music" }, 28 | { "バラエティ", "variety" }, 29 | { "映画", "cinema" }, 30 | { "アニメ/特撮", "anime" }, 31 | { "ドキュメンタリー/教養", "documentary" }, 32 | { "劇場/公演", "stage" }, 33 | { "趣味/教育", "hobby" }, 34 | { "福祉", "welfare" }, //福祉 35 | { "予備", "etc" }, //予備 36 | { "予備", "etc" }, //予備 37 | { "予備", "etc" }, //予備 38 | { "その他", "etc" } //その他 39 | }; 40 | /* コンテント記述子 ジャンル中分類 */ 41 | #define MIDDLECAT_COUNT 256 42 | static CONTENT_TYPE ContentMiddleCatList[MIDDLECAT_COUNT] = { 43 | {"定時・総合","Regular/General"}, 44 | {"天気","Weather"}, 45 | {"特集・ドキュメント","Special topic/documentary"}, 46 | {"政治・国会","Politics/diet"}, 47 | {"経済・市況","Economy/market"}, 48 | {"海外・国際","Overseas"}, 49 | {"解説","Commentary"}, 50 | {"討論・会談","Discussion/meeting"}, 51 | {"報道特番","Special news report"}, 52 | {"ローカル・地域","Local"}, 53 | {"交通","Traffic"}, 54 | {"",""}, 55 | {"",""}, 56 | {"",""}, 57 | {"",""}, 58 | {"",""}, 59 | {"スポーツニュース","Sports news"}, 60 | {"野球","Baseball"}, 61 | {"サッカー","soccer"}, 62 | {"ゴルフ","Golf"}, 63 | {"その他の球技","Other ball games"}, 64 | {"相撲・格闘技","Sumo/fighting sports"}, 65 | {"オリンピック・国際大会","Olympic/international games"}, 66 | {"マラソン・陸上・水泳","Marathon/field and track/swimming"}, 67 | {"モータースポーツ","Motor sports"}, 68 | {"マリン・ウインタースポーツ","Marine/winter sports"}, 69 | {"競馬・公営競技","Horse race/public sports"}, 70 | {"",""}, 71 | {"",""}, 72 | {"",""}, 73 | {"",""}, 74 | {"その他","Other"}, 75 | {"芸能・ワイドショー","Show business/tabloid show"}, 76 | {"ファッション","Fashion"}, 77 | {"暮らし・住まい","Life/residence"}, 78 | {"健康・医療","Health/medical care"}, 79 | {"ショッピング・通販","Shopping/catalog shopping"}, 80 | {"グルメ・料理","Gourmet/cooking show"}, 81 | {"イベント","Events"}, 82 | {"番組紹介・お知らせ","Promotion/information"}, 83 | {"",""}, 84 | {"",""}, 85 | {"",""}, 86 | {"",""}, 87 | {"",""}, 88 | {"",""}, 89 | {"",""}, 90 | {"その他","Others"}, 91 | {"国内ドラマ","Japanese drama"}, 92 | {"海外ドラマ","Overseas drama"}, 93 | {"時代劇","Historical drama"}, 94 | {"",""}, 95 | {"",""}, 96 | {"",""}, 97 | {"",""}, 98 | {"",""}, 99 | {"",""}, 100 | {"",""}, 101 | {"",""}, 102 | {"",""}, 103 | {"",""}, 104 | {"",""}, 105 | {"",""}, 106 | {"その他","Others"}, 107 | {"国内ロック・ポップス","Japanese rock/pops"}, 108 | {"海外ロック・ポップス","Overseas rock/pops"}, 109 | {"クラシック・オペラ","Classical/opera"}, 110 | {"ジャズ・フュージョン","Jazz/fusion"}, 111 | {"歌謡曲・演歌","Japanese popular song/ballad (Enka)"}, 112 | {"ライブ・コンサート","Live show/concert"}, 113 | {"ランキング・リクエスト","Ranking/Request show"}, 114 | {"カラオケ・のど自慢","Karaoke/singing contest"}, 115 | {"民謡・邦楽","Folk/Japanese music"}, 116 | {"童謡・キッズ","Children's song"}, 117 | {"民族音楽・ワールドミュージック","Ethnic/world music"}, 118 | {"",""}, 119 | {"",""}, 120 | {"",""}, 121 | {"",""}, 122 | {"その他","Other"}, 123 | {"クイズ","Quiz"}, 124 | {"ゲーム","Game"}, 125 | {"トークバラエティ","Talk show"}, 126 | {"お笑い・コメディ","Comedy"}, 127 | {"音楽バラエティ","Musical variety show"}, 128 | {"旅バラエティ","Travel variety show"}, 129 | {"料理バラエティ","Cooking variety show"}, 130 | {"",""}, 131 | {"",""}, 132 | {"",""}, 133 | {"",""}, 134 | {"",""}, 135 | {"",""}, 136 | {"",""}, 137 | {"",""}, 138 | {"その他","Other"}, 139 | {"洋画","Overseas movie"}, 140 | {"邦画","Japanese movie"}, 141 | {"アニメ","Animation movie"}, 142 | {"",""}, 143 | {"",""}, 144 | {"",""}, 145 | {"",""}, 146 | {"",""}, 147 | {"",""}, 148 | {"",""}, 149 | {"",""}, 150 | {"",""}, 151 | {"",""}, 152 | {"",""}, 153 | {"",""}, 154 | {"その他","Other"}, 155 | {"国内アニメ","Japanese animation"}, 156 | {"海外アニメ","Overseas animation"}, 157 | {"特撮","Special effects program"}, 158 | {"",""}, 159 | {"",""}, 160 | {"",""}, 161 | {"",""}, 162 | {"",""}, 163 | {"",""}, 164 | {"",""}, 165 | {"",""}, 166 | {"",""}, 167 | {"",""}, 168 | {"",""}, 169 | {"",""}, 170 | {"その他","Other"}, 171 | {"社会・時事","Social/topical news"}, 172 | {"歴史・紀行","History/travel"}, 173 | {"自然・動物・環境","Nature/animal/environment"}, 174 | {"宇宙・科学・医学","Universe/science/science of medicine"}, 175 | {"カルチャー・伝統文化","Culture/traditional culture"}, 176 | {"文学・文芸","Literature/liberal arts"}, 177 | {"スポーツ","Sports"}, 178 | {"ドキュメンタリー全般","General documentary"}, 179 | {"インタビュー・討論","Interview/discussion"}, 180 | {"",""}, 181 | {"",""}, 182 | {"",""}, 183 | {"",""}, 184 | {"",""}, 185 | {"",""}, 186 | {"その他","Other"}, 187 | {"現代劇・新劇","Modern play"}, 188 | {"ミュージカル","Musical"}, 189 | {"ダンス・バレエ","Dance/ballet"}, 190 | {"落語・演芸","Comic monologue (Rakugo)/ entertainment"}, 191 | {"歌舞伎・古典","Kabuki/classical play"}, 192 | {"",""}, 193 | {"",""}, 194 | {"",""}, 195 | {"",""}, 196 | {"",""}, 197 | {"",""}, 198 | {"",""}, 199 | {"",""}, 200 | {"",""}, 201 | {"",""}, 202 | {"その他","Other"}, 203 | {"旅・釣り・アウトドア","Travel/fishing/outdoors"}, 204 | {"園芸・ペット・手芸","Gardening/pet/ handicraft"}, 205 | {"音楽・美術・工芸","Music/art/ artifice"}, 206 | {"囲碁・将棋","Japanese go/chess (Shogi)"}, 207 | {"麻雀・パチンコ","Mah-jong/Pachinko"}, 208 | {"車・オートバイ","Automobile/motorcycle"}, 209 | {"コンピュータ・TVゲーム","Computer/TV game"}, 210 | {"会話・語学","Conversation/language"}, 211 | {"幼児・小学生","Infants/primary school students"}, 212 | {"中学生・高校生","Junior/senior high school students"}, 213 | {"大学生・受験","College/preparatory students"}, 214 | {"生涯教育・資格","Lifelong education/qulification"}, 215 | {"教育問題","Educational problem"}, 216 | {"",""}, 217 | {"",""}, 218 | {"その他","Other"}, 219 | {"高齢者","Aged persons"}, 220 | {"障害者","Handicapped person"}, 221 | {"社会福祉","Social welfare"}, 222 | {"ボランティア","Volunteers"}, 223 | {"手話","Sign language"}, 224 | {"文字(字幕)","Texts (caption)"}, 225 | {"音声解説","Audio commentary"}, 226 | {"",""}, 227 | {"",""}, 228 | {"",""}, 229 | {"",""}, 230 | {"",""}, 231 | {"",""}, 232 | {"",""}, 233 | {"",""}, 234 | {"",""}, 235 | {"",""}, 236 | {"",""}, 237 | {"",""}, 238 | {"",""}, 239 | {"",""}, 240 | {"",""}, 241 | {"",""}, 242 | {"",""}, 243 | {"",""}, 244 | {"",""}, 245 | {"",""}, 246 | {"",""}, 247 | {"",""}, 248 | {"",""}, 249 | {"",""}, 250 | {"",""}, 251 | {"",""}, 252 | {"",""}, 253 | {"",""}, 254 | {"",""}, 255 | {"",""}, 256 | {"",""}, 257 | {"",""}, 258 | {"",""}, 259 | {"",""}, 260 | {"",""}, 261 | {"",""}, 262 | {"",""}, 263 | {"",""}, 264 | {"",""}, 265 | {"",""}, 266 | {"",""}, 267 | {"",""}, 268 | {"",""}, 269 | {"",""}, 270 | {"",""}, 271 | {"",""}, 272 | {"",""}, 273 | {"",""}, 274 | {"",""}, 275 | {"",""}, 276 | {"",""}, 277 | {"",""}, 278 | {"",""}, 279 | {"",""}, 280 | {"",""}, 281 | {"",""}, 282 | {"",""}, 283 | {"",""}, 284 | {"",""}, 285 | {"",""}, 286 | {"",""}, 287 | {"",""}, 288 | {"",""}, 289 | {"",""}, 290 | {"",""}, 291 | {"",""}, 292 | {"",""}, 293 | {"",""}, 294 | {"",""}, 295 | {"",""}, 296 | {"",""}, 297 | {"",""}, 298 | {"その他","Other"} 299 | }; 300 | #define CSCAT_COUNT 3 301 | static CONTENT_TYPE ContentCSCatList[CSCAT_COUNT] = { 302 | {"スポーツ","Sports"}, 303 | {"洋画","Overseas movie"}, 304 | {"邦画","Japanese movie"} 305 | }; 306 | #define CSMIDDLECAT_COUNT 48 307 | static CONTENT_TYPE ContentCSMiddleCatList[CSMIDDLECAT_COUNT] = { 308 | {"テニス","Tennis"}, 309 | {"バスケットボール","Basketball"}, 310 | {"ラグビー","Rugby"}, 311 | {"アメリカンフットボール","Football"}, 312 | {"ボクシング","Boxing"}, 313 | {"プロレス","Professional wrestling"}, 314 | {"",""}, 315 | {"",""}, 316 | {"",""}, 317 | {"",""}, 318 | {"",""}, 319 | {"",""}, 320 | {"",""}, 321 | {"",""}, 322 | {"",""}, 323 | {"その他","Others"}, 324 | {"アクション","Action movies"}, 325 | {"SF/ファンタジー","SF/fantasy movies"}, 326 | {"コメディー","Comedy movies"}, 327 | {"サスペンス/ミステリー","Suspense/mystery movies"}, 328 | {"恋愛/ロマンス","Love/romance movies"}, 329 | {"ホラー/スリラー","Horror/thriller movies"}, 330 | {"ウエスタン","Western movies"}, 331 | {"ドラマ/社会派ドラマ","Drama/social drama"}, 332 | {"アニメーション","Animation movies"}, 333 | {"ドキュメンタリー","Documentary movies"}, 334 | {"アドベンチャー/冒険","Adventure movies"}, 335 | {"ミュージカル/音楽映画","Musical movies"}, 336 | {"ホームドラマ","Domestic drama"}, 337 | {"",""}, 338 | {"",""}, 339 | {"その他","Others"}, 340 | {"アクション","Action movies"}, 341 | {"SF/ファンタジー","SF/fantasy movies"}, 342 | {"お笑い/コメディー","Comedy"}, 343 | {"サスペンス/ミステリー","Suspense/mystery movies"}, 344 | {"恋愛/ロマンス","Love/romance movies"}, 345 | {"ホラー/スリラー","Horror/thriller movies"}, 346 | {"青春/学園/アイドル","Young/campus/idol dramas"}, 347 | {"任侠/時代劇","Japanese gangster/costume drama"}, 348 | {"アニメーション","Animation movies"}, 349 | {"ドキュメンタリー","Documentary movies"}, 350 | {"アドベンチャー/冒険","Adventure movies"}, 351 | {"ミュージカル/音楽映画","Musical movies"}, 352 | {"ホームドラマ","Domestic drama"}, 353 | {"",""}, 354 | {"",""}, 355 | {"その他","Others"} 356 | }; 357 | 358 | 359 | static char *getContentStr(unsigned char cat,unsigned char usernibble,int kbn,int lang) { 360 | CONTENT_TYPEA *large; 361 | CONTENT_TYPEA *middle; 362 | char *ret = ""; 363 | 364 | if (lang > 2) return ret; 365 | if (kbn > 2) return ret; 366 | 367 | 368 | large = (CONTENT_TYPEA *)ContentCatList; 369 | middle = (CONTENT_TYPEA *)ContentMiddleCatList; 370 | if (cat == 0xe1) { 371 | large = (CONTENT_TYPEA *)ContentCSCatList; 372 | middle = (CONTENT_TYPEA *)ContentCSMiddleCatList; 373 | cat = usernibble; 374 | if (cat > 0x2f) return ret; 375 | } 376 | 377 | switch(kbn) { 378 | case CONTENT_LARGE: 379 | return large[cat >> 4].lang[lang]; 380 | break; 381 | case CONTENT_MIDDLE: 382 | return middle[cat].lang[lang]; 383 | break; 384 | } 385 | return ret; 386 | } 387 | /* コンテント記述子 0xe0 番組付属情報 */ 388 | static char *getAttachInfo(unsigned char cat) { 389 | char *ret; 390 | ret=NULL; 391 | switch(cat) { 392 | case 0x00: ret = "中止の可能性あり"; break; 393 | case 0x01: ret = "延長の可能性あり"; break; 394 | case 0x02: ret = "中断の可能性あり"; break; 395 | case 0x03: ret = "同一シリーズの別話数放送の可能性あり"; break; 396 | case 0x04: ret = "編成未定枠"; break; 397 | case 0x05: ret = "繰り上げの可能性あり"; break; 398 | case 0x10: ret = "中断ニュースあり"; break; 399 | case 0x11: ret = "当該イベントに関連する臨時サービスあり"; break; 400 | case 0x20: ret = "当該イベント中に3D映像あり"; break; 401 | default: ret=""; 402 | } 403 | return ret; 404 | } 405 | static char *getVideoAspect(unsigned char cat) { 406 | char *ret; 407 | ret=""; 408 | switch(cat&0x0f) { 409 | case 0x01:ret = "4:3";break; 410 | case 0x02: 411 | case 0x03:ret = "16:9";break; 412 | case 0x04:ret = ">16:9";break; 413 | } 414 | return ret; 415 | } 416 | static char *getVideoResolution(unsigned char cat) { 417 | char *ret; 418 | ret=""; 419 | switch(cat&0xf0) { 420 | case 0x90:ret = "QFHD";break; 421 | case 0xb0: 422 | case 0xc0: 423 | case 0xe0:ret = "HD";break; 424 | case 0x00: 425 | case 0xa0:ret = "SD";break; 426 | } 427 | return ret; 428 | } 429 | 430 | /* 映像コンポーネント種別 */ 431 | static char *getVideoComponentDescStr(int cat) { 432 | char *ret; 433 | ret=NULL; 434 | switch (cat) { 435 | case 0x01: ret = "映像480i(525i)、アスペクト比4:3"; break; 436 | case 0x02: ret = "映像480i(525i)、アスペクト比16:9 パンベクトルあり"; break; 437 | case 0x03: ret = "映像480i(525i)、アスペクト比16:9 パンベクトルなし"; break; 438 | case 0x04: ret = "映像480i(525i)、アスペクト比 > 16:9"; break; 439 | case 0x91: ret = "映像2160p、アスペクト比4:3"; break; 440 | case 0x92: ret = "映像2160p、アスペクト比16:9 パンベクトルあり"; break; 441 | case 0x93: ret = "映像2160p、アスペクト比16:9 パンベクトルなし"; break; 442 | case 0x94: ret = "映像2160p、アスペクト比 > 16:9"; break; 443 | case 0xa1: ret = "映像480p(525p)、アスペクト比4:3"; break; 444 | case 0xa2: ret = "映像480p(525p)、アスペクト比16:9 パンベクトルあり"; break; 445 | case 0xa3: ret = "映像480p(525p)、アスペクト比16:9 パンベクトルなし"; break; 446 | case 0xa4: ret = "映像480p(525p)、アスペクト比 > 16:9"; break; 447 | case 0xb1: ret = "映像1080i(1125i)、アスペクト比4:3"; break; 448 | case 0xb2: ret = "映像1080i(1125i)、アスペクト比16:9 パンベクトルあり"; break; 449 | case 0xb3: ret = "映像1080i(1125i)、アスペクト比16:9 パンベクトルなし"; break; 450 | case 0xb4: ret = "映像1080i(1125i)、アスペクト比 > 16:9"; break; 451 | case 0xc1: ret = "映像720p(750p)、アスペクト比4:3"; break; 452 | case 0xc2: ret = "映像720p(750p)、アスペクト比16:9 パンベクトルあり"; break; 453 | case 0xc3: ret = "映像720p(750p)、アスペクト比16:9 パンベクトルなし"; break; 454 | case 0xc4: ret = "映像720p(750p)、アスペクト比 > 16:9"; break; 455 | case 0xd1: ret = "映像240p、アスペクト比4:3"; break; 456 | case 0xd2: ret = "映像240p、アスペクト比16:9 パンベクトルあり"; break; 457 | case 0xd3: ret = "映像240p、アスペクト比16:9 パンベクトルなし"; break; 458 | case 0xd4: ret = "映像240p、アスペクト比 > 16:9"; break; 459 | case 0xe1: ret = "映像1080p(1125p)、アスペクト比4:3"; break; 460 | case 0xe2: ret = "映像1080p(1125p)、アスペクト比16:9 パンベクトルあり"; break; 461 | case 0xe3: ret = "映像1080p(1125p)、アスペクト比16:9 パンベクトルなし"; break; 462 | case 0xe4: ret = "映像1080p(1125p)、アスペクト比 > 16:9"; break; 463 | default: 464 | ret = "映像不明"; 465 | } 466 | return ret; 467 | } 468 | /* 音声コンポーネント種別 */ 469 | static char *getAudioComponentDescStr(int cat) { 470 | char *ret; 471 | ret=NULL; 472 | switch (cat) { 473 | case 0x01: ret = "シングルモノ"; break; 474 | case 0x02: ret = "デュアルモノ"; break; 475 | case 0x03: ret = "ステレオ"; break; 476 | case 0x09: ret = "サラウンドステレオ"; break; 477 | default: 478 | ret = "音声不明"; 479 | } 480 | return ret; 481 | } 482 | /* */ 483 | static char *getTP(int freq) { 484 | char *ret; 485 | ret=""; 486 | switch (freq) { 487 | case 1172748: ret = "BS1"; break; 488 | case 1176584: ret = "BS3"; break; 489 | case 1180420: ret = "BS5"; break; 490 | case 1184256: ret = "BS7"; break; 491 | case 1188092: ret = "BS9"; break; 492 | case 1191928: ret = "BS11"; break; 493 | case 1195764: ret = "BS13"; break; 494 | case 1199600: ret = "BS15"; break; 495 | case 1203436: ret = "BS17"; break; 496 | case 1207272: ret = "BS19"; break; 497 | case 1211108: ret = "BS21"; break; 498 | case 1214944: ret = "BS23"; break; 499 | case 1229100: ret = "CS2"; break; 500 | case 1233100: ret = "CS4"; break; 501 | case 1237100: ret = "CS6"; break; 502 | case 1241100: ret = "CS4"; break; 503 | case 1245100: ret = "CS10"; break; 504 | case 1249100: ret = "CS12"; break; 505 | case 1253100: ret = "CS14"; break; 506 | case 1257100: ret = "CS16"; break; 507 | case 1261100: ret = "CS18"; break; 508 | case 1265100: ret = "CS20"; break; 509 | case 1269100: ret = "CS22"; break; 510 | case 1273100: ret = "CS24"; break; 511 | } 512 | return ret; 513 | } 514 | static char *getPolarization(int polarization) 515 | { 516 | char *ret; 517 | ret=""; 518 | switch (polarization) { 519 | case 0x00: ret = "水平";break; 520 | case 0x01: ret = "垂直";break; 521 | case 0x02: ret = "左旋";break; 522 | case 0x03: ret = "右旋";break; 523 | default:break; 524 | } 525 | return ret; 526 | } 527 | /* arib tr-b14 割り当てガイドラインより*/ 528 | static unsigned short getTSID2TP(unsigned short tsid) { 529 | return (tsid & 0x01f0)>>4; 530 | } 531 | static unsigned short getTSID2SLOT(unsigned short tsid) { 532 | /* for NHK BS */ 533 | if (tsid == 16625 || tsid == 16626) { 534 | tsid = tsid - 1; 535 | } 536 | return tsid & 0x0007; 537 | } 538 | static char *getTSID2BSCS(unsigned short tsid) { 539 | char *ret; 540 | ret=""; 541 | switch ((tsid & 0xf000)>>12) { 542 | case 4: ret = "BS";break; 543 | case 6: 544 | case 7: ret = "CS";break; 545 | default:break; 546 | } 547 | return ret; 548 | } 549 | 550 | static unsigned short freqToCH(unsigned short freq) 551 | { 552 | return ((freq/7)-473)/6 + 13; 553 | } 554 | 555 | static char *getBSCSGR(SVT_CONTROL *svtcur) { 556 | static char ret[10]; 557 | ret[0]=0; 558 | if (svtcur->original_network_id < 0x10) { 559 | return getTSID2BSCS(svtcur->transport_stream_id); 560 | } 561 | sprintf(ret,"GR%d",svtcur->remote_control_key_id); 562 | return ret; 563 | } 564 | #endif 565 | --------------------------------------------------------------------------------