OSDN Git Service

EPG収集
authorosx86_pt1 <rmitachi@ta2.so-net.ne.jp>
Wed, 6 Apr 2016 15:36:52 +0000 (00:36 +0900)
committerosx86_pt1 <rmitachi@ta2.so-net.ne.jp>
Wed, 6 Apr 2016 15:36:52 +0000 (00:36 +0900)
19 files changed:
iPTd_R2.sdf
src/Raym/Object.h
src/Raym/String.cpp
src/keys.h
src/mpeg2/ts/EIT.cpp
src/mpeg2/ts/EIT.h
src/mpeg2/ts/Header.cpp
src/mpeg2/ts/Header.h
src/mpeg2/ts/PAT.cpp
src/mpeg2/ts/PAT.h
src/mpeg2/ts/PMT.cpp
src/mpeg2/ts/PMT.h
src/mpeg2/ts/SDT.cpp
src/mpeg2/ts/SDT.h
src/mpeg2/ts/Table.cpp
src/mpeg2/ts/Table.h
src/ry0/iPTd/Analyzer.cpp
src/ry0/iPTd/Controller.cpp
src/ry0/iPTd/Controller.h

index b71acfb..390b9fb 100644 (file)
Binary files a/iPTd_R2.sdf and b/iPTd_R2.sdf differ
index d51bb21..4402313 100644 (file)
@@ -167,6 +167,7 @@ public:
     friend void RaymLock(Object *);\r
     friend void RaymUnlock(Object *);\r
     friend void RaymCondWait(Object *);\r
+    friend void RaymCondTimedWait(Object *, int msec);\r
     friend void RaymCondSignal(Object *);\r
     friend void RaymCondBroadcast(Object *);\r
 };\r
@@ -226,6 +227,24 @@ inline void RaymCondWait(Object *obj)
 #endif\r
 \r
 #ifndef RAYM_MUTEX_CHECK\r
