00001
00002
00003
00004
00005 #include <stdlib.h>
00006 #include <stdio.h>
00007 #include <zlib.h>
00008
00009 #include "dsmccobjcarousel.h"
00010 #include "dsmccreceiver.h"
00011 #include "dsmcccache.h"
00012 #include "dsmcc.h"
00013
00014 #include "mythcontext.h"
00015
00016
00017 DSMCCCacheModuleData::DSMCCCacheModuleData(DsmccDii *dii,
00018 DsmccModuleInfo *info,
00019 unsigned short streamTag)
00020 : m_carousel_id(dii->download_id), m_module_id(info->module_id),
00021 m_stream_id(streamTag), m_version(info->module_version),
00022 m_moduleSize(info->module_size), m_receivedData(0),
00023 m_completed(false)
00024 {
00025 m_blocks.setAutoDelete(true);
00026
00027
00028 int num_blocks = (m_moduleSize + dii->block_size - 1) / dii->block_size;
00029 m_blocks.fill(NULL, num_blocks);
00030
00031
00032 m_descriptorData = info->modinfo.descriptorData;
00033 }
00034
00039 unsigned char *DSMCCCacheModuleData::AddModuleData(DsmccDb *ddb,
00040 const unsigned char *data)
00041 {
00042 if (m_version != ddb->module_version)
00043 return NULL;
00044
00045 if (m_completed)
00046 return NULL;
00047
00048
00049 VERBOSE(VB_DSMCC, QString("[dsmcc] Module %1 block number %2 length %3")
00050 .arg(ddb->module_id).arg(ddb->block_number).arg(ddb->len));
00051
00052 if (ddb->block_number >= m_blocks.size())
00053 {
00054 VERBOSE(VB_DSMCC, QString("[dsmcc] Module %1 block number %2 "
00055 "is larger than %3")
00056 .arg(ddb->module_id).arg(ddb->block_number)
00057 .arg(m_blocks.size()));
00058
00059 return NULL;
00060 }
00061
00062 if (m_blocks[ddb->block_number] == NULL)
00063 {
00064 QByteArray *block = new QByteArray;
00065 block->duplicate((char*) data, ddb->len);
00066
00067 m_blocks.insert(ddb->block_number, block);
00068 m_receivedData += ddb->len;
00069 }
00070
00071 VERBOSE(VB_DSMCC, QString("[dsmcc] Module %1 Current Size %2 "
00072 "Total Size %3")
00073 .arg(m_module_id).arg(m_receivedData).arg(m_moduleSize));
00074
00075 if (m_receivedData < m_moduleSize)
00076 return NULL;
00077
00078 VERBOSE(VB_DSMCC, QString("[dsmcc] Reconstructing module %1 from blocks")
00079 .arg(m_module_id));
00080
00081
00082 unsigned char *tmp_data = (unsigned char*) malloc(m_receivedData);
00083 if (tmp_data == NULL)
00084 return NULL;
00085
00086 uint curp = 0;
00087 for (uint i = 0; i < m_blocks.size(); i++)
00088 {
00089 QByteArray *block = m_blocks[i];
00090 uint size = block->size();
00091 memcpy(tmp_data + curp, block->data(), size);
00092 curp += size;
00093 }
00094 m_blocks.clear();
00095
00096
00097 if (m_descriptorData.isCompressed)
00098 {
00099 unsigned long dataLen = m_descriptorData.originalSize + 1;
00100 VERBOSE(VB_DSMCC, QString("[dsmcc] uncompressing: "
00101 "compressed size %1, final size %2")
00102 .arg(m_moduleSize).arg(dataLen));
00103
00104 unsigned char *uncompressed = (unsigned char*) malloc(dataLen + 1);
00105 int ret = uncompress(uncompressed, &dataLen, tmp_data, m_moduleSize);
00106 if (ret != Z_OK)
00107 {
00108 VERBOSE(VB_DSMCC,"[dsmcc] compression error, skipping");
00109 free(tmp_data);
00110 free(uncompressed);
00111 return NULL;
00112 }
00113
00114 free(tmp_data);
00115 m_completed = true;
00116 return uncompressed;
00117 }
00118 else
00119 {
00120 m_completed = true;
00121 return tmp_data;
00122 }
00123 }
00124
00125
00126 ObjCarousel::ObjCarousel(Dsmcc *dsmcc)
00127 : filecache(dsmcc), m_id(0)
00128 {
00129 m_Cache.setAutoDelete(true);
00130 }
00131
00132 void ObjCarousel::AddModuleInfo(DsmccDii *dii, Dsmcc *status,
00133 unsigned short streamTag)
00134 {
00135 for (int i = 0; i < dii->number_modules; i++)
00136 {
00137 DSMCCCacheModuleData *cachep;
00138 DsmccModuleInfo *info = &(dii->modules[i]);
00139
00140
00141
00142 for (cachep = m_Cache.first(); cachep; cachep = m_Cache.next())
00143 {
00144 if (cachep->CarouselId() == dii->download_id &&
00145 cachep->ModuleId() == info->module_id)
00146 {
00147
00148 if (cachep->Version() == info->module_version)
00149 {
00150 VERBOSE(VB_DSMCC, QString("[dsmcc] Already Know "
00151 "Module %1")
00152 .arg(info->module_id));
00153 if (cachep->ModuleSize() == info->module_size)
00154 return;
00155
00156
00157
00158 VERBOSE(VB_DSMCC, QString("[dsmcc] Module %1 size "
00159 "has changed (%2 to %3) "
00160 "but version has not!!")
00161 .arg(info->module_id)
00162 .arg(info->module_size)
00163 .arg(cachep->DataSize()));
00164 }
00165
00166 VERBOSE(VB_DSMCC, QString("[dsmcc] Updated "
00167 "Module %1")
00168 .arg(info->module_id));
00169
00170
00171 m_Cache.remove();
00172 break;
00173 }
00174 }
00175
00176 VERBOSE(VB_DSMCC, QString("[dsmcc] Saving info for module %1")
00177 .arg(dii->modules[i].module_id));
00178
00179
00180 cachep = new DSMCCCacheModuleData(dii, info, streamTag);
00181
00182 int tag = info->modinfo.tap.assoc_tag;
00183 VERBOSE(VB_DSMCC, QString("[dsmcc] Module info tap "
00184 "identifies tag %1 with carousel %2\n")
00185 .arg(tag).arg(cachep->CarouselId()));
00186
00187
00188 status->AddTap(tag, cachep->CarouselId());
00189
00190
00191 m_Cache.append(cachep);
00192 }
00193 }
00194
00200 void ObjCarousel::AddModuleData(unsigned long carousel, DsmccDb *ddb,
00201 const unsigned char *data)
00202 {
00203 VERBOSE(VB_DSMCC, QString("[dsmcc] Data block on carousel %1").arg(m_id));
00204
00205
00206 QPtrListIterator<DSMCCCacheModuleData> it(m_Cache);
00207 DSMCCCacheModuleData *cachep;
00208 for (; (cachep = it.current()) != 0; ++it)
00209 {
00210 if (cachep->CarouselId() == carousel &&
00211 (cachep->ModuleId() == ddb->module_id))
00212 {
00213 break;
00214 }
00215 }
00216
00217 if (cachep == NULL)
00218 return;
00219
00220
00221 unsigned char *tmp_data = cachep->AddModuleData(ddb, data);
00222
00223 if (tmp_data)
00224 {
00225
00226 unsigned int len = cachep->DataSize();
00227 unsigned long curp = 0;
00228 VERBOSE(VB_DSMCC, QString("[biop] Module size (uncompressed) = %1")
00229 .arg(len));
00230
00231
00232
00233
00234 while (curp < len)
00235 {
00236 BiopMessage bm;
00237 if (!bm.Process(cachep, &filecache, tmp_data, &curp))
00238 break;
00239 }
00240 free(tmp_data);
00241 }
00242 }