+inline void RaymCondTimedWait(Object *obj, int msec)\r
+{\r
+#ifdef _WIN32\r
+    SleepConditionVariableCS(&(obj->_cond), &(obj->_cs), (DWORD)msec);\r
+#else\r
+#endif\r
+}\r
+#else\r
+#ifdef _WIN32\r
+#define RaymCondTimedWait(obj, msec) \\r
+    DebugLog3("before wait: %s %d", __FILE__, __LINE__); \\r
+    SleepConditionVariableCS(&(obj->_cond), &(obj->_cs), (DWORD)msec); \\r
+    DebugLog3("after wait: %s %d", __FILE__, __LINE__);\r
+#else\r
+#endif\r
+#endif\r
+\r
+#ifndef RAYM_MUTEX_CHECK\r
 inline void RaymCondSignal(Object *obj)\r
 {\r
 #ifdef _WIN32\r
index 6aacd5b..2fd9df9 100644 (file)
@@ -863,6 +863,14 @@ bool String::isEqualToString(String *string)
     bool result = false;\r
     if (string != NULL)\r
     {\r
+        if (_str == NULL)\r
+        {\r
+            DebugLog0("String::isEqualToString() : _str == NULL");\r
+        }\r
+        if (string->_str == NULL)\r
+        {\r
+            DebugLog0("String::isEqualToString() : string->_str == NULL");\r
+        }\r
         result = (strcmp(_str, string->_str) == 0);\r
     }\r
     return result;\r
index 26daa6c..c12b949 100644 (file)
@@ -52,6 +52,7 @@ static const char *KEY_RESULT                   = "Result";
 #define KEY_EPG_DATE                                            "Date"\r
 #define KEY_EPG_START                                           "Start"\r
 #define KEY_EPG_END                                             "End"\r
+#define KEY_EPG_DURATION                                        "Duration"\r
 #define KEY_EPG_TITLE                                           "Title"\r
 #define KEY_EPG_DESCRIPTION                                     "Description"\r
 #define KEY_EPG_CHANNEL                                         "Channel"\r
@@ -62,6 +63,9 @@ static const char *KEY_RESULT                   = "Result";
 #define KEY_EPG_REPEAT                                          "Repeat"\r
 #define KEY_EPG_KEYWORDS                                        "Keywords"\r
 #define KEY_EPG_RESERVED_BY_KEYWORDS                            "Reserved by keywords"\r
+#define KEY_EPG_EXT_ITEM_DESCRIPTION                            "Extended Item Description"\r
+#define KEY_EPG_EXT_ITEM                                        "Extended Item"\r
+#define KEY_EPG_EXT_ITEMS                                       "Extended Items"\r
 \r
 // ローカライズ用キー\r
 #define KEY_I18N_Main_Menu                                      "Main Menu"\r
index 47f37c0..d432db5 100644 (file)
@@ -1,9 +1,5 @@
-/*\r
- *  EIT.cpp\r
- *  PTxSystem\r
- *\r
- *  Created by Ryosuke Mitachi on 11/08/24.\r
- *  Copyright 2011 __MyCompanyName__. All rights reserved.\r
+/**\r
+ * @file EIT.cpp\r
  *\r
  */\r
 \r
@@ -22,23 +18,20 @@ EIT::EIT()
 \r
 EIT::EIT(EIT &eit)\r
 {\r
-//    printf("copy constructor.\n");\r
-    _table_id                       = eit._table_id;\r
-    _section_syntax_indicator       = eit._section_syntax_indicator;\r
-    _section_length                 = eit._section_length;\r
-    _service_id                     = eit._service_id;\r
-    _version_number                 = eit._version_number;\r
-    _current_next_indicator         = eit._current_next_indicator;\r
-    _section_number                 = eit._section_number;\r
-    _last_section_number            = eit._last_section_number;\r
-    _transport_stream_id            = eit._transport_stream_id;\r
-    _original_network_id            = eit._original_network_id;\r
-    _segment_last_section_number    = eit._segment_last_section_number;\r
-    _last_table_id                  = eit._last_table_id;\r
-\r
-    _event_offset                   = eit._event_offset;\r
-\r
-    _length                         = eit._length;\r
+    _table_id                    = eit._table_id;\r
+    _section_syntax_indicator    = eit._section_syntax_indicator;\r
+    _section_length              = eit._section_length;\r
+    _service_id                  = eit._service_id;\r
+    _version_number              = eit._version_number;\r
+    _current_next_indicator      = eit._current_next_indicator;\r
+    _section_number              = eit._section_number;\r
+    _last_section_number         = eit._last_section_number;\r
+    _transport_stream_id         = eit._transport_stream_id;\r
+    _original_network_id         = eit._original_network_id;\r
+    _segment_last_section_number = eit._segment_last_section_number;\r
+    _last_table_id               = eit._last_table_id;\r
+    _event_offset                = eit._event_offset;\r
+    _length                      = eit._length;\r
     memcpy(_event_data, eit._event_data, sizeof(_event_data));\r
 }\r
 \r
@@ -51,27 +44,20 @@ bool EIT::decode_section()
 {\r
     bool result = false;\r
 \r
-    /*\r
-     * 0x4E        : EIT(自ストリームの現在と次の番組)\r
-     * 0x4F        : EIT(他ストリームの現在と次の番組)\r
-     * 0x50 - 0x5F : EIT(自ストリーム、スケジュール)\r
-     * 0x60 - 0x6F : EIT(他ストリーム、スケジュール)\r
-     */\r
     _table_id = _section[0x00];\r
-\r
-    if ((0x4E <= _table_id) && (_table_id <= 0x6F))\r
+    if ((TABLE_ID_SELF <= _table_id) && (_table_id <= TABLE_ID_OTHER_SCHEDULE_END))\r
     {\r
-        _section_syntax_indicator       = (_section[0x01] & 0x80) >> 7;\r
-        _section_length                 = ((_section[0x01] << 8) + _section[0x02]) & 0x0FFF;\r
-        _service_id                     = (_section[0x03] << 8) + _section[0x04];\r
-        _version_number                 = (_section[0x05] & 0x3E) >> 1;\r
-        _current_next_indicator         = _section[0x05] & 0x01;\r
-        _section_number                 = _section[0x06];\r
-        _last_section_number            = _section[0x07];\r
-        _transport_stream_id            = (_section[0x08] << 8) + _section[0x09];\r
-        _original_network_id            = (_section[0x0a] << 8) + _section[0x0b];\r
-        _segment_last_section_number    = _section[0x0c];\r
-        _last_table_id                  = _section[0x0d];\r
+        _section_syntax_indicator    = (_section[0x01] & 0x80) >> 7;\r
+        _section_length              = ((_section[0x01] << 8) + _section[0x02]) & 0x0FFF;\r
+        _service_id                  = (_section[0x03] << 8) + _section[0x04];\r
+        _version_number              = (_section[0x05] & 0x3E) >> 1;\r
+        _current_next_indicator      = _section[0x05] & 0x01;\r
+        _section_number              = _section[0x06];\r
+        _last_section_number         = _section[0x07];\r
+        _transport_stream_id         = (_section[0x08] << 8) + _section[0x09];\r
+        _original_network_id         = (_section[0x0a] << 8) + _section[0x0b];\r
+        _segment_last_section_number = _section[0x0c];\r
+        _last_table_id               = _section[0x0d];\r
 \r
         if (GetCrc32(_section, _section_length + 3) == 0)\r
         {\r
@@ -80,17 +66,12 @@ bool EIT::decode_section()
             result = true;\r
         }\r
     }\r
-    else\r
-    {\r
-        printf("table id error. %d\n", _table_id);\r
-        reset();\r
-    }\r
+\r
     return result;\r
 }\r
 \r
 void EIT::reset()\r
 {\r
-    printf("EIT::reset\n");\r
     _table_id = 0;\r
     _section_length = 0;\r
     _event_offset = 0xFFFF;\r
@@ -98,8 +79,6 @@ void EIT::reset()
 \r
 EIT::Event *EIT::nextEvent()\r
 {\r
-printf("%s %d %d %d %d\n",__FUNCTION__, _table_id, _length, _section_length, _event_offset);\r
-//    if ((_table_id != 0) && (_length > 0) && (_length == _section_length + 3) && (_event_offset < (_length - 4)))\r
     if ((_event_offset >= 0x00) && (_event_offset + 0x0c < _section_length - 0x0e))\r
     {\r
         _event._event_id = (_event_data[_event_offset] << 8) + _event_data[_event_offset + 0x01];\r
@@ -119,9 +98,9 @@ printf("%s %d %d %d %d\n",__FUNCTION__, _table_id, _length, _section_length, _ev
             _event._st_year += 1900;\r
             _event._st_month -= 1;\r
         }\r
-        _event._st_hour  = ((_event_data[_event_offset + 0x04] & 0xF0) >> 4) * 10 + (_event_data[_event_offset + 0x04] & 0x0F);\r
-        _event._st_min   = ((_event_data[_event_offset + 0x05] & 0xF0) >> 4) * 10 + (_event_data[_event_offset + 0x05] & 0x0F);\r
-        _event._st_sec   = ((_event_data[_event_offset + 0x06] & 0xF0) >> 4) * 10 + (_event_data[_event_offset + 0x06] & 0x0F);\r
+        _event._st_hour = ((_event_data[_event_offset + 0x04] & 0xF0) >> 4) * 10 + (_event_data[_event_offset + 0x04] & 0x0F);\r
+        _event._st_min  = ((_event_data[_event_offset + 0x05] & 0xF0) >> 4) * 10 + (_event_data[_event_offset + 0x05] & 0x0F);\r
+        _event._st_sec  = ((_event_data[_event_offset + 0x06] & 0xF0) >> 4) * 10 + (_event_data[_event_offset + 0x06] & 0x0F);\r
 \r
         // duration\r
         _event._dur_hour = ((_event_data[_event_offset + 0x07] & 0xF0) >> 4) * 10 + (_event_data[_event_offset + 0x07] & 0x0F);\r
@@ -132,25 +111,16 @@ printf("%s %d %d %d %d\n",__FUNCTION__, _table_id, _length, _section_length, _ev
         _event._free_CA_mode = (_event_data[_event_offset + 0x0a] & 0x10) >> 4;\r
         _event._descriptors_loop_length = ((_event_data[_event_offset + 0x0a] & 0x0F) << 8) + _event_data[_event_offset + 0x0b];\r
 \r
-printf("descriptors_loop_length = %d\n", _event._descriptors_loop_length);\r
         if (_event_offset + 0x0c + _event._descriptors_loop_length <= _section_length)\r
-//        if (_event_offset + 0x0c + _event._descriptors_loop_length <= _length - 4)\r
         {\r
             _event._descriptor_ptr = &_event_data[_event_offset + 0x0c];\r
             _event._descriptor_offset = 0;\r
             _event_offset += (0x0c + _event._descriptors_loop_length);\r
-printf("next event_offset = %d\n", _event_offset);\r
+\r
             return &_event;\r
         }\r
-        else\r
-        {\r
-printf("check 001\n");\r
-        }\r
-    }\r
-    else\r
-    {\r
-printf("check 002\n");\r
     }\r
+\r
     _event._event_id = 0;\r
     _event._descriptors_loop_length = 0;\r
     return NULL;\r
@@ -158,7 +128,6 @@ printf("check 002\n");
 \r
 Descriptor *EIT::Event::nextDescriptor()\r
 {\r
-//printf("%s\n", __FUNCTION__);\r
     if (_descriptors_loop_length >= 2)\r
     {\r
         uint16_t len = Table::parseDescriptor(&_descriptor_ptr[_descriptor_offset], _descriptors_loop_length, &_descriptor);\r
index 480c14a..5419f2f 100644 (file)
-//
-// EIT.h
-//
-
-#ifndef __MPEG2_TS_EIT_H__
-#define __MPEG2_TS_EIT_H__
-
-#include "mpeg2/ts/Table.h"
-
-namespace MPEG2
-{
-
-namespace TS
-{
-
-#define MAXSECLEN 4096
-
-typedef struct _EIThead {
-       char table_id;
-       int section_syntax_indicator;
-       int reserved_future_use;
-       int reserved1;
-       int section_length;
-       int service_id;
-       int reserved2;
-       int version_number;
-       int current_next_indicator;
-       int section_number;
-       int last_section_number;
-       int transport_stream_id;
-       int original_network_id;
-       int segment_last_section_number;
-       int last_table_id;
-} EIThead;
-
-typedef struct _EITbody {
-       int event_id;
-       char start_time[5];
-       char duration[3];
-       int running_status;
-       int free_CA_mode;
-       int descriptors_loop_length;
-
-       //
-       int yy;
-       int mm;
-       int dd;
-       int hh;
-       int hm;
-       int ss;
-       int dhh;
-       int dhm;
-       int dss;
-} EITbody;
-
-typedef struct _SEVTdesc {
-       int  descriptor_tag;
-       int  descriptor_length;
-       char ISO_639_language_code[3];
-       int  event_name_length;
-       char event_name[MAXSECLEN];
-       int  text_length;
-       char text[MAXSECLEN];
-} SEVTdesc;
-
-typedef struct _EEVTDhead {
-       int  descriptor_tag;
-       int  descriptor_length;
-       int  descriptor_number;
-       int  last_descriptor_number;
-       char ISO_639_language_code[3];
-       int  length_of_items;
-} EEVTDhead;
-
-typedef struct _EEVTDitem {
-       int  item_description_length;
-       char item_description[MAXSECLEN];
-       int  item_length;
-       char item[MAXSECLEN];
-
-       //
-       int  descriptor_number;
-} EEVTDitem;
-
-typedef struct _EEVTDtail {
-       int  text_length;
-       char text[MAXSECLEN];
-} EEVTDtail;
-
-typedef struct _ContentDesc {
-       int descriptor_tag;
-       int descriptor_length;
-       char content[MAXSECLEN];
-} ContentDesc;
-
-typedef struct _SeriesDesc {
-       int descriptor_tag;
-       int descriptor_length;
-       int series_id;
-       int repeat_label;
-       int program_pattern;
-       int expire_date_valid_flag;
-       int expire_date;
-       int episode_number;
-       int last_episode_number;
-       char series_name_char[MAXSECLEN];
-} SeriesDesc;
-
-class EIT : public Table
-{
-protected:
-    bool decode_section();
-
-public:
-    uint8_t     _table_id;                      //  8
-    uint8_t     _section_syntax_indicator;      //  1
-                                                //  1   '1'
-                                                //  2   '11'
-    uint16_t    _section_length;                // 12
-    uint16_t    _service_id;                    // 16
-                                                //  2   '11'
-    uint8_t     _version_number;                //  5
-    uint8_t     _current_next_indicator;        //  1
-    uint8_t     _section_number;                //  8
-    uint8_t     _last_section_number;           //  8
-    uint16_t    _transport_stream_id;           // 16
-    uint16_t    _original_network_id;           // 16
-    uint8_t     _segment_last_section_number;   //  8
-    uint8_t     _last_table_id;                 //  8
-
-    class Event
-    {
-
-    public:
-        uint16_t    _event_id;                  // 16
-        // start_time                              40
-        uint16_t    _st_year;
-        uint8_t     _st_month;
-        uint8_t     _st_day;
-        uint8_t     _st_hour;
-        uint8_t     _st_min;
-        uint8_t     _st_sec;
-        // duration                                24
-        uint8_t     _dur_hour;
-        uint8_t     _dur_min;
-        uint8_t     _dur_sec;
-        uint8_t     _running_status;            //  3
-        uint8_t     _free_CA_mode;              //  1
-        uint16_t    _descriptors_loop_length;   // 12
-
-        uint8_t *   _descriptor_ptr;
-        uint16_t    _descriptor_offset;
-        Descriptor  _descriptor;
-        Descriptor *nextDescriptor();
-    };
-
-    uint8_t     _event_data[MAX_SECT_LEN];
-    uint16_t    _event_offset;
-    Event       _event;
-
-public:
-    EIT();
-    EIT(EIT &eit);
-    ~EIT();
-    void reset();
-
-    Event *nextEvent();
-};
-
-
-} // TS
-} // MPEG2
-#endif
+/**\r
+ * @file EIT.h\r
+ *\r
+ */\r
+\r
+#pragma once\r
+\r
+#include "mpeg2/ts/Table.h"\r
+\r
+namespace MPEG2\r
+{\r
+\r
+namespace TS\r
+{\r
+\r
+class EIT : public Table\r
+{\r
+protected:\r
+    bool decode_section();\r
+\r
+public:\r
+    /*\r
+     * 0x4E        : EIT(自ストリームの現在と次の番組)\r
+     * 0x4F        : EIT(他ストリームの現在と次の番組)\r
+     * 0x50 - 0x5F : EIT(自ストリーム、スケジュール)\r
+     * 0x60 - 0x6F : EIT(他ストリーム、スケジュール)\r
+     */\r
+    enum\r
+    {\r
+        TABLE_ID_SELF                   = 0x4E,\r
+        TABLE_ID_OTHER                  = 0x4F,\r
+        TABLE_ID_SELF_SCHEDULE_BEGIN    = 0x50,\r
+        TABLE_ID_SELF_SCHEDULE_END      = 0x5F,\r
+        TABLE_ID_OTHER_SCHEDULE_BEGIN   = 0x60,\r
+        TABLE_ID_OTHER_SCHEDULE_END     = 0x6F\r
+    };\r
+\r
+    uint8_t         _table_id;                      //  8\r
+    uint8_t         _section_syntax_indicator;      //  1\r
+                                                    //  1   '1'\r
+                                                    //  2   '11'\r
+    uint16_t        _section_length;                // 12\r
+    uint16_t        _service_id;                    // 16\r
+                                                    //  2   '11'\r
+    uint8_t         _version_number;                //  5\r
+    uint8_t         _current_next_indicator;        //  1\r
+    uint8_t         _section_number;                //  8\r
+    uint8_t         _last_section_number;           //  8\r
+    uint16_t        _transport_stream_id;           // 16\r
+    uint16_t        _original_network_id;           // 16\r
+    uint8_t         _segment_last_section_number;   //  8\r
+    uint8_t         _last_table_id;                 //  8\r
+\r
+    class Event\r
+    {\r
+\r
+    public:\r
+        uint16_t    _event_id;                      // 16\r
+        // start_time                                  40\r
+        uint16_t    _st_year;\r
+        uint8_t     _st_month;\r
+        uint8_t     _st_day;\r
+        uint8_t     _st_hour;\r
+        uint8_t     _st_min;\r
+        uint8_t     _st_sec;\r
+        // duration                                    24\r
+        uint8_t     _dur_hour;\r
+        uint8_t     _dur_min;\r
+        uint8_t     _dur_sec;\r
+        uint8_t     _running_status;                //  3\r
+        uint8_t     _free_CA_mode;                  //  1\r
+        uint16_t    _descriptors_loop_length;       // 12\r
+\r
+        uint8_t *   _descriptor_ptr;\r
+        uint16_t    _descriptor_offset;\r
+        Descriptor  _descriptor;\r
+        Descriptor *nextDescriptor();\r
+    };\r
+\r
+    uint8_t     _event_data[MAX_SECT_LEN];\r
+    uint16_t    _event_offset;\r
+    Event       _event;\r
+\r
+public:\r
+    EIT();\r
+    EIT(EIT &eit);\r
+    ~EIT();\r
+    void reset();\r
+\r
+    Event *nextEvent();\r
+};\r
+\r
+} // TS\r
+} // MPEG2\r
index 089c609..580fa05 100644 (file)
@@ -1,5 +1,6 @@
-/*
- *  Header.cpp
+/**
+ * @file Header.cpp
+ *
  */
 
 #include "mpeg2/ts/Header.h"
index 008f589..807ff47 100644 (file)
@@ -1,5 +1,6 @@
-/*
- *  Header.h
+/**
+ * @file Header.h
+ *
  */
 #pragma once
 
index dc92788..38aa4ae 100644 (file)
@@ -1,6 +1,8 @@
-/*
- *  PAT.cpp
+/**
+ * @file PAT.cpp
+ *
  */
+
 #include "mpeg2/ts/PAT.h"
 
 namespace MPEG2
@@ -41,7 +43,7 @@ PAT::~PAT()
 bool PAT::decode_section()
 {
     bool result = true;
-    _table_id                 = _section[0x00];
+    _table_id = _section[0x00];
     if (_table_id == TABLE_ID_PAT)
     {
         _section_syntax_indicator = (_section[0x01] & 0x80) >> 7;
@@ -106,4 +108,4 @@ bool PAT::isEqual(PAT *pat)
 }
 
 } // TS
-} // MPEG2
\ No newline at end of file
+} // MPEG2
index 9ac1292..3566421 100644 (file)
@@ -1,8 +1,9 @@
-/*
- *  PAT.h
+/**
+ * @file PAT.h
+ *
  */
-#ifndef __MPEG2_TS_PAT_H__
-#define __MPEG2_TS_PAT_H__
+
+#pragma once
 
 #include "mpeg2/ts/Table.h"
 
@@ -14,24 +15,25 @@ namespace TS
 class PAT : public Table
 {
 public:
-    uint8_t     _table_id;                  //  8
-    uint8_t     _section_syntax_indicator;  //  1
-                                            //  1  '0'
-                                            //  2  reserved
-    uint16_t    _section_length;            // 12
-    uint16_t    _transport_stream_id;       // 16
-                                            //  2  reserved
-    uint8_t     _version_number;            //  5
-    uint8_t     _current_next_indicator;    //  1
-    uint8_t     _section_number;            //  8
-    uint8_t     _last_section_number;       //  8
-    uint16_t    _program_count;
-    struct _program {
-        uint16_t    _program_number;        // 16
-                                            //  3  reserved
-        uint16_t    _pid;                   // 13
-    } *_programs;
-                                            // 32  CRC
+    uint8_t         _table_id;                  //  8
+    uint8_t         _section_syntax_indicator;  //  1
+                                                //  1  '0'
+                                                //  2  reserved
+    uint16_t        _section_length;            // 12
+    uint16_t        _transport_stream_id;       // 16
+                                                //  2  reserved
+    uint8_t         _version_number;            //  5
+    uint8_t         _current_next_indicator;    //  1
+    uint8_t         _section_number;            //  8
+    uint8_t         _last_section_number;       //  8
+    uint16_t        _program_count;
+    struct _program
+    {
+        uint16_t    _program_number;            // 16
+                                                //  3  reserved
+        uint16_t    _pid;                       // 13
+    } *             _programs;
+                                                // 32  CRC
 
 protected:
     bool decode_section();
@@ -46,4 +48,3 @@ public:
 
 } // TS
 } // MPEG2
-#endif
\ No newline at end of file
index 883a10b..4ed6c10 100644 (file)
@@ -1,5 +1,6 @@
-/*
- *  PMT.cpp
+/**
+ * @file PMT.cpp
+ *
  */
 
 #include "mpeg2/ts/PMT.h"
@@ -38,7 +39,7 @@ PMT::~PMT()
 bool PMT::decode_section()
 {
     bool result = true;
-    _table_id                 = _section[0x00];
+    _table_id = _section[0x00];
     if (_table_id == TABLE_ID_PMT)
     {
         _section_syntax_indicator = (_section[0x01] & 0x80) >> 7;
@@ -54,7 +55,7 @@ bool PMT::decode_section()
         {
             free(_descriptor);
         }
-        _descriptor               = (uint8_t *)malloc(_program_info_length);
+        _descriptor = (uint8_t *)malloc(_program_info_length);
         memcpy(_descriptor, &_section[0x0c], _program_info_length);
 
         if (_elements != NULL)
@@ -83,10 +84,10 @@ bool PMT::decode_section()
             {
                 _elements = (struct _element *)realloc(_elements, sizeof(struct _element) * (_element_count + 1));
             }
-            _elements[_element_count]._stream_type = _section[offset];
+            _elements[_element_count]._stream_type    = _section[offset];
             _elements[_element_count]._elementary_PID = ((_section[offset + 1] << 8) + _section[offset + 2]) & 0x1FFF;
             _elements[_element_count]._ES_info_length = ((_section[offset + 3] << 8) + _section[offset + 4]) & 0x0FFF;
-            _elements[_element_count]._descriptor = (uint8_t *)malloc(_elements[_element_count]._ES_info_length);
+            _elements[_element_count]._descriptor     = (uint8_t *)malloc(_elements[_element_count]._ES_info_length);
             memcpy(_elements[_element_count]._descriptor, &_section[offset + 5], _elements[_element_count]._ES_info_length);
             offset += (5 + _elements[_element_count]._ES_info_length);
             _element_count++;
@@ -103,6 +104,7 @@ bool PMT::decode_section()
 
 void PMT::reset()
 {
+    _table_id                 = 0;
     _section_syntax_indicator = 0;
     _section_length           = 0;
     _program_number           = 0;
@@ -133,4 +135,4 @@ void PMT::reset()
 }
 
 } // TS
-} // MPEG2
\ No newline at end of file
+} // MPEG2
index 9c6e726..5ef9660 100644 (file)
@@ -1,8 +1,9 @@
-/*
- *  PMT.h
+/**
+ * @file PMT.h
+ *
  */
-#ifndef __MPEG2_TS_PMT_H__
-#define __MPEG2_TS_PMT_H__
+
+#pragma once
 
 #include "mpeg2/ts/Table.h"
 
@@ -14,33 +15,33 @@ namespace TS
 class PMT : public Table
 {
 public:
-    uint8_t     _table_id;                  //  8
-    uint8_t     _section_syntax_indicator;  //  1
-                                            //  1  '0'
-                                            //  2  reserved
-    uint16_t    _section_length;            // 12
-    uint16_t    _program_number;            // 16
-                                            //  2  reserved
-    uint8_t     _version_number;            //  5
-    uint8_t     _current_next_indicator;    //  1
-    uint8_t     _section_number;            //  8
-    uint8_t     _last_section_number;       //  8
-                                            //  3  reserved
-    uint16_t    _PCR_PID;                   // 13
-                                            //  4  reserved
-    uint16_t    _program_info_length;       // 12
-    uint8_t *   _descriptor;                //  N
-    uint16_t    _element_count;
+    uint8_t         _table_id;                  //  8
+    uint8_t         _section_syntax_indicator;  //  1
+                                                //  1  '0'
+                                                //  2  reserved
+    uint16_t        _section_length;            // 12
+    uint16_t        _program_number;            // 16
+                                                //  2  reserved
+    uint8_t         _version_number;            //  5
+    uint8_t         _current_next_indicator;    //  1
+    uint8_t         _section_number;            //  8
+    uint8_t         _last_section_number;       //  8
+                                                //  3  reserved
+    uint16_t        _PCR_PID;                   // 13
+                                                //  4  reserved
+    uint16_t        _program_info_length;       // 12
+    uint8_t *       _descriptor;                //  N
+    uint16_t        _element_count;
     struct _element
     {
-        uint8_t     _stream_type;           //  8
-                                            //  3  reserved
-        uint16_t    _elementary_PID;        // 13
-                                            //  4  reserved
-        uint16_t    _ES_info_length;        // 12
-        uint8_t *   _descriptor;            //  N
-    } *_elements;
-                                            // 32  CRC
+        uint8_t     _stream_type;               //  8
+                                                //  3  reserved
+        uint16_t    _elementary_PID;            // 13
+                                                //  4  reserved
+        uint16_t    _ES_info_length;            // 12
+        uint8_t *   _descriptor;                //  N
+    } *             _elements;
+                                                // 32  CRC
 
 protected:
     bool decode_section();
@@ -53,4 +54,3 @@ public:
 
 } // TS
 } // MPEG2
-#endif
\ No newline at end of file
index 782091a..c15b032 100644 (file)
@@ -1,5 +1,6 @@
-/*\r
- *  SDT.cpp\r
+/**\r
+ * @file SDT.cpp\r
+ *\r
  */\r
 \r
 #include "b25/aribstr.h"\r
index 7b3cab3..2fe7b0e 100644 (file)
@@ -1,8 +1,9 @@
-//
-// SDT.h
-//
-#ifndef __MPEG2_TS_SDT_H__
-#define __MPEG2_TS_SDT_H__
+/**
+ * @file SDT.h
+ *
+ */
+
+#pragma once
 
 #include "mpeg2/ts/Table.h"
 
@@ -103,6 +104,3 @@ public:
 
 } // TS
 } // MPEG2
-#endif
-
-
index 007ae8c..b8f7e7a 100644 (file)
@@ -63,73 +63,13 @@ int Table::GetCrc32(
 \r
        return crc;\r
 }\r
-/*\r
-bool Table::decode(uint8_t *packet)\r
-{\r
-    bool result = false;\r
-\r
-    Header header(packet);\r
-\r
-    if (header._transport_error)\r
-    {\r
-        printf("transport error.\n");\r
-        return false;\r
-    }\r
-\r
-    if (header._payload_unit_start)\r
-    {\r
-        _pid = header._pid;\r
-        _length = 0;\r
-        memset(_section, 0x00, sizeof(_section));\r
-    }\r
-\r
-#if 0\r
-    if ((_pid == header._pid) && (_continuity_counter == header._continuity_counter))\r
-    {\r
-        // adaptation_field_control\r
-        if (header._adaptation_field_control != 0x02)\r
-        {\r
-            uint16_t length;\r
-            length = header._payload_unit_start ? ((((packet[0x06] << 8) + packet[0x07]) & 0x0FFF) + 3) : ((((_section[0x01] << 8) + _section[0x02]) & 0x0FFF) + 3);\r
-            uint8_t offset = 0x04;\r
-            if (header._adaptation_field_control == 0x03)\r
-            {\r
-                offset = offset + 1 + packet[0x04];\r
-            }\r
-            if (_length == 0)\r
-            {\r
-                // pointer_field\r
-                offset += 1;\r
-            }\r
-            uint16_t cpylen = ((length - _length) < (PACKET_SIZE - offset)) ? (length - _length) : (PACKET_SIZE - offset);\r
 \r
-            memcpy(&_section[_length], &packet[offset], cpylen);\r
-            _length += cpylen;\r
-            _continuty_counter++;\r
-\r
-            if (_length == length)\r
-            {\r
-                if (GetCrc32(_section, _length) == 0)\r
-                {\r
-                    // decode\r
-                    result = decode_section();\r
-                }\r
-            }\r
-        }\r
-    }\r
-#endif\r
-\r
-    return result;\r
-}\r
-*/\r
 bool Table::decode(Header *header, uint8_t *packet)\r
 {\r
     bool result = false;\r
 \r
     if (header->_adaptation_field_control != 0x02)\r
     {\r
-        uint16_t length;\r
-        length = header->_payload_unit_start ? ((((packet[0x06] << 8) + packet[0x07]) & 0x0FFF) + 3) : ((((_section[0x01] << 8) + _section[0x02]) & 0x0FFF) + 3);\r
         uint8_t offset = 0x04;\r
         if (header->_adaptation_field_control == 0x03)\r
         {\r
@@ -143,6 +83,7 @@ bool Table::decode(Header *header, uint8_t *packet)
                 if (packet[offset] != 0)\r
                 {\r
                     memcpy(&_section[_length], &packet[offset + 1], packet[offset]);\r
+                    _length += packet[offset];\r
                 }\r
                 result = decode_section();\r
                 _length = 0;\r
@@ -158,284 +99,221 @@ bool Table::decode(Header *header, uint8_t *packet)
     return result;\r
 }\r
 \r
-bool Table::decode_section()\r
-{\r
-    return false;\r
-}\r
-\r
 void Table::reset()\r
 {\r
-    printf("Table::reset\n");\r
     _pid = 0xFFFF;\r
     _length = 0;\r
     memset(_section, 0x00, sizeof(_section));\r
 }\r
 \r
-static int getBit(unsigned char *byte, int *pbit, int gbit)\r
+static uint16_t parseServiceDescriptor(uint8_t *buf, ServiceDescriptor *service)\r
 {\r
-       int pbyte = *pbit / 8;\r
-       unsigned char *fbyte = byte + pbyte;\r
-\r
-       int cutbit = *pbit - (pbyte * 8);\r
-       int lcutbit = 32 - (cutbit + gbit);\r
-\r
-       unsigned char tbuf[4]; //\r
-       unsigned int tnum;\r
-\r
-       memcpy(tbuf, fbyte, sizeof(unsigned char) * 4);\r
-\r
-       //\r
-       tbuf[0] = tbuf[0] << cutbit;\r
-       tbuf[0] = tbuf[0] >> cutbit;\r
-\r
-       //\r
-       tnum = tbuf[0] << 24 | tbuf[1] << 16 | tbuf[2] << 8 | tbuf[3];\r
-\r
-       //\r
-       tnum = tnum >> lcutbit;\r
-\r
-       *pbit += gbit;\r
-\r
-       return tnum;\r
-}\r
-\r
-#define MAXSECLEN 4096\r
-\r
-static void getStr(char *tostr, unsigned char *byte, int *pbit, int len)\r
-{\r
-    char str[MAXSECLEN];\r
-    int pbyte = *pbit / 8;\r
-    unsigned char *fbyte = byte + pbyte;\r
-\r
-    memset(str, 0, sizeof(char) * MAXSECLEN);\r
-    memcpy(str, fbyte, len);\r
-\r
-    *pbit += (len * 8);\r
-\r
-    AribToString(tostr, str, len);\r
-}\r
-\r
-static void getStr(char *tostr, unsigned char *byte, int len)\r
-{\r
-    char str[MAXSECLEN];\r
-\r
-    memset(str, 0, sizeof(char) * MAXSECLEN);\r
-    memcpy(str, byte, len);\r
-\r
-    AribToString(tostr, str, len);\r
-}\r
-\r
-static uint16_t parseContentDescriptor(uint8_t *buf, ContentDescriptor *content)\r
-{\r
-//    printf("%s\n", __FUNCTION__);\r
-    for (int i = 0; i < (content->descriptor_length / 2); ++i)\r
+    service->_descriptor_tag = buf[0];\r
+    service->_descriptor_length = buf[1];\r
+    service->_service_type = buf[2];\r
+    service->_service_provider_name_length = buf[3];\r
+    if (service->_service_provider_name_length > 0)\r
     {\r
-        content->contents[i].content_nibble_level_1 = (buf[i * 2 + 0x02] & 0xF0) >> 4;\r
-        content->contents[i].content_nibble_level_2 = buf[i * 2 + 0x02] & 0x0F;\r
-        content->contents[i].user_nibble_1 = (buf[i * 2 + 0x03] & 0xF0) >> 4;\r
-        content->contents[i].user_nibble_2 = buf[i * 2 + 0x03] & 0x0F;\r
+        memcpy(service->_service_provider_name, &buf[4], service->_service_provider_name_length);\r
     }\r
-    return content->descriptor_length + 2;\r
+    service->_service_name_length = buf[4 + service->_service_provider_name_length];\r
+    if (service->_service_name_length > 0)\r
+    {\r
+        memcpy(service->_service_name, &buf[5 + service->_service_provider_name_length], service->_service_name_length);\r
+    }\r
+    return service->_descriptor_length + 2;\r
 }\r
 \r
 static uint16_t parseShortEventDescriptor(uint8_t *buf, ShortEventDescriptor *short_event)\r
 {\r
-//    printf("%s\n", __FUNCTION__);\r
-    uint16_t result = short_event->descriptor_length + 2;\r
-#if 0\r
-    memcpy(&short_event->ISO_639_language_code[0], &buf[0x02], 3);\r
-    short_event->event_name_length = buf[0x05];\r
-    if ((short_event->event_name_length + 5) <= short_event->descriptor_length)\r
+    short_event->_descriptor_tag = buf[0];\r
+    short_event->_descriptor_length = buf[1];\r
+    memcpy(short_event->_ISO_639_language_code, &buf[2], 3);\r
+    short_event->_event_name_length = buf[5];\r
+    if (short_event->_event_name_length > 0)\r
     {\r
-//        memcpy(&short_event->event_name[0], &buf[0x06], short_event->event_name_length);\r
-        getStr((char *)short_event->event_name, &buf[0x06], short_event->event_name_length);\r
-        short_event->text_length = buf[short_event->event_name_length + 6];\r
-        if ((short_event->text_length + short_event->event_name_length + 5) == short_event->descriptor_length)\r
-        {\r
-//            memcpy(&short_event->text[0], &buf[short_event->event_name_length + 6], short_event->text_length);\r
-            getStr((char *)short_event->text, &buf[short_event->event_name_length + 6], short_event->text_length);\r
-//            printf("%s() success.\n", __FUNCTION__);\r
-        }\r
-        else\r
-        {\r
-            printf("%s() event_name_length = %d\n", __FUNCTION__, short_event->event_name_length);\r
-            printf("%s() text_length error. %d\n", __FUNCTION__, short_event->text_length);\r
-            result = 0;\r
-        }\r
+        memcpy(short_event->_event_name, &buf[6], short_event->_event_name_length);\r
     }\r
-    else\r
+    short_event->_text_length = buf[6 + short_event->_event_name_length];\r
+    if (short_event->_text_length > 0)\r
     {\r
-        printf("%s() descriptor_length = %d\n", __FUNCTION__, short_event->descriptor_length);\r
-        printf("%s() event_name_length error. %d\n", __FUNCTION__, short_event->event_name_length);\r
-        result = 0;\r
+        memcpy(short_event->_text, &buf[7 + short_event->_event_name_length], short_event->_text_length);\r
     }\r
-#else\r
-    int boff = 0;\r
-\r
-    memset(short_event, 0, sizeof(ShortEventDescriptor));\r
-\r
-    short_event->descriptor_tag = getBit(buf, &boff, 8);\r
-    if ((short_event->descriptor_tag & 0xFF) == 0x4D)\r
-    {\r
-        short_event->descriptor_length = getBit(buf, &boff, 8);\r
-        memcpy(short_event->ISO_639_language_code, buf + boff / 8, 3);\r
-        /* desc->ISO_639_language_code = getBit(data, &boff, 24); */\r
-        boff += 24;\r
-\r
-        short_event->event_name_length = getBit(buf, &boff, 8);\r
-//        memset((char *)short_event->event_name, 0x00, MAX_DESC_LEN);\r
-//        getStr((char *)short_event->event_name, buf, &boff, short_event->event_name_length);\r
-        memcpy((char *)short_event->event_name, buf + boff / 8, short_event->event_name_length);\r
-        boff += short_event->event_name_length * 8;\r
-\r
-        short_event->text_length = getBit(buf, &boff, 8);\r
-//        memset((char *)short_event->text, 0x00, MAX_DESC_LEN);\r
-//        getStr((char *)short_event->text, buf, &boff, short_event->text_length);\r
-        memcpy((char *)short_event->text, buf + boff / 8, short_event->text_length);\r
-    }\r
-    else\r
-    {\r
-        result = false;\r
-    }\r
-#endif\r
-    return result;\r
+    return short_event->_descriptor_length + 2;\r
 }\r
 \r
 static uint16_t parseExtendedEventDescriptor(uint8_t *buf, ExtendedEventDescriptor *extended)\r
 {\r
-//    printf("%s\n", __FUNCTION__);\r
-    uint16_t result = extended->descriptor_length + 2;\r
-#if 1\r
-    extended->descriptor_number = (buf[0x02] & 0xF0) >> 4;\r
-    extended->last_descriptor_number = buf[0x02] & 0x0F;\r
-    memcpy(&extended->ISO_639_language_code[0], &buf[0x03], 3);\r
-    extended->length_of_items = buf[0x06];\r
-    extended->item_count = 0;\r
-    if ((extended->length_of_items + 6) <= extended->descriptor_length)\r
+    extended->_descriptor_tag = buf[0x00];\r
+    extended->_descriptor_length = buf[0x01];\r
+    extended->_descriptor_number = (buf[0x02] & 0xF0) >> 4;\r
+    extended->_last_descriptor_number = buf[0x02] & 0x0F;\r
+    memcpy(&extended->_ISO_639_language_code[0], &buf[0x03], 3);\r
+    extended->_length_of_items = buf[0x06];\r
+    extended->_item_count = 0;\r
+    if ((extended->_length_of_items + 6) <= extended->_descriptor_length)\r
     {\r
-        extended->text_length = 0;\r
-        extended->text_length = buf[extended->length_of_items + 7];\r
-        if ((extended->text_length + extended->length_of_items + 6) == extended->descriptor_length)\r
+        extended->_text_length = buf[extended->_length_of_items + 7];\r
+        if ((extended->_text_length + extended->_length_of_items + 6) == extended->_descriptor_length)\r
         {\r
-            memcpy(&extended->text[0], &buf[extended->length_of_items + 7], extended->text_length);\r
-//            memset((char *)extended->text, 0x00, MAX_DESC_LEN);\r
-//            getStr((char *)extended->text, &buf[extended->length_of_items + 7], extended->text_length);\r
+            memcpy(&extended->_text[0], &buf[extended->_length_of_items + 7], extended->_text_length);\r
 \r
-            int item_remain = extended->length_of_items;\r
+            int item_remain = extended->_length_of_items;\r
             int item_offset = 0x07;\r
             while (item_remain >= 2)\r
             {\r
-                extended->items[extended->item_count].item_description_length = buf[item_offset++];\r
-                if (extended->items[extended->item_count].item_description_length > 0)\r
+                extended->_items[extended->_item_count]._item_description_length = buf[item_offset++];\r
+                if (extended->_items[extended->_item_count]._item_description_length > 0)\r
                 {\r
-                    memcpy(&extended->items[extended->item_count].item_description[0], &buf[item_offset],\r
-                           extended->items[extended->item_count].item_description_length);\r
-//                    memset((char *)&extended->items[extended->item_count].item_description[0], 0x00, MAX_DESC_LEN);\r
-//                    getStr((char *)&extended->items[extended->item_count].item_description[0], &buf[item_offset],\r
-//                           extended->items[extended->item_count].item_description_length);\r
-                    item_offset += extended->items[extended->item_count].item_description_length;\r
+                    memcpy(&extended->_items[extended->_item_count]._item_description[0], &buf[item_offset],\r
+                           extended->_items[extended->_item_count]._item_description_length);\r
+                    item_offset += extended->_items[extended->_item_count]._item_description_length;\r
                 }\r
-                item_remain -= (1 + extended->items[extended->item_count].item_description_length);\r
+                item_remain -= (1 + extended->_items[extended->_item_count]._item_description_length);\r
                 if (item_remain < 1)\r
                 {\r
                     printf("%s item desc len error.\n", __FUNCTION__);\r
-                    result = 0;\r
                     break;\r
                 }\r
                 \r
-                extended->items[extended->item_count].item_length = buf[item_offset++];\r
-                if (extended->items[extended->item_count].item_length > 0)\r
+                extended->_items[extended->_item_count]._item_length = buf[item_offset++];\r
+                if (extended->_items[extended->_item_count]._item_length > 0)\r
                 {\r
-                    memcpy(&extended->items[extended->item_count].item[0], &buf[item_offset],\r
-                           extended->items[extended->item_count].item_length);\r
-//                    memset((char *)&extended->items[extended->item_count].item[0], 0x00, MAX_DESC_LEN);\r
-//                    getStr((char *)&extended->items[extended->item_count].item[0], &buf[item_offset],\r
-//                           extended->items[extended->item_count].item_length);\r
-                    item_offset += extended->items[extended->item_count].item_length;\r
+                    memcpy(&extended->_items[extended->_item_count]._item[0], &buf[item_offset],\r
+                           extended->_items[extended->_item_count]._item_length);\r
+                    item_offset += extended->_items[extended->_item_count]._item_length;\r
                 }\r
-                item_remain -= (1 + extended->items[extended->item_count].item_length);\r
+                item_remain -= (1 + extended->_items[extended->_item_count]._item_length);\r
                 if ((item_remain < 0) || (item_remain == 1))\r
                 {\r
                     printf("%s item len error. %d\n", __FUNCTION__, item_remain);\r
-                    result = 0;\r
                     break;\r
                 }\r
-                else {\r
-//                    printf("eevt success.\n");\r
-                }\r
 \r
-                ++extended->item_count;\r
+                ++extended->_item_count;\r
             }\r
         }\r
-        else\r
-        {\r
-            printf("%s() length_of_items = %d\n", __FUNCTION__, extended->length_of_items);\r
-            printf("%s() text_length error. %d\n", __FUNCTION__, extended->text_length);\r
-            result = 0;\r
-        }\r
     }\r
-    else\r
+\r
+    return extended->_descriptor_length + 2;\r
+}\r
+\r
+static uint16_t parseComponentDescriptor(uint8_t *buf, ComponentDescriptor *component)\r
+{\r
+    component->_descriptor_tag = buf[0];\r
+    component->_descriptor_length = buf[1];\r
+\r
+    return component->_descriptor_length + 2;\r
+}\r
+\r
+static uint16_t parseContentDescriptor(uint8_t *buf, ContentDescriptor *content)\r
+{\r
+    content->_descriptor_tag = buf[0];\r
+    content->_descriptor_length = buf[1];\r
+    for (int i = 0; i < (content->_descriptor_length / 2); ++i)\r
     {\r
-        printf("%s() descriptor_length = %d\n", __FUNCTION__, extended->descriptor_length);\r
-        printf("%s() length_of_items error. %d\n", __FUNCTION__, extended->length_of_items);\r
-        result = 0;\r
+        content->_contents[i]._content_nibble_level_1 = (buf[i * 2 + 0x02] & 0xF0) >> 4;\r
+        content->_contents[i]._content_nibble_level_2 = buf[i * 2 + 0x02] & 0x0F;\r
+        content->_contents[i]._user_nibble_1 = (buf[i * 2 + 0x03] & 0xF0) >> 4;\r
+        content->_contents[i]._user_nibble_2 = buf[i * 2 + 0x03] & 0x0F;\r
     }\r
-#else\r
-#endif\r
-    return result;\r
+    return content->_descriptor_length + 2;\r
+}\r
+\r
+static uint16_t parseDigitalCopyControlDescriptor(uint8_t *buf, DigitalCopyControlDescriptor *digital_copy_control)\r
+{\r
+    digital_copy_control->_descriptor_tag = buf[0];\r
+    digital_copy_control->_descriptor_length = buf[1];\r
+\r
+    return digital_copy_control->_descriptor_length + 2;\r
+}\r
+\r
+static uint16_t parseAudioComponentDescriptor(uint8_t *buf, AudioComponentDescriptor *audio_component)\r
+{\r
+    audio_component->_descriptor_tag = buf[0];\r
+    audio_component->_descriptor_length = buf[1];\r
+    audio_component->_stream_content = buf[2] & 0x0F;\r
+    audio_component->_component_type = buf[3];\r
+    audio_component->_component_tag = buf[4];\r
+    audio_component->_stream_type = buf[5];\r
+    audio_component->_simulcast_group_tag = buf[6];\r
+    audio_component->_ES_multi_lingual_flag = buf[7] >> 7;\r
+    audio_component->_main_component_flag = (buf[7] >> 6) & 0x01;\r
+    audio_component->_quality_indicator = (buf[7] >> 4) & 0x03;\r
+    audio_component->_sampling_rate = (buf[7] >> 1) & 0x07;\r
+    memcpy(audio_component->_ISO_639_language_code, &buf[8], 3);\r
+    if (audio_component->_ES_multi_lingual_flag == 1)\r
+    {\r
+        memcpy(audio_component->_ISO_639_language_code_2, &buf[11], 3);\r
+    }\r
+    uint8_t cpylen = audio_component->_descriptor_length - (9 + audio_component->_ES_multi_lingual_flag * 3);\r
+    memcpy(audio_component->_text_char, &buf[11 + audio_component->_ES_multi_lingual_flag * 3], cpylen);\r
+    return audio_component->_descriptor_length + 2;\r
+}\r
+\r
+static uint16_t parseSeriesDescriptor(uint8_t *buf, SeriesDescriptor *series)\r
+{\r
+    series->_descriptor_tag = buf[0];\r
+    series->_descriptor_length = buf[1];\r
+\r
+    return series->_descriptor_length + 2;\r
 }\r
 \r
 uint16_t Table::parseDescriptor(uint8_t *buf, uint16_t length, Descriptor *descriptor)\r
 {\r
     uint16_t result = 0;\r
 \r
-    descriptor->other.descriptor_tag    = buf[0x00];\r
-    descriptor->other.descriptor_length = buf[0x01];\r
+    descriptor->_other._descriptor_tag    = buf[0x00];\r
+    descriptor->_other._descriptor_length = buf[0x01];\r
 \r
     // length check\r
-    if ((descriptor->other.descriptor_length + 2) <= length)\r
+    if ((descriptor->_other._descriptor_length + 2) <= length)\r
     {\r
-        switch (descriptor->other.descriptor_tag)\r
+        switch (descriptor->_other._descriptor_tag)\r
         {\r
-        case 0x4D: // Short event descriptor\r
-            result = parseShortEventDescriptor(buf, &descriptor->short_event);\r
+        case TAG_SERVICE_DESCRIPTOR:\r
+            result = parseServiceDescriptor(buf, &descriptor->_service);\r
             break;\r
 \r
-        case 0x4E: // Extended event descriptor\r
-            result = parseExtendedEventDescriptor(buf, &descriptor->extended_event);\r
+        case TAG_SHORT_EVENT_DESCRIPTOR:\r
+            result = parseShortEventDescriptor(buf, &descriptor->_short_event);\r
             break;\r
 \r
-        case 0x54: // Content descriptor\r
-            result = parseContentDescriptor(buf, &descriptor->content);\r
+        case TAG_EXTENDED_EVENT_DESCRIPTOR:\r
+            result = parseExtendedEventDescriptor(buf, &descriptor->_extended_event);\r
             break;\r
 \r
-        case 0x50: // Component\r
-//            result = parseComponentDescriptor(hoge);\r
-            result = descriptor->other.descriptor_length + 2;\r
+        case TAG_COMPONENT_DESCRIPTOR:\r
+            result = parseComponentDescriptor(buf, &descriptor->_component);\r
             break;\r
 \r
-        case 0xC4: // Audio Component \r
-//            result = parseAudioComponentDescriptor(hoge);\r
-            result = descriptor->other.descriptor_length + 2;\r
+        case TAG_CONTENT_DESCRIPTOR:\r
+            result = parseContentDescriptor(buf, &descriptor->_content);\r
             break;\r
 \r
+        case TAG_DIGITAL_COPY_CONTROL_DESCRIPTOR:\r
+            result = parseDigitalCopyControlDescriptor(buf, &descriptor->_digital_copy_control);\r
+            break;\r
+\r
+        case TAG_AUDIO_COMPONENT_DESCRIPTOR:\r
+            result = parseAudioComponentDescriptor(buf, &descriptor->_audio_component);\r
+            break;\r
 \r
-        case 0xD5: // Series descriptor\r
-//            result = parseSeriesDescriptor(hoge);\r
-            result = descriptor->other.descriptor_length + 2;\r
+        case TAG_SERIES_DESCRIPTOR:\r
+            result = parseSeriesDescriptor(buf, &descriptor->_series);\r
             break;\r
 \r
         default:\r
-            memcpy(&descriptor->other.descriptor[0], &buf[0x02], descriptor->other.descriptor_length);\r
-            result = descriptor->other.descriptor_length + 2;\r
+            memcpy(&descriptor->_other._descriptor[0], &buf[0x02], descriptor->_other._descriptor_length);\r
+            result = descriptor->_other._descriptor_length + 2;\r
             break;\r
         }\r
     }\r
     else\r
     {\r
         printf("%s() length = %d\n", __FUNCTION__, length);\r
-        printf("%s() descriptor_tag = %d\n", __FUNCTION__, descriptor->other.descriptor_tag);\r
-        printf("%s() descriptor_length error. %d\n", __FUNCTION__, descriptor->other.descriptor_length);\r
+        printf("%s() descriptor_tag = %d\n", __FUNCTION__, descriptor->_other._descriptor_tag);\r
+        printf("%s() descriptor_length error. %d\n", __FUNCTION__, descriptor->_other._descriptor_length);\r
         result = 0;\r
 //        abort();\r
     }\r
@@ -443,4 +321,4 @@ uint16_t Table::parseDescriptor(uint8_t *buf, uint16_t length, Descriptor *descr
 }\r
 \r
 } // TS\r
-} // MPEG2
\ No newline at end of file
+} // MPEG2\r
index 06d4026..b512f72 100644 (file)
@@ -27,122 +27,166 @@ enum
 \r
 enum\r
 {\r
-    TAG_BOUQUET_NAME_DESCRIPTOR     = 0x47,\r
-    TAG_SERVICE_DESCRIPTOR          = 0x48,\r
-    TAG_SHORT_EVENT_DESCRIPTOR      = 0x4D,\r
-    TAG_EXTENDED_EVENT_DESCRIPTOR   = 0x4E,\r
-    TAG_COMPONENT_DESCRIPTOR        = 0x50,\r
-    TAG_CONTENT_DESCRIPTOR          = 0x54,\r
-    TAG_SERIES_DESCRIPTOR           = 0xD5,\r
+    TAG_BOUQUET_NAME_DESCRIPTOR         = 0x47,\r
+    TAG_SERVICE_DESCRIPTOR              = 0x48,\r
+    TAG_SHORT_EVENT_DESCRIPTOR          = 0x4D,\r
+    TAG_EXTENDED_EVENT_DESCRIPTOR       = 0x4E,\r
+    TAG_COMPONENT_DESCRIPTOR            = 0x50,\r
+    TAG_CONTENT_DESCRIPTOR              = 0x54,\r
     TAG_EVENT_GROUP_DESCRIPTOR          = 0xD6,\r
     TAG_DIGITAL_COPY_CONTROL_DESCRIPTOR = 0xC1,\r
     TAG_AUDIO_COMPONENT_DESCRIPTOR      = 0xC4,\r
+    TAG_DATA_CONTENT_DESCRIPTOR         = 0xC7,\r
+    TAG_SERIES_DESCRIPTOR               = 0xD5\r
 };\r
 \r
 // 6.2.1 Bouquet name descriptor\r
 typedef struct _BouquetNameDescriptor\r
 {\r
-    uint8_t         descriptor_tag;                         //  8\r
-    uint8_t         descriptor_length;                      //  8\r
-    uint8_t         descriptor[MAX_DESC_LEN];               //  8 x N\r
+    uint8_t         _descriptor_tag;                        //  8\r
+    uint8_t         _descriptor_length;                     //  8\r
+    uint8_t         _descriptor[MAX_DESC_LEN];              //  8 x N\r
 } BouquetNameDescriptor;\r
 \r
+// 6.2.3 Component descriptor\r
+typedef struct _ComponentDescriptor\r
+{\r
+    uint8_t         _descriptor_tag;                        //  8\r
+    uint8_t         _descriptor_length;                     //  8\r
+    uint8_t         _reserved_future_use;                   //  4\r
+    uint8_t         _stream_content;                        //  4\r
+    uint8_t         _component_type;                        //  8\r
+    uint8_t         _component_tag;                         //  8\r
+    uint8_t         _ISO_639_language_code[3];              //  24\r
+    uint8_t         _text_char[MAX_DESC_LEN];               //  8 x N\r
+} ComponentDescriptor;\r
+\r
 // 6.2.4 Content descriptor\r
 typedef struct _ContentDescriptor\r
 {\r
-    uint8_t         descriptor_tag;                         //  8\r
-    uint8_t         descriptor_length;                      //  8\r
+    uint8_t         _descriptor_tag;                        //  8\r
+    uint8_t         _descriptor_length;                     //  8\r
     struct\r
     {\r
-        uint8_t     content_nibble_level_1;                 //  4\r
-        uint8_t     content_nibble_level_2;                 //  4\r
-        uint8_t     user_nibble_1;                          //  4\r
-        uint8_t     user_nibble_2;                          //  4\r
-    } contents[MAX_DESC_LEN/2];                             // 16 x N\r
+        uint8_t     _content_nibble_level_1;                //  4\r
+        uint8_t     _content_nibble_level_2;                //  4\r
+        uint8_t     _user_nibble_1;                         //  4\r
+        uint8_t     _user_nibble_2;                         //  4\r
+    } _contents[MAX_DESC_LEN/2];                            // 16 x N\r
 } ContentDescriptor;\r
 \r
 // 6.2.7 Extended event descriptor\r
 typedef struct _ExtendedEventDescriptor\r
 {\r
-    uint8_t         descriptor_tag;                         //  8\r
-    uint8_t         descriptor_length;                      //  8\r
-    uint8_t         descriptor_number;                      //  4\r
-    uint8_t         last_descriptor_number;                 //  4\r
-    uint8_t         ISO_639_language_code[3];               // 24\r
-    uint8_t         length_of_items;                        //  8\r
-    uint8_t         item_count;\r
+    uint8_t         _descriptor_tag;                        //  8\r
+    uint8_t         _descriptor_length;                     //  8\r
+    uint8_t         _descriptor_number;                     //  4\r
+    uint8_t         _last_descriptor_number;                //  4\r
+    uint8_t         _ISO_639_language_code[3];              // 24\r
+    uint8_t         _length_of_items;                       //  8\r
+    uint8_t         _item_count;\r
     struct\r
     {\r
-        uint8_t     item_description_length;                //  8\r
-        uint8_t     item_description[MAX_DESC_LEN];         //  8 x N\r
-        uint8_t     item_length;                            //  8\r
-        uint8_t     item[MAX_DESC_LEN];                     //  8 x N\r
-    } items[MAX_DESC_LEN/2];\r
-    uint8_t         text_length;                            //  8\r
-    uint8_t         text[MAX_DESC_LEN];                     //  8 x N\r
+        uint8_t     _item_description_length;               //  8\r
+        uint8_t     _item_description[MAX_DESC_LEN];        //  8 x N\r
+        uint8_t     _item_length;                           //  8\r
+        uint8_t     _item[MAX_DESC_LEN];                    //  8 x N\r
+    } _items[MAX_DESC_LEN/2];\r
+    uint8_t         _text_length;                           //  8\r
+    uint8_t         _text[MAX_DESC_LEN];                    //  8 x N\r
 } ExtendedEventDescriptor;\r
 \r
 // 6.2.13 Service descriptor\r
 typedef struct _ServiceDescriptor\r
 {\r
-    uint8_t         descriptor_tag;                         //  8\r
-    uint8_t         descriptor_length;                      //  8\r
-    uint8_t         service_type;                           //  8\r
-    uint8_t         service_provider_name_length;           //  8\r
-    uint8_t         service_provider_name[MAX_DESC_LEN];    //  8 x N\r
-    uint8_t         service_name_length;                    //  8\r
-    uint8_t         service_name[MAX_DESC_LEN];             //  8 x N\r
+    uint8_t         _descriptor_tag;                        //  8\r
+    uint8_t         _descriptor_length;                     //  8\r
+    uint8_t         _service_type;                          //  8\r
+    uint8_t         _service_provider_name_length;          //  8\r
+    uint8_t         _service_provider_name[MAX_DESC_LEN];   //  8 x N\r
+    uint8_t         _service_name_length;                   //  8\r
+    uint8_t         _service_name[MAX_DESC_LEN];            //  8 x N\r
 } ServiceDescriptor;\r
 \r
 // 6.2.15 Short event descriptor\r
 typedef struct _ShortEventDescriptor\r
 {\r
-    uint8_t         descriptor_tag;                         //  8\r
-    uint8_t         descriptor_length;                      //  8\r
-    uint8_t         ISO_639_language_code[3];               // 24\r
-    uint8_t         event_name_length;                      //  8\r
-    uint8_t         event_name[MAX_DESC_LEN];               //  8 x N\r
-    uint8_t         text_length;                            //  8\r
-    uint8_t         text[MAX_DESC_LEN];                     //  8 x N\r
+    uint8_t         _descriptor_tag;                        //  8\r
+    uint8_t         _descriptor_length;                     //  8\r
+    uint8_t         _ISO_639_language_code[3];              // 24\r
+    uint8_t         _event_name_length;                     //  8\r
+    uint8_t         _event_name[MAX_DESC_LEN];              //  8 x N\r
+    uint8_t         _text_length;                           //  8\r
+    uint8_t         _text[MAX_DESC_LEN];                    //  8 x N\r
 } ShortEventDescriptor;\r
 \r
+// 6.2.23 Digital copy control descriptor\r
+typedef struct _DigitalCopyControlDescriptor\r
+{\r
+    uint8_t         _descriptor_tag;                        //  8\r
+    uint8_t         _descriptor_length;                     //  8\r
+\r
+} DigitalCopyControlDescriptor;\r
+\r
+// 6.2.26 Audio compoenent descriptor\r
+typedef struct _AudioComponentDescriptor\r
+{\r
+    uint8_t         _descriptor_tag;                        //  8\r
+    uint8_t         _descriptor_length;                     //  8\r
+    uint8_t         _reserved_future_use;                   //  4\r
+    uint8_t         _stream_content;                        //  4\r
+    uint8_t         _component_type;                        //  8\r
+    uint8_t         _component_tag;                         //  8\r
+    uint8_t         _stream_type;                           //  8\r
+    uint8_t         _simulcast_group_tag;                   //  8\r
+    uint8_t         _ES_multi_lingual_flag;                 //  1\r
+    uint8_t         _main_component_flag;                   //  1\r
+    uint8_t         _quality_indicator;                     //  2\r
+    uint8_t         _sampling_rate;                         //  3\r
+    uint8_t         _reserved_future_use_2;                 //  1\r
+    uint8_t         _ISO_639_language_code[3];              // 24\r
+    uint8_t         _ISO_639_language_code_2[3];            // 24 if (ES_multi_lingual_flag == 1)\r
+    uint8_t         _text_char[MAX_DESC_LEN];               //  8 x N\r
+} AudioComponentDescriptor;\r
+\r
 // 6.2.33 Series descriptor\r
 typedef struct _SeriesDescriptor\r
 {\r
-    uint8_t         descriptor_tag;                         //  8\r
-    uint8_t         descriptor_length;                      //  8\r
-    uint16_t        series_id;                              // 16\r
-    uint8_t         repeat_label;                           //  4\r
-    uint8_t         program_pattern;                        //  3\r
-    uint8_t         expire_date_valid_flag;                 //  1\r
-    uint16_t        expire_date;                            // 16\r
-    uint16_t        episode_number;                         // 12\r
-    uint16_t        last_episode_number;                    // 12\r
-    uint8_t         series_name[MAX_DESC_LEN];              //  8 x N\r
+    uint8_t         _descriptor_tag;                        //  8\r
+    uint8_t         _descriptor_length;                     //  8\r
+    uint16_t        _series_id;                             // 16\r
+    uint8_t         _repeat_label;                          //  4\r
+    uint8_t         _program_pattern;                       //  3\r
+    uint8_t         _expire_date_valid_flag;                //  1\r
+    uint16_t        _expire_date;                           // 16\r
+    uint16_t        _episode_number;                        // 12\r
+    uint16_t        _last_episode_number;                   // 12\r
+    uint8_t         _series_name[MAX_DESC_LEN];             //  8 x N\r
 } SeriesDescriptor;\r
 \r
 \r
 typedef struct _OtherDescriptor\r
 {\r
-    uint8_t         descriptor_tag;                         //  8\r
-    uint8_t         descriptor_length;                      //  8\r
-    uint8_t         descriptor[MAX_DESC_LEN];               //  8 x N\r
+    uint8_t         _descriptor_tag;                        //  8\r
+    uint8_t         _descriptor_length;                     //  8\r
+    uint8_t         _descriptor[MAX_DESC_LEN];              //  8 x N\r
 } OtherDescriptor;\r
 \r
 typedef union _Descriptor\r
 {\r
-    uint8_t                     descriptor_tag;\r
-    BouquetNameDescriptor       bouquet_name;\r
-    ServiceDescriptor           service;\r
-    ShortEventDescriptor        short_event;\r
-    ExtendedEventDescriptor     extended_event;\r
-    ContentDescriptor           content;\r
-    SeriesDescriptor            series;\r
-    OtherDescriptor             other;\r
+    uint8_t                         _descriptor_tag;\r
+    BouquetNameDescriptor           _bouquet_name;\r
+    ComponentDescriptor             _component;\r
+    ContentDescriptor               _content;\r
+    ExtendedEventDescriptor         _extended_event;\r
+    ServiceDescriptor               _service;\r
+    ShortEventDescriptor            _short_event;\r
+    DigitalCopyControlDescriptor    _digital_copy_control;\r
+    AudioComponentDescriptor        _audio_component;\r
+    SeriesDescriptor                _series;\r
+    OtherDescriptor                 _other;\r
 } Descriptor;\r
 \r
-\r
-\r
 class Table\r
 {\r
 protected:\r
@@ -150,12 +194,11 @@ protected:
     uint16_t    _length;\r
     uint8_t     _section[MAX_SECT_LEN];\r
 \r
-    virtual bool decode_section();\r
+    virtual bool decode_section() = 0;\r
 \r
 public:\r
     Table();\r
     virtual ~Table();\r
-//    bool decode(uint8_t *packet);\r
     bool decode(Header *header, uint8_t *packet);\r
     void reset();\r
 \r
index 2310be9..9d4c59b 100644 (file)
@@ -5,6 +5,9 @@
 \r
 #include <time.h>\r
 \r
+#define DBG_LEVEL 0\r
+#include "Raym/Log.h"\r
+\r
 #include "Raym/Raym.h"\r
 #include "b25/aribstr.h"\r
 #include "ry0/iPTd/Analyzer.h"\r
@@ -94,309 +97,305 @@ Dictionary *Analyzer::stationInfo()
     return result;\r
 }\r
 \r
-static Array *eit2epgs(MPEG2::TS::EIT *eit)\r
+Array *Analyzer::collectEPGs(time_t limit)\r
 {\r
-    Array *result = Array::arrayWithCapacity(0);\r
+    _demux.setFlag(MPEG2::TS::Demultiplexer::FLG_EIT, true);\r
 \r
-printf("    | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");\r
-printf("----+------------------------------------------------\n");\r
-for (int ii = 0; ii < eit->_section_length - 0x0e; ++ii)\r
-{\r
-    if (ii % 16 == 0)\r
-    {\r
-        printf("%04x: ", ii);\r
-    }\r
-    printf("%02x ", eit->_event_data[ii]);\r
-    if (ii % 16 == 15)\r
-    {\r
-        printf("\n");\r
-    }\r
-}\r
-printf("\n");\r
+    std::vector<MPEG2::TS::EIT *> eits;\r
+\r
+    RaymLock(this);\r
+\r
+    time_t start = time(NULL);\r
     while (true)\r
     {\r
-        MPEG2::TS::EIT::Event *event = eit->nextEvent();\r
-        if (event == NULL)\r
+        while ((_eit == NULL) && (time(NULL) < start + limit))\r
         {\r
-        DebugLog0("event is null\n");\r
-            break;\r
+            RaymCondTimedWait(this, 1000);\r
         }\r
 \r
-        DebugLog0("eit -> epg: start\n");\r
-\r
-        Dictionary *epg = Dictionary::dictionaryWithCapacity(0);\r
-\r
-        char tmp[32];\r
-#ifdef _WIN32\r
-        sprintf_s(tmp, "%d", eit->_service_id);\r
-#else\r
-        sprintf(tmp, "%d", eit->_service_id);\r
-#endif\r
-        epg->setString(tmp, KEY_EPG_SERVICE_ID);\r
-\r
-#ifdef _WIN32\r
-        sprintf_s(tmp, "%d", event->_event_id);\r
-#else\r
-        sprintf(tmp, "%d", event->_event_id);\r
-#endif\r
-        epg->setString(tmp, KEY_EPG_EVENT_ID);\r
-\r
-        char date[16];\r
-#ifdef _WIN32\r
-        sprintf_s(date, sizeof(date), "%02d/%02d/%02d", event->_st_year, event->_st_month, event->_st_day);\r
-#else\r
-        sprintf(date, "%02d/%02d/%02d", event->_st_year, event->_st_month, event->_st_day);\r
-#endif\r
-        epg->setString(date, KEY_EPG_DATE);\r
-\r
-        char start[16];\r
-#ifdef _WIN32\r
-        sprintf_s(start, sizeof(start), "%02d:%02d:%02d", event->_st_hour, event->_st_min, event->_st_sec);\r
-#else\r
-        sprintf(start, "%02d:%02d:%02d", event->_st_hour, event->_st_min, event->_st_sec);\r
-#endif\r
-        epg->setString(start, KEY_EPG_START);\r
-\r
-        int hour = event->_st_hour + event->_dur_hour;\r
-        int min = event->_st_min + event->_dur_min;\r
-        int sec = event->_st_sec + event->_dur_sec;\r
-        if (sec >= 60)\r
+        if (_eit != NULL)\r
         {\r
-            min += 1;\r
-            sec -= 60;\r
+            eits.push_back(_eit);\r
+            _eit = NULL;\r
         }\r
-        if (min >= 60)\r
+        else\r
         {\r
-            hour += 1;\r
-            min -= 60;\r
+            break;\r
         }\r
-        char end[16];\r
-#ifdef _WIN32\r
-        sprintf_s(end, sizeof(end), "%02d:%02d:%02d", hour, min, sec);\r
-#else\r
-        sprintf(end, "%02d:%02d:%02d", hour, min, sec);\r
-#endif\r
-        epg->setString(end, KEY_EPG_END);\r
-\r
-        Data *data = Data::dataWithCapacity(0);\r
-\r
-        DebugLog0("eit -> epg: check 000\n");\r
-        while (true)\r
+    }\r
+\r
+    RaymUnlock(this);\r
+\r
+    _demux.setFlag(MPEG2::TS::Demultiplexer::FLG_EIT, false);\r
+\r
+    Array *result = Array::arrayWithCapacity(0);\r
+\r
+    std::vector<MPEG2::TS::EIT *>::iterator it;\r
+    for (it = eits.begin(); it != eits.end(); ++it)\r
+    {\r
+        MPEG2::TS::EIT *eit = (*it);\r
+        if ((eit->_table_id == MPEG2::TS::EIT::TABLE_ID_SELF) ||\r
+            ((MPEG2::TS::EIT::TABLE_ID_SELF_SCHEDULE_BEGIN <= eit->_table_id) && (eit->_table_id <= MPEG2::TS::EIT::TABLE_ID_SELF_SCHEDULE_END)))\r
         {\r
-            MPEG2::TS::Descriptor *desc = event->nextDescriptor();\r
-            if (desc == NULL)\r
+            MPEG2::TS::EIT::Event *event;\r
+            while ((event = eit->nextEvent()) != NULL)\r
             {\r
-        DebugLog0("eit -> epg: check 001\n");\r
-                break;\r
-            }\r
-        DebugLog0("eit -> epg: check 002\n");\r
+                char service_id[32];\r
+                sprintf_s(service_id, "%d", eit->_service_id);\r
 \r
-            switch (desc->descriptor_tag)\r
-            {\r
-            case MPEG2::TS::TAG_BOUQUET_NAME_DESCRIPTOR:\r
-                DebugLog0("TAG_BOUQUET_NAME_DESCRIPTOR\n");\r
-                break;\r
+                char event_id[32];\r
+                sprintf_s(event_id, "%d", event->_event_id);\r
 \r
-            case MPEG2::TS::TAG_SERVICE_DESCRIPTOR:\r
-                DebugLog0("TAG_SERVICE_DESCRIPTOR\n");\r
-                break;\r
+                Dictionary *epg = NULL;\r
 \r
-            case MPEG2::TS::TAG_SHORT_EVENT_DESCRIPTOR:\r
-                DebugLog0("TAG_SHORT_EVENT_DESCRIPTOR\n");\r
-                if (desc->short_event.event_name_length > 0)\r
+                for (uint32_t i = 0; i < result->count(); ++i)\r
                 {\r
-DebugLog0("event_name_length: %d\n", desc->short_event.event_name_length);\r
-                    char *tmp = (char *)malloc(desc->short_event.event_name_length * 2 + 1);\r
-                    if (tmp)\r
+                    epg = (Dictionary *)result->objectAtIndex(i);\r
+                    if (epg->stringForKey(KEY_EPG_SERVICE_ID)->isEqualToString(service_id) &&\r
+                        epg->stringForKey(KEY_EPG_EVENT_ID)->isEqualToString(event_id))\r
                     {\r
-                        AribToString(tmp, (const char *)desc->short_event.event_name, desc->short_event.event_name_length);\r
-DebugLog0("event_name: %s\n", tmp);\r
-                        String *event_name = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
-                        if (event_name)\r
-                        {\r
-DebugLog0("event_name: %s\n", event_name->cString());\r
-                            epg->setString(event_name, KEY_EPG_TITLE);\r
-                        }\r
-                        else\r
-                        {\r
-                            printf("stringWithCString() NG.\n");\r
-                        }\r
-\r
-                        free(tmp);\r
-                    }\r
-                    else\r
-                    {\r
-                        printf("malloc NG.\n");\r
+                        break;\r
                     }\r
+                    epg = NULL;\r
                 }\r
-                else\r
-                {\r
-DebugLog0("event_name_length ng: %d\n", desc->short_event.event_name_length);\r
-                }\r
-                if (desc->short_event.text_length > 0)\r
+\r
+                if (epg == NULL)\r
                 {\r
-DebugLog0("text_length: %d\n", desc->short_event.text_length);\r
-                    char *tmp = (char *)malloc(desc->short_event.text_length * 2 + 1);\r
-                    if (tmp)\r
+                    epg = Dictionary::dictionaryWithCapacity(0);\r
+                    epg->setString(service_id, KEY_EPG_SERVICE_ID);\r
+                    epg->setString(event_id, KEY_EPG_EVENT_ID);\r
+\r
+                    char date[16];\r
+                    sprintf_s(date, sizeof(date), "%02d/%02d/%02d", event->_st_year, event->_st_month, event->_st_day);\r
+                    epg->setString(date, KEY_EPG_DATE);\r
+\r
+                    char start[16];\r
+                    sprintf_s(start, sizeof(start), "%02d:%02d:%02d", event->_st_hour, event->_st_min, event->_st_sec);\r
+                    epg->setString(start, KEY_EPG_START);\r
+\r
+                    int hour = event->_st_hour + event->_dur_hour;\r
+                    int min = event->_st_min + event->_dur_min;\r
+                    int sec = event->_st_sec + event->_dur_sec;\r
+                    if (sec >= 60)\r
                     {\r
-                        AribToString(tmp, (const char *)desc->short_event.text, desc->short_event.text_length);\r
-                        String *text = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
-                        if (text)\r
-                        {\r
-                            epg->setString(text, KEY_EPG_DESCRIPTION);\r
-                        }\r
-                        else\r
-                        {\r
-                            printf("stringWithCString() NG.\n");\r
-                        }\r
-                        free(tmp);\r
+                        min += 1;\r
+                        sec -= 60;\r
                     }\r
-                    else\r
+                    if (min >= 60)\r
                     {\r
-                        printf("mallco NG.\n");\r
+                        hour += 1;\r
+                        min -= 60;\r
                     }\r
+                    char end[16];\r
+                    sprintf_s(end, sizeof(end), "%02d:%02d:%02d", hour, min, sec);\r
+                    epg->setString(end, KEY_EPG_END);\r
+\r
+                    char duration[8];\r
+                    sprintf_s(duration, sizeof(duration), "%d", event->_dur_hour * 3600 + event->_dur_min * 60 + event->_dur_sec);\r
+                    epg->setString(duration, KEY_EPG_DURATION);\r
+\r
+                    result->addObject(epg);\r
                 }\r
-                else\r
-                {\r
-DebugLog0("text_length ng: %d\n", desc->short_event.text_length);\r
-                }\r
-                break;\r
 \r
-            case MPEG2::TS::TAG_EXTENDED_EVENT_DESCRIPTOR:\r
-                printf("TAG_EXTENDED_EVENT_DESCRIPTOR\n");\r
-                for (int i = 0; i < desc->extended_event.item_count; ++i)\r
+                Array *ext_items = NULL;\r
+                String *ext_item_desc = NULL;\r
+                Data *ext_item = NULL;\r
+                Data *ext_text = NULL;\r
+\r
+                MPEG2::TS::Descriptor *desc;\r
+                while ((desc = event->nextDescriptor()) != NULL)\r
                 {\r
+                    switch (desc->_descriptor_tag)\r
+                    {\r
+                    case MPEG2::TS::TAG_BOUQUET_NAME_DESCRIPTOR:\r
+                        DebugLog3("TAG_BOUQUET_NAME_DESCRIPTOR\n");\r
+                        break;\r
 \r
-                    // item_description と item を繋げてしまうと正しく読めない場合がある\r
-                    // 現状は item_description は捨てる\r
-                    // どうやって扱うか、今後の課題\r
+                    case MPEG2::TS::TAG_SERVICE_DESCRIPTOR:\r
+                        DebugLog3("TAG_SERVICE_DESCRIPTOR\n");\r
+                        break;\r
 \r
-                    if (desc->extended_event.items[i].item_description_length > 0)\r
-                    {\r
-                        char *tmp = (char *)malloc(desc->extended_event.items[i].item_description_length * 2 + 1);\r
-                        if (tmp)\r
+                    case MPEG2::TS::TAG_SHORT_EVENT_DESCRIPTOR:\r
+                        DebugLog3("TAG_SHORT_EVENT_DESCRIPTOR\n");\r
+                        if (desc->_short_event._event_name_length > 0)\r
                         {\r
-                            AribToString(tmp, (const char *)desc->extended_event.items[i].item_description, desc->extended_event.items[i].item_description_length);\r
-                            String *item_description = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
-                            if (item_description)\r
+                            char *tmp = (char *)malloc(desc->_short_event._event_name_length * 3);\r
+                            if (tmp != NULL)\r
                             {\r
-                                DebugLog0("item_description: %s\n", item_description->cString());\r
+                                AribToString(tmp, (const char *)desc->_short_event._event_name, desc->_short_event._event_name_length);\r
+                                String *event_name = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
+                                if (event_name != NULL)\r
+                                {\r
+                                    epg->setString(event_name, KEY_EPG_TITLE);\r
+                                }\r
+                                free(tmp);\r
                             }\r
-                            free(tmp);\r
                         }\r
-//                            data->appendBytes(desc->extended_event.items[i].item_description, \r
-//                                            desc->extended_event.items[i].item_description_length);\r
-                    }\r
+                        if (desc->_short_event._text_length > 0)\r
+                        {\r
+                            char *tmp = (char *)malloc(desc->_short_event._text_length * 3);\r
+                            if (tmp != NULL)\r
+                            {\r
+                                AribToString(tmp, (const char *)desc->_short_event._text, desc->_short_event._text_length);\r
+                                String *text = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
+                                if (text != NULL)\r
+                                {\r
+                                    epg->setString(text, KEY_EPG_DESCRIPTION);\r
+                                }\r
+                                free(tmp);\r
+                            }\r
+                        }\r
+                        break;\r
 \r
+                    case MPEG2::TS::TAG_EXTENDED_EVENT_DESCRIPTOR:\r
+                        DebugLog3("TAG_EXTENDED_EVENT_DESCRIPTOR\n");\r
+                        {\r
+                            for (int i = 0; i < desc->_extended_event._item_count; ++i)\r
+                            {\r
+                                if (ext_items == NULL)\r
+                                {\r
+                                    ext_items = Array::arrayWithCapacity(0);\r
+                                    epg->setObject(ext_items, KEY_EPG_EXT_ITEMS);\r
+                                }\r
+\r
+                                if (desc->_extended_event._items[i]._item_description_length > 0)\r
+                                {\r
+                                    if (ext_item != NULL)\r
+                                    {\r
+                                        char *tmp = (char *)malloc(ext_item->length() * 3);\r
+                                        if (tmp != NULL)\r
+                                        {\r
+                                            AribToString(tmp, (const char *)ext_item->bytes(), ext_item->length());\r
+                                            String *desc = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
+                                            if (desc != NULL)\r
+                                            {\r
+                                                Dictionary *dict = Dictionary::dictionaryWithCapacity(0);\r
+                                                if (ext_item_desc != NULL)\r
+                                                {\r
+                                                    dict->setString(ext_item_desc, KEY_EPG_EXT_ITEM_DESCRIPTION);\r
+                                                    ext_item_desc = NULL;\r
+                                                }\r
+                                                dict->setString(desc, KEY_EPG_EXT_ITEM);\r
+                                                ext_items->addObject(dict);\r
+                                            }\r
+                                            free(tmp);\r
+                                        }\r
+                                        ext_item = NULL;\r
+                                    }\r
+\r
+                                    char *tmp = (char *)malloc(desc->_extended_event._items[i]._item_description_length * 3);\r
+                                    if (tmp != NULL)\r
+                                    {\r
+                                        AribToString(tmp, (const char *)desc->_extended_event._items[i]._item_description,\r
+                                                    desc->_extended_event._items[i]._item_description_length);\r
+                                        ext_item_desc = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
+                                        free(tmp);\r
+                                    }\r
+                                    else\r
+                                    {\r
+                                        ext_item_desc = NULL;\r
+                                    }\r
+                                }\r
+\r
+                                if (desc->_extended_event._items[i]._item_length > 0)\r
+                                {\r
+                                    if (ext_item == NULL)\r
+                                    {\r
+                                        ext_item = Data::dataWithCapacity(0);\r
+                                    }\r
+                                    ext_item->appendBytes(desc->_extended_event._items[i]._item,\r
+                                                          desc->_extended_event._items[i]._item_length);\r
+                                }\r
+                            }\r
+                            if (desc->_extended_event._text_length > 0)\r
+                            {\r
+                                if (ext_text == NULL)\r
+                                {\r
+                                    ext_text = Data::dataWithCapacity(0);\r
+                                }\r
+                                ext_text->appendBytes(desc->_extended_event._text, desc->_extended_event._text_length);\r
+                            }\r
+                        }\r
+                        break;\r
 \r
-                    if (desc->extended_event.items[i].item_length > 0)\r
-                    {\r
-                        data->appendBytes(desc->extended_event.items[i].item,\r
-                                          desc->extended_event.items[i].item_length);\r
-                    }\r
-                }\r
-                if (desc->extended_event.text_length > 0)\r
-                {\r
-                    DebugLog0("TAG_EXTENDED_EVENT_DESCRIPTOR\n");\r
-                    DebugLog0("  text: %s\n", desc->extended_event.text);\r
-                    data->appendBytes(desc->extended_event.text, desc->extended_event.text_length);\r
-                }\r
-                break;\r
+                    case MPEG2::TS::TAG_CONTENT_DESCRIPTOR:\r
+                        DebugLog3("TAG_CONTENT_DESCRIPTOR\n");\r
+                        break;\r
 \r
-            case MPEG2::TS::TAG_CONTENT_DESCRIPTOR:\r
-                DebugLog0("TAG_CONTENT_DESCRIPTOR\n");\r
-                break;\r
+                    case MPEG2::TS::TAG_SERIES_DESCRIPTOR:\r
+                        DebugLog3("TAG_SERIES_DESCRIPTOR\n");\r
+                        break;\r
 \r
-            case MPEG2::TS::TAG_SERIES_DESCRIPTOR:\r
-                DebugLog0("TAG_SERIES_DESCRIPTOR\n");\r
-                break;\r
+                    case MPEG2::TS::TAG_EVENT_GROUP_DESCRIPTOR:\r
+                        DebugLog3("TAG_EVENT_GROUP_DESCRIPTOR\n");\r
+                        break;\r
 \r
-            case MPEG2::TS::TAG_EVENT_GROUP_DESCRIPTOR:\r
-                DebugLog0("TAG_EVENT_GROUP_DESCRIPTOR\n");\r
-                break;\r
+                    case MPEG2::TS::TAG_COMPONENT_DESCRIPTOR:\r
+                        DebugLog3("TAG_COMPONENT_DESCRIPTOR\n");\r
+                        break;\r
 \r
-            case MPEG2::TS::TAG_COMPONENT_DESCRIPTOR:\r
-                DebugLog0("TAG_COMPONENT_DESCRIPTOR\n");\r
-                break;\r
+                    case MPEG2::TS::TAG_DIGITAL_COPY_CONTROL_DESCRIPTOR:\r
+                        DebugLog3("TAG_DIGITAL_COPY_CONTROL_DESCRIPTOR\n");\r
+                        break;\r
 \r
-            case MPEG2::TS::TAG_DIGITAL_COPY_CONTROL_DESCRIPTOR:\r
-                DebugLog0("TAG_DIGITAL_COPY_CONTROL_DESCRIPTOR\n");\r
-                break;\r
+                    case MPEG2::TS::TAG_AUDIO_COMPONENT_DESCRIPTOR:\r
+                        DebugLog3("TAG_AUDIO_COMPONENT_DESCRIPTOR\n");\r
+                        break;\r
 \r
-            case MPEG2::TS::TAG_AUDIO_COMPONENT_DESCRIPTOR:\r
-                DebugLog0("TAG_AUDIO_COMPONENT_DESCRIPTOR\n");\r
-                break;\r
+                    case MPEG2::TS::TAG_DATA_CONTENT_DESCRIPTOR:\r
+                        DebugLog3("TAG_AUDIO_COMPONENT_DESCRIPTOR\n");\r
+                        break;\r
 \r
-//                case MPEG2::TS::TAG_17: // 不明\r
+                    default:\r
+                        DebugLog3("Unknown descriptor: 0x%02X\n", desc->_descriptor_tag);\r
+                        break;\r
+                    }\r
+                }\r
 \r
-            default:\r
-                DebugLog0("Unknown descriptor: 0x%02X\n", desc->descriptor_tag);\r
-                break;\r
-            }\r
-        }\r
+                if (ext_item != NULL)\r
+                {\r
+                    char *tmp = (char *)malloc(ext_item->length() * 3);\r
+                    if (tmp != NULL)\r
+                    {\r
+                        AribToString(tmp, (const char *)ext_item->bytes(), ext_item->length());\r
+                        String *desc = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
+                        if (desc != NULL)\r
+                        {\r
+                            Dictionary *dict = Dictionary::dictionaryWithCapacity(0);\r
+                            if (ext_item_desc != NULL)\r
+                            {\r
+                                dict->setString(ext_item_desc, KEY_EPG_EXT_ITEM_DESCRIPTION);\r
+                                ext_item_desc = NULL;\r
+                            }\r
+                            dict->setString(desc, KEY_EPG_EXT_ITEM);\r
+                            ext_items->addObject(dict);\r
+                        }\r
+                        free(tmp);\r
+                    }\r
+                    ext_item = NULL;\r
+                }\r
 \r
-        if (data->length())\r
-        {\r
-            char *tmp = (char *)malloc(data->length() * 2);\r
-            if (tmp)\r
-            {\r
-                AribToString(tmp, (const char *)data->bytes(), data->length());\r
-                String *desc = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
-                if (desc)\r
+                if (ext_text != NULL)\r
                 {\r
-                    epg->setString(desc, KEY_EPG_DESCRIPTION);\r
+                    char *tmp = (char *)malloc(ext_text->length() * 3);\r
+                    if (tmp != NULL)\r
+                    {\r
+                        AribToString(tmp, (const char *)ext_text->bytes(), ext_text->length());\r
+                        String *desc = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
+                        if (desc != NULL)\r
+                        {\r
+                            Dictionary *dict = Dictionary::dictionaryWithCapacity(0);\r
+                            dict->setString("no desc", KEY_EPG_EXT_ITEM_DESCRIPTION);\r
+                            dict->setString(desc, KEY_EPG_EXT_ITEM);\r
+                            ext_items->addObject(dict);\r
+                        }\r
+                        free(tmp);\r
+                    }\r
+                    ext_text = NULL;\r
                 }\r
-                free(tmp);\r
             }\r
         }\r
 \r
-        result->addObject(epg);\r
-\r
-        DebugLog0("eit -> epg: done\n");\r
-        DebugLog0("%s\n", epg->toString().c_str());\r
-    }\r
-\r
-\r
-    DebugLog0("eit2epg done.\n");\r
-    return result;\r
-}\r
-\r
-Array *Analyzer::collectEPGs(time_t limit)\r
-{\r
-    _demux.setFlag(MPEG2::TS::Demultiplexer::FLG_EIT, true);\r
-\r
-    std::vector<MPEG2::TS::EIT *> eits;\r
-\r
-    DebugLog0("b lock\n");\r
-    RaymLock(this);\r
-    DebugLog0("a lock\n");\r
-\r
-    time_t start = time(NULL);\r
-    while (time(NULL) < start + limit)\r
-    {\r
-        while (_eit == NULL)\r
-        {\r
-            DebugLog0("b wait\n");\r
-            RaymCondWait(this);\r
-            DebugLog0("a wait\n");\r
-        }\r
-\r
-        eits.push_back(_eit);\r
-        _eit = NULL;\r
-    }\r
-\r
-    DebugLog0("b unlock\n");\r
-    RaymUnlock(this);\r
-    DebugLog0("a unlock\n");\r
-\r
-    _demux.setFlag(MPEG2::TS::Demultiplexer::FLG_EIT, false);\r
-\r
-    Array *result = Array::arrayWithCapacity(0);\r
-\r
-    std::vector<MPEG2::TS::EIT *>::iterator it;\r
-    for (it = eits.begin(); it != eits.end(); ++it)\r
-    {\r
-        result->addObjectsFromArray(eit2epgs(*it));\r
         delete *it;\r
     }\r
 \r
@@ -423,9 +422,7 @@ void Analyzer::detect(MPEG2::TS::SDT *sdt)
 \r
 void Analyzer::detect(MPEG2::TS::EIT *eit)\r
 {\r
-    DebugLog0("b lock: detect\n");\r
     RaymLock(this);\r
-    DebugLog0("a lock: detect\n");\r
     if (_eit != NULL)\r
     {\r
         delete _eit;\r
@@ -433,9 +430,7 @@ void Analyzer::detect(MPEG2::TS::EIT *eit)
     }\r
     _eit = new MPEG2::TS::EIT(*eit);\r
     RaymCondSignal(this);\r
-    DebugLog0("b unlock: detect\n");\r
     RaymUnlock(this);\r
-    DebugLog0("a unlock: detect\n");\r
 }\r
 \r
 } // iPTd\r
index b7cde41..79356c9 100644 (file)
@@ -59,8 +59,8 @@ static const long long CMD_COLLECT_EPG_ISDB_T   = 0x0006;  // 番組情報取得
 static const TimeInterval DEF_COLLECT_EPG_DELAY    = 1.0;\r
 static const TimeInterval DEF_COLLECT_EPG_RETRY    = 60.0;\r
 \r
-static const time_t DEF_COLLECT_EPG_LIMIT_S  = 20;\r
-static const time_t DEF_COLLECT_EPG_LIMIT_T  = 30;\r
+static const time_t DEF_COLLECT_EPG_LIMIT_S  = 30;\r
+static const time_t DEF_COLLECT_EPG_LIMIT_T  = 75;\r
 \r
 static const time_t OFFSET_OF_START_TIME        = -2;       // 録画開始時刻の補正(秒単位)\r
 static const time_t OFFSET_OF_END_TIME          = -3;       // 録画停止時刻の補正(秒単位)\r
@@ -172,6 +172,42 @@ std::string Controller::createVideoPath(int tuner)
     return result;\r
 }\r
 \r
+// epgの開始時刻でソートする為の比較関数\r
+Integer compareFunction(Object *obj1, Object *obj2, void *context)\r
+{\r
+    if (isKindOfClass(Dictionary, obj1) && isKindOfClass(Dictionary, obj2))\r
+    {\r
+        time_t st1;\r
+        time_t ed1;\r
+        Controller::getTimeWithEPG((Dictionary *)obj1, &st1, &ed1);\r
+\r
+        time_t st2;\r
+        time_t ed2;\r
+        Controller::getTimeWithEPG((Dictionary *)obj2, &st2, &ed2);\r
+\r
+        if (st1 < st2)\r
+        {\r
+            return OrderedAscending;\r
+        }\r
+        else if (st1 > st2)\r
+        {\r
+            return OrderedDescending;\r
+        }\r
+        else\r
+        {\r
+            if (ed1 < ed2)\r
+            {\r
+                return OrderedAscending;\r
+            }\r
+            else if (ed1 > ed2)\r
+            {\r
+                return OrderedDescending;\r
+            }\r
+        }\r
+    }\r
+    return OrderedSame;\r
+}\r
+\r
 #ifndef _WIN32\r
 #pragma mark '\r
 #pragma mark ------- EPG関連 -------\r
@@ -185,7 +221,9 @@ void Controller::removePastEPGs()
     time_t now = time(NULL);\r
 \r
     // lock\r
-    RaymLock(this);\r
+    RaymLock(_epgs);\r
+\r
+    Array *epg_list = Array::arrayWithCapacity(0);\r
 \r
     // サービスIDでループ\r
     Array *keys1 = _epgs->allKeys();\r
@@ -215,12 +253,56 @@ void Controller::removePastEPGs()
                         // 削除する\r
                         events->removeObjectForKey(key);\r
                     }\r
+                    else\r
+                    {\r
+                        epg_list->addObject(epg);\r
+                    }\r
                 }\r
             }\r
         }\r
     }\r
 \r
+    epg_list = epg_list->sortedArrayUsingFunction(compareFunction, this);\r
+    std::string xmltv_programs;\r
+    for (uint i = 0; i < epg_list->count(); ++i)\r
+    {\r
+        Dictionary *epg = (Dictionary *)epg_list->objectAtIndex(i);\r
+\r
+        std::string epg_date     = epg->stringForKey(KEY_EPG_DATE)->stringByReplacingOccurrencesOfString("/", "")->cString();\r
+        std::string epg_start    = epg->stringForKey(KEY_EPG_START)->stringByReplacingOccurrencesOfString(":", "")->cString();\r
+        std::string epg_end      = epg->stringForKey(KEY_EPG_END)->stringByReplacingOccurrencesOfString(":", "")->cString();\r
+        std::string epg_event_id = epg->stringForKey(KEY_EPG_EVENT_ID)->cString();\r
+        std::string epg_duration = epg->stringForKey(KEY_EPG_DURATION)->cString();\r
+        std::string epg_title    = epg->stringForKey(KEY_EPG_TITLE)->cString();\r
+\r
+        Array *ch_list = _service_to_channels->arrayForKey(epg->stringForKey(KEY_EPG_SERVICE_ID));\r
+        for (uint ch_idx = 0; (ch_list != NULL) && (ch_idx < ch_list->count()); ++ch_idx)\r
+        {\r
+            xmltv_programs += "  <programme start=\"" + epg_date + epg_start + " +0900\" stop=\"";\r
+            xmltv_programs += epg_date + epg_end + " +0900\" channel=\"";\r
+            xmltv_programs += ((String *)ch_list->objectAtIndex(ch_idx))->cString();\r
+            xmltv_programs += "\" event_id=\"" + epg_event_id + "\" duration=\"" + epg_duration + "\">\r\n";\r
+\r
+            xmltv_programs += "    <title lang=\"ja_JP\">" + epg_title + "</title>\r\n";\r
+\r
+            xmltv_programs += "  </programme>\r\n";\r
+        }\r
+    }\r
+\r
     // unlock\r
+    RaymUnlock(_epgs);\r
+\r
+    std::string str_xmltv_xml;\r
+    str_xmltv_xml =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";\r
+    str_xmltv_xml += "<!DOCTYPE tv SYSTEM \"xmltv.dtd\">\r\n";\r
+    str_xmltv_xml += "<tv generator-info-name=\"iPTd_R2\" generator-info-url=\"http://localhost/\">\r\n";\r
+    str_xmltv_xml += _xmltv_channels;\r
+    str_xmltv_xml += xmltv_programs;\r
+    str_xmltv_xml += "</tv>\r\n";\r
+\r
+    RaymLock(this);\r
+    RELEASE(_xmltv_xml);\r
+    _xmltv_xml = String::alloc()->initWithUTF8String(str_xmltv_xml.c_str());\r
     RaymUnlock(this);\r
 }\r
 \r
@@ -252,10 +334,7 @@ void Controller::collectEPGsForTuner(int tuner, time_t limit)
     an->release();\r
 \r
     // lock\r
-    RaymLock(this);\r
-\r
-    long add_cnt = 0;\r
-    long discard = 0;\r
+    RaymLock(_epgs);\r
 \r
     for (uint j = 0; j < collected->count(); ++j)\r
     {\r
@@ -264,8 +343,6 @@ void Controller::collectEPGsForTuner(int tuner, time_t limit)
         if (epg1->stringForKey(KEY_EPG_TITLE) == NULL)\r
         {\r
             // タイトルが無い場合は不要\r
-            ++discard;\r
-//            DebugLog0("discard: %s", epg1->toString().c_str());\r
             continue;\r
         }\r
 \r
@@ -284,18 +361,16 @@ void Controller::collectEPGsForTuner(int tuner, time_t limit)
             key = epg1->stringForKey(KEY_EPG_EVENT_ID);\r
             if (key != NULL)\r
             {\r
-                ++add_cnt;\r
                 epgs_of_service->setObject(epg1, key);\r
             }\r
         }\r
     }\r
-    DebugLog0("add: %d, discard: %d", add_cnt, discard);\r
 \r
     // ファイルへ書き出し\r
     _epgs->writeToFile(_epgs_path, true);\r
 \r
     // unlock\r
-    RaymUnlock(this);\r
+    RaymUnlock(_epgs);\r
 \r
     DebugLog2("Controller::collectEPGsForTuner(%d) end.", tuner);\r
 }\r
@@ -394,10 +469,11 @@ bool Controller::collectEPGs(Tuner::Type type)
     {\r
         DebugLog0("collect EPG of \"%s\" was finished.", _tuners[tuner]->name());\r
 \r
-        // 過去のEPGを削除\r
-        removePastEPGs();\r
     }\r
 \r
+    // 過去のEPGを削除\r
+    removePastEPGs();\r
+\r
     DebugLog2("Controller::collectEPGs(%s) end.", type == Tuner::ISDB_S ? "ISDB-S" : "ISDB-T");\r
 \r
     return true;\r
@@ -3675,102 +3751,22 @@ HTTPResponse *Controller::responseForReloadURI(NET::HTTPRequest *request, SOCKAD
 HTTPResponse *Controller::responseForPlaylist(HTTPRequest *request, SOCKADDR_IN *client)\r
 {\r
     HTTPResponse *result = NULL;\r
-    // http://bit.ly/iptv_feb2015\r
-\r
-#if 0\r
-\r
-#EXTM3U\r
-\r
-#EXTINF:-1, [COLOR yellow]Updated 15/04/2015 @ 03:45 [/COLOR]  \r
-plugin://plugin.video.youtube/?action=play_video&videoid=eMduu81gNgM\r
-#EXTINF:-1, [COLOR green] --Uk Live Tv--[/COLOR]  \r
-plugin://plugin.video.youtube/?action=play_video&videoid=eMduu81gNgM\r
-#EXTINF:-1, [COLOR green] --Free Collection of IPTV sports links--[/COLOR]  \r
-plugin://plugin.video.youtube/?action=play_video&videoid=eMduu81gNgM\r
-#EXTINF:-1, [COLOR red] --Links will go down. Please note that it will take time to update--[/COLOR]\r
-plugin://plugin.video.youtube/?action=play_video&videoid=eMduu81gNgM\r
-#EXTINF:-1, [COLOR red] --Please contact me at the husham.com website--[/COLOR]\r
-plugin://plugin.video.youtube/?action=play_video&videoid=eMduu81gNgM\r
-\r
-#EXTINF:-1, Sky sports news\r
-rtmp://89.248.172.159:443/liverepeater playpath=35 swfUrl=http://popeoftheplayers.eu/atdedead.swf pageUrl=http://popeoftheplayers.eu/crichd.php?id=35&width=600&height=450 token=#atd%#$ZH\r
-#EXTINF:-1,Bt sports 1\r
-rtmp://80.82.78.87:443/liverepeater/starsp pageUrl=http://xxxxxxxxxxxxxxxx.xx/rtmpe://strm.dcast.tv:1935/live/asdfadfaa/pageUrl=http://xxxxx.xx/rtmp://80.82.64.90:443/liverepeater/79/pageUrl=http://filotv.pw/rtmpe://strm.ukcast.tv:1935/redirect/FUNKTSN/pageUrl=http://ukcast.tv/rtmp://173.192.81.176:443/liverepeater/stream1/token%ZZri(nKa@#Z/pageUrl=http://hdcast.org/cdn.kingofplayers.com/rtmpe://46.246.29.152:1935/redirect/HDMNBC playpath=41?18?49?33?48?38?11 pageUrl=http://popeoftheplayers.eu/hdcast.org/rtmp://31.220.0.134:1935/live/tsn2/pageUrl=http://www.eucast.tv/rtmp://195.154.236.152:80/liverepeater/141449/pageUrl=http://goodcast.pw/rtmp://77.81.98.134/tv/bt1h28qn?v=pageUrl=http://castok.com/rtmp://89.46.102.70:443/liveedge/bt1pageUrl=http://hqstreams.tv/rtmpe://play.finecast.tv/live/hqbt1page/playpath=42?finecast.tv/rtmpe://cdn.hdcast.org:1935/redirect/swfUrl=http://www.hdcast.org/aplayer/jwplayer.flash.swfpageUrl=http://www.hdcast.org/token=Fo5_n0w?U.rA6l3-70w47ch@#8x12pX@ token=#atd%#$ZH\r
 \r
-#endif\r
-\r
-\r
-    std::string contents;\r
-    contents = "#EXTM3U\r\n";\r
-    contents += "\r\n";\r
-\r
-    Dictionary *tuner_channel_to_udp = _streaming_ctrls->dictionaryForKey(KEY_MAPPING_TUNER_CHANNEL_TO_UDP);\r
-    if (tuner_channel_to_udp != NULL)\r
+    if (_iptv_m3u8 != NULL)\r
     {\r
-        Tuner::Type types[] = {Tuner::ISDB_T, Tuner::ISDB_S};\r
-        for (int t = 0; t < sizeof(types) / sizeof(Tuner::Type); ++t)\r
-        {\r
-            for (int i = 0; i < _tunerCount; ++i)\r
-            {\r
-                if (isTunerInitialized(i) && (_tuners[i]->type() == types[t]))\r
-                {\r
-                    uint ch_max = ((types[t] == Tuner::ISDB_T) ? Tuner::MAX_CHANNELS_ISDB_T : Tuner::MAX_CHANNELS_ISDB_S);\r
-                    for (uint ch = 0; ch <= ch_max; ++ch)\r
-                    {\r
-                        if (isChannelEnabled(i, ch))\r
-                        {\r
-                            char tuner_and_channel[10];\r
-                            sprintf_s(tuner_and_channel, "%d,%d", i, ch);\r
-                            char *chstr = strchr(tuner_and_channel, ',');\r
-                            if (chstr != NULL)\r
-                            {\r
-                                ++chstr;\r
-                            }\r
+        result = responseWithUTF8Text(request, _iptv_m3u8);\r
+    }\r
 \r
-                            String *udp_str = tuner_channel_to_udp->stringForKey(tuner_and_channel);\r
-                            if (udp_str != NULL)\r
-                            {\r
-                                contents += "#EXTINF:-1 tvg-id=\"";\r
-                                contents += tuner_and_channel;\r
-                                contents += "\" tvg-logo=\"";\r
-                                contents += ((types[t] == Tuner::ISDB_T) ? "t_" : "s_");\r
-                                if (chstr != NULL)\r
-                                {\r
-                                    contents += chstr;\r
-                                }\r
-                                else\r
-                                {\r
-                                    contents += "ffff";\r
-                                }\r
-                                contents += "\" group-title=\"";\r
-                                contents += _tuners[i]->name();\r
-                                contents += "\", ";\r
-                                String *station_name = stationName(types[t], ch);\r
-                                if (station_name != NULL)\r
-                                {\r
-                                    contents += station_name->cString();\r
-                                }\r
-                                else\r
-                                {\r
-                                    contents += tuner_and_channel;\r
-                                }\r
-                                contents += "\r\n";\r
-                                contents += "udp://0.0.0.0:";\r
-                                contents += udp_str->cString();\r
-                                contents += "\r\n";\r
-                            }\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-        }\r
+    return result;\r
+}\r
 \r
-    }\r
+HTTPResponse *Controller::responseForXmltv(HTTPRequest *request, SOCKADDR_IN *client)\r
+{\r
+    HTTPResponse *result = NULL;\r
 \r
-    String *text = String::stringWithUTF8String(contents.c_str());\r
-    if (text != NULL)\r
+    if (_xmltv_xml != NULL)\r
     {\r
-        result = responseWithUTF8Text(request, text);\r
+        result = responseWithUTF8Text(request, _xmltv_xml);\r
     }\r
 \r
     return result;\r
@@ -4534,6 +4530,10 @@ HTTPResponse *Controller::request(HTTPRequest *request, SOCKADDR_IN *client)
         {\r
             return responseForPlaylist(request, client);\r
         }\r
+        else if (uri->isMatch("^/xmltv.xml$"))\r
+        {\r
+            return responseForXmltv(request, client);\r
+        }\r
 \r
         //\r
         else if (uri->isMatch("^/iptd.log$"))\r
@@ -4770,42 +4770,6 @@ String *Controller::stationName(Tuner::Type type, int channel)
     return result;\r
 }\r
 \r
-// epgの開始時刻でソートする為の比較関数\r
-Integer compareFunction(Object *obj1, Object *obj2, void *context)\r
-{\r
-    if (isKindOfClass(Dictionary, obj1) && isKindOfClass(Dictionary, obj2))\r
-    {\r
-        time_t st1;\r
-        time_t ed1;\r
-        Controller::getTimeWithEPG((Dictionary *)obj1, &st1, &ed1);\r
-\r
-        time_t st2;\r
-        time_t ed2;\r
-        Controller::getTimeWithEPG((Dictionary *)obj2, &st2, &ed2);\r
-\r
-        if (st1 < st2)\r
-        {\r
-            return OrderedAscending;\r
-        }\r
-        else if (st1 > st2)\r
-        {\r
-            return OrderedDescending;\r
-        }\r
-        else\r
-        {\r
-            if (ed1 < ed2)\r
-            {\r
-                return OrderedAscending;\r
-            }\r
-            else if (ed1 > ed2)\r
-            {\r
-                return OrderedDescending;\r
-            }\r
-        }\r
-    }\r
-    return OrderedSame;\r
-}\r
-\r
 Array *Controller::programsForServices(Array *services)\r
 {\r
     DebugLog2("Controller::programsForServices()");\r
@@ -4918,7 +4882,7 @@ void Controller::timerExpired(Timer *timer, void *userInfo)
         {\r
             // 初期化成功\r
             DebugLog2("tuner initialize success.");\r
-#if 0\r
+#if 1\r
             // EPG収集用タイマ起動(ISDB-S)\r
             _timer_epg_s = Timer::alloc()->initWithTimeInterval(DEF_COLLECT_EPG_DELAY, this, (void *)CMD_COLLECT_EPG_ISDB_S, true);\r
             if (_timer_epg_s != NULL)\r
@@ -5365,6 +5329,93 @@ int Controller::restart()
         }\r
     }\r
 \r
+    RELEASE(_service_to_channels);\r
+    _service_to_channels = Dictionary::alloc()->initWithCapacity(0);\r
+\r
+    _xmltv_channels = "";\r
+    std::string str_iptv_m3u8;\r
+    str_iptv_m3u8 = "#EXTM3U\r\n";\r
+    str_iptv_m3u8 += "\r\n";\r
+\r
+    Dictionary *tunerInfos = _props->dictionaryForKey(KEY_TUNERS);\r
+    int idx_isdb_t = 0;\r
+    int idx_isdb_s = 0;\r
+    Tuner::Type type = Tuner::Type::ISDB_T;\r
+    while ((idx_isdb_t < _tunerCount) || (idx_isdb_s < _tunerCount))\r
+    {\r
+        int *idx = (type == Tuner::Type::ISDB_T) ? &idx_isdb_t : &idx_isdb_s;\r
+        while (*idx < _tunerCount)\r
+        {\r
+            if (_tuners[*idx]->type() == type)\r
+            {\r
+                Dictionary *tunerInfo = tunerInfos->dictionaryForKey(_tuners[*idx]->name());\r
+                if (tunerInfo->boolForKey(KEY_ENABLED))\r
+                {\r
+                    int ch_max = (type == Tuner::Type::ISDB_T) ? Tuner::MAX_CHANNELS_ISDB_T : Tuner::MAX_CHANNELS_ISDB_S;\r
+                    for (int ch = 0; ch < ch_max; ++ch)\r
+                    {\r
+                        char key[8];\r
+                        sprintf_s(key, "%03d", ch);\r
+                        Dictionary *channelInfo = tunerInfo->dictionaryForKey(KEY_CHANNELS)->dictionaryForKey(key);\r
+                        if ((channelInfo != NULL) && channelInfo->boolForKey(KEY_ENABLED))\r
+                        {\r
+                            Array *services = channelInfo->arrayForKey(KEY_SERVICES);\r
+                            for (uint service_idx = 0; service_idx < services->count(); ++service_idx)\r
+                            {\r
+                                Dictionary *service = (Dictionary *)services->objectAtIndex(service_idx);\r
+                                char channel_name[32];\r
+                                sprintf_s(channel_name, "%03d_%s", *idx, service->stringForKey(KEY_SERVICE_ID)->cString());\r
+\r
+                                Array *ch_list = _service_to_channels->arrayForKey(service->stringForKey(KEY_SERVICE_ID));\r
+                                if (ch_list == NULL)\r
+                                {\r
+                                    ch_list = Array::arrayWithCapacity(0);\r
+                                    _service_to_channels->setObject(ch_list, service->stringForKey(KEY_SERVICE_ID));\r
+                                }\r
+                                ch_list->addObject(String::stringWithUTF8String(channel_name));\r
+\r
+                                _xmltv_channels += "  <channel id=\"";\r
+                                _xmltv_channels += channel_name;\r
+                                _xmltv_channels += "\"";\r
+                                // transport_stream_id\r
+                                // original_network_id\r
+                                _xmltv_channels += " service_id=\"";\r
+                                _xmltv_channels += service->stringForKey(KEY_SERVICE_ID)->cString();\r
+                                _xmltv_channels += "\">\r\n";\r
+\r
+                                _xmltv_channels += "    <display-name lang=\"ja_JP\">";\r
+                                _xmltv_channels += service->stringForKey(KEY_NAME)->cString();\r
+                                _xmltv_channels += "</display-name>\r\n";\r
+\r
+                                _xmltv_channels += "  </channel>\r\n";\r
+\r
+                                str_iptv_m3u8 += "#EXTINF:-1 tvg-id=\"";\r
+                                str_iptv_m3u8 += channel_name;\r
+                                str_iptv_m3u8 += "\" tvg-logo=\"logo_";\r
+                                str_iptv_m3u8 += channel_name;\r
+                                str_iptv_m3u8 += "\" group-title=\"";\r
+                                str_iptv_m3u8 += _tuners[*idx]->name();\r
+                                str_iptv_m3u8 += "\", ";\r
+                                str_iptv_m3u8 += service->stringForKey(KEY_NAME)->cString();\r
+                                str_iptv_m3u8 += "\r\n";\r
+                                str_iptv_m3u8 += "http://0.0.0.0:50080/";\r
+                                str_iptv_m3u8 += channel_name;\r
+                                str_iptv_m3u8 += "/streaming.m3u8\r\n";\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+                break;\r
+            }\r
+            ++(*idx);\r
+        }\r
+        ++(*idx);\r
+        type = (type == Tuner::Type::ISDB_T) ? Tuner::Type::ISDB_S : Tuner::Type::ISDB_T;\r
+    }\r
+\r
+    _iptv_m3u8 = String::alloc()->initWithUTF8String(str_iptv_m3u8.c_str());\r
+\r
+\r
     // 周期タイマ起動\r
     _timer_periodic = Timer::alloc()->initWithTimeInterval(1.0, this, (void *)CMD_PERIODIC, true);\r
     _timer_periodic->fire();\r
@@ -5391,6 +5442,72 @@ int Controller::start()
     //   設定以前にログ出力しないこと\r
     Raym::LOG_NUM_MAX = 8;\r
 \r
+#if 0\r
+    AutoreleasePool *epg_pool = AutoreleasePool::alloc()->init();\r
+\r
+    class EPGTest : public Raym::TimerDelegate\r
+    {\r
+    public:\r
+        Analyzer *  _an;\r
+        Timer *     _timer;\r
+\r
+        EPGTest(Analyzer *an)\r
+        {\r
+            _an = an;\r
+\r
+            _timer = Timer::alloc()->initWithTimeInterval(3.0, this, NULL, false);\r
+            _timer->fire();\r
+        }\r
+\r
+        ~EPGTest()\r
+        {\r
+            RELEASE(_timer);\r
+        }\r
+\r
+        void timerExpired(Raym::Timer *timer, void *userInfo)\r
+        {\r
+            AutoreleasePool *pool = AutoreleasePool::alloc()->init();\r
+            Data *data = Data::dataWithContentsOfFile("./mini.ts");\r
+            if (data != NULL)\r
+            {\r
+                DebugLog0("open ok");\r
+                _an->put((uint8_t *)data->bytes(), data->length());\r
+            }\r
+            else\r
+            {\r
+                DebugLog0("open ng");\r
+            }\r
+            pool->release();\r
+        }\r
+    };\r
+\r
+    Analyzer *an = Analyzer::alloc()->init();\r
+    EPGTest test(an);\r
+\r
+    Array *collected = an->collectEPGs(60);\r
+    if (collected != NULL)\r
+    {\r
+        DebugLog0("collected: %d", collected->count());\r
+\r
+        Dictionary *dict = Dictionary::dictionaryWithCapacity(0);\r
+        dict->setObject(collected, "Array");\r
+        if (dict->writeToFile("./hoge.plist", false))\r
+        {\r
+            DebugLog0("write ng.");\r
+        }\r
+\r
+        for (uint i = 0; i < collected->count(); ++i)\r
+        {\r
+            Dictionary *epg = (Dictionary *)collected->objectAtIndex(i);\r
+            DebugLog0("EPG: %s", epg->toString().c_str());\r
+        }\r
+    }\r
+\r
+    an->release();\r
+    epg_pool->release();\r
+    return 0;\r
+#endif\r
+\r
     HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());\r
     if (hProcess != NULL)\r
     {\r
@@ -5433,6 +5550,10 @@ int Controller::start()
     _reservation_seq_id = 0;\r
     _cancel_epg_collect = false;\r
 \r
+    _iptv_m3u8          = NULL;\r
+    _xmltv_xml          = NULL;\r
+    _service_to_channels = NULL;\r
+\r
     _tunerCount = 0;\r
     for (int i = 0; i < ry0::device::MAX_TUNERS; ++i)\r
     {\r
@@ -5896,6 +6017,9 @@ int Controller::start()
     RELEASE(_store_path);\r
     RELEASE(_reservations_path);\r
     RELEASE(_reservations);\r
+    RELEASE(_iptv_m3u8);\r
+    RELEASE(_xmltv_xml);\r
+    RELEASE(_service_to_channels);\r
 \r
     if (_multi2_dll != NULL)\r
     {\r
index 2406f67..1336387 100644 (file)
@@ -13,7 +13,7 @@
 #include "net/HTTPDaemon.h"\r
 \r
 #define VERSION "0.03"\r
-#define REVISION 20\r
+#define REVISION 30\r
 \r
 namespace ry0\r
 {\r
@@ -30,7 +30,6 @@ class Controller : public Raym::Application,
                    public NET::HTTPDaemonDelegate\r
 {\r
 private:\r
-//    CRITICAL_SECTION                _cs;\r
 \r
     Raym::String *          _system_path;           // システムパス(実行ファイルが配置されているディレクトリ)\r
     Raym::String *          _props_path;            // プロパティファイルのパス\r
@@ -42,14 +41,14 @@ private:
     Raym::String *          _store_path;            // 録画データ格納先\r
     Raym::Dictionary *      _reservations;          // 予約情報\r
     Raym::String *          _reservations_path;     // 予約情報ファイルのパス\r
-    int                             _reservation_seq_id;    // 予約情報シーケンスID\r
-    int                             _idle_count;            // アイドルカウンタ\r
+    int                     _reservation_seq_id;    // 予約情報シーケンスID\r
+    int                     _idle_count;            // アイドルカウンタ\r
 \r
-    bool                            _initialized;           // 初期化済み\r
-    HMODULE                         _multi2_dll;\r
-    bool                            _cancel_epg_collect;    // EPG収集キャンセル\r
+    bool                    _initialized;           // 初期化済み\r
+    HMODULE                 _multi2_dll;\r
+    bool                    _cancel_epg_collect;    // EPG収集キャンセル\r
 \r
-    NET::HTTPDaemon *               _httpd;\r
+    NET::HTTPDaemon *       _httpd;\r
 \r
     Raym::Dictionary *      _streaming_ctrls;       // ストリーミング制御情報格納用\r
 \r
@@ -60,6 +59,11 @@ private:
     Raym::Timer *           _timer_epg_s;           // EPG(ISDB-S)収集用\r
     Raym::Timer *           _timer_epg_t;           // EPG(ISDB-T)収集用\r
 \r
+    Raym::String *          _iptv_m3u8;\r
+    Raym::String *          _xmltv_xml;\r
+    std::string             _xmltv_channels;\r
+    Raym::Dictionary *      _service_to_channels;\r
+\r
     void scanChannel(int tuner);\r
     void periodic();\r
     void periodic_2();\r
@@ -132,6 +136,7 @@ public:
     NET::HTTPResponse *responseForModKeywordsCGI(NET::HTTPRequest *request, SOCKADDR_IN *client);\r
     NET::HTTPResponse *responseForReloadURI(NET::HTTPRequest *request, SOCKADDR_IN *client, const char *uri, int sec = 0);\r
     NET::HTTPResponse *responseForPlaylist(NET::HTTPRequest *request, SOCKADDR_IN *client);\r
+    NET::HTTPResponse *responseForXmltv(NET::HTTPRequest *request, SOCKADDR_IN *client);\r
     NET::HTTPResponse *responseForHLSControl(NET::HTTPRequest *request, SOCKADDR_IN *client, int tuner, int channel, Raym::String *preset);\r
     NET::HTTPResponse *requestTunerControl(NET::HTTPRequest *request, SOCKADDR_IN *client, int tuner);\r
     NET::HTTPResponse *request(NET::HTTPRequest *request, SOCKADDR_IN *client);\r