mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-08-27 07:23:09 +02:00
Copy sectionsd code to new eitd directory, to cleanup and leave original code for reference
This commit is contained in:
@@ -174,7 +174,7 @@ data/lcd/clock/Makefile
|
||||
data/locale/Makefile
|
||||
data/scripts/Makefile
|
||||
data/themes/Makefile
|
||||
src/sectionsd/Makefile
|
||||
src/eitd/Makefile
|
||||
src/timerd/Makefile
|
||||
src/zapit/Makefile
|
||||
src/zapit/lib/Makefile
|
||||
|
3052
src/eitd/FreesatTables.hpp
Normal file
3052
src/eitd/FreesatTables.hpp
Normal file
File diff suppressed because it is too large
Load Diff
20
src/eitd/Makefile.am
Normal file
20
src/eitd/Makefile.am
Normal file
@@ -0,0 +1,20 @@
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/lib \
|
||||
-I$(top_srcdir)/src/zapit/include \
|
||||
-I$(top_srcdir)/lib/libconfigfile \
|
||||
-I$(top_srcdir)/lib/connection \
|
||||
-I$(top_srcdir)/lib/libeventserver \
|
||||
-I$(top_srcdir)/lib/xmltree
|
||||
|
||||
if BOXTYPE_COOL
|
||||
INCLUDES += -I$(top_srcdir)/lib/libcoolstream
|
||||
endif
|
||||
if BOXTYPE_TRIPLE
|
||||
INCLUDES += -I$(top_srcdir)/lib/libtriple
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = -D DO_NOT_INCLUDE_STUFF_NOT_NEEDED_FOR_SECTIONSD
|
||||
|
||||
noinst_LIBRARIES = libsectionsd.a
|
||||
libsectionsd_a_SOURCES = sectionsd.cpp dmxapi.cpp debug.cpp dmx.cpp SIsections.cpp SIevents.cpp SIutils.cpp SIlanguage.cpp edvbstring.cpp
|
141
src/eitd/SIbouquets.hpp
Normal file
141
src/eitd/SIbouquets.hpp
Normal file
@@ -0,0 +1,141 @@
|
||||
#ifndef SIBOUQUETS_HPP
|
||||
#define SIBOUQUETS_HPP
|
||||
//
|
||||
// $Id: SIbouquets.hpp,v 1.2 2006/02/08 21:15:50 houdini Exp $
|
||||
//
|
||||
// classes SIservices and SIservices (dbox-II-project)
|
||||
//
|
||||
// Homepage: http://dbox2.elxsi.de
|
||||
//
|
||||
// Copyright (C) 2001 fnbrd (fnbrd@gmx.de),
|
||||
// 2002 thegoodguy (thegoodguy@berlios.de)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <endian.h>
|
||||
|
||||
#include <sectionsdclient/sectionsdMsg.h>
|
||||
|
||||
// forward references
|
||||
class SIservice;
|
||||
class SIevent;
|
||||
class SIbouquet;
|
||||
|
||||
struct loop_len {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved_future_use : 4;
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
#else
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
unsigned reserved_future_use : 4;
|
||||
#endif
|
||||
unsigned descriptors_loop_length_lo : 8;
|
||||
} __attribute__ ((packed)) ; // 2 Bytes
|
||||
|
||||
struct bat_service {
|
||||
|
||||
unsigned transport_stream_id_hi : 8;
|
||||
unsigned transport_stream_id_lo : 8;
|
||||
unsigned original_network_id_hi : 8;
|
||||
unsigned original_network_id_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved_future_use : 4;
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
#else
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
unsigned reserved_future_use : 4;
|
||||
#endif
|
||||
unsigned descriptors_loop_length_lo : 8;
|
||||
|
||||
} __attribute__ ((packed)) ; // 6 Bytes
|
||||
|
||||
|
||||
|
||||
class SIbouquet {
|
||||
public:
|
||||
SIbouquet(const t_bouquet_id _bouquet_id) {
|
||||
|
||||
bouquet_id = _bouquet_id;
|
||||
transport_stream_id = 0;
|
||||
original_network_id = 0;
|
||||
service_id = 0;
|
||||
serviceTyp = 0;
|
||||
// position = 0;
|
||||
bouquetName = "";
|
||||
}
|
||||
|
||||
// Um einen service zum Suchen zu erstellen
|
||||
SIbouquet(const t_bouquet_id _bouquet_id, const t_service_id _service_id, const t_original_network_id _original_network_id, const t_transport_stream_id _transport_stream_id)
|
||||
{
|
||||
service_id = _service_id;
|
||||
original_network_id = _original_network_id;
|
||||
transport_stream_id = _transport_stream_id;
|
||||
serviceTyp = 0;
|
||||
// position = 0;
|
||||
}
|
||||
// Std-Copy
|
||||
SIbouquet(const SIbouquet &s) {
|
||||
|
||||
service_id = s.service_id;
|
||||
original_network_id = s.original_network_id;
|
||||
transport_stream_id = s.transport_stream_id;
|
||||
bouquet_id = s.bouquet_id;
|
||||
bouquetName = s.bouquetName;
|
||||
serviceTyp = s.serviceTyp;
|
||||
position = s.position;
|
||||
}
|
||||
|
||||
t_bouquet_id bouquet_id; // This is because of wrong design of sectionsd. Normally we would parse only tables instead of sections...
|
||||
std::string bouquetName; // This is because of wrong design of sectionsd. Normally we would parse only tables instead of sections...
|
||||
t_original_network_id original_network_id;
|
||||
t_transport_stream_id transport_stream_id;
|
||||
t_service_id service_id;
|
||||
uint16_t position;
|
||||
unsigned char serviceTyp;
|
||||
bool operator < (const SIbouquet& s) const {
|
||||
return uniqueKey() < s.uniqueKey();
|
||||
}
|
||||
|
||||
t_bouquetentry_id uniqueKey(void) const {
|
||||
return CREATE_BOUQUETENTRY_ID(bouquet_id, (uint16_t) serviceTyp, position, service_id);
|
||||
}
|
||||
|
||||
void dump(void) const {
|
||||
|
||||
printf("Bouquet-ID: %hu\n", bouquet_id);
|
||||
printf("Original-Network-ID: %hu\n", original_network_id);
|
||||
printf("Transport-Stream-ID: %hu\n", transport_stream_id);
|
||||
printf("Service-ID: %hu\n", service_id);
|
||||
printf("Service-Typ: %hhu\n", serviceTyp);
|
||||
if(bouquetName.length())
|
||||
printf("Bouquet-Name: %s\n", bouquetName.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSIbouquet : public std::unary_function<SIbouquet, void>
|
||||
{
|
||||
void operator() (const SIbouquet &s) { s.dump();}
|
||||
};
|
||||
|
||||
// Als Klasse, da ich nicht weiss, wie man eine Forward-Referenz auf ein typedef macht
|
||||
class SIbouquets : public std::set <SIbouquet, std::less<SIbouquet> >
|
||||
{
|
||||
};
|
||||
|
||||
#endif // SIBOUQUETS_HPP
|
593
src/eitd/SIevents.cpp
Normal file
593
src/eitd/SIevents.cpp
Normal file
@@ -0,0 +1,593 @@
|
||||
//
|
||||
// $Id: SIevents.cpp,v 1.35 2008/08/16 19:23:18 seife Exp $
|
||||
//
|
||||
// classes SIevent and SIevents (dbox-II-project)
|
||||
//
|
||||
// Homepage: http://dbox2.elxsi.de
|
||||
//
|
||||
// Copyright (C) 2001 fnbrd (fnbrd@gmx.de)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/poll.h> // fuer poll()
|
||||
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "SIlanguage.hpp"
|
||||
#include "SIutils.hpp"
|
||||
#include "SIservices.hpp"
|
||||
#include "SIevents.hpp"
|
||||
#ifdef UPDATE_NETWORKS
|
||||
#include "SIbouquets.hpp"
|
||||
#include "SInetworks.hpp"
|
||||
#endif
|
||||
#include "SIsections.hpp"
|
||||
#include <dmxapi.h>
|
||||
|
||||
const std::string languangeOFF = "OFF";
|
||||
|
||||
SIevent::SIevent(const struct eit_event *e)
|
||||
{
|
||||
eventID = (e->event_id_hi << 8) | e->event_id_lo;
|
||||
time_t start_time = changeUTCtoCtime(((const unsigned char *)e) + 2);
|
||||
unsigned long duration = 0;
|
||||
|
||||
if (!((e->duration_hi == 0xff) && (e->duration_mid == 0xff) && (e->duration_lo == 0xff)))
|
||||
duration = ((e->duration_hi)>>4)*10*3600L + ((e->duration_hi)&0x0f)*3600L +
|
||||
((e->duration_mid)>>4)*10*60L + ((e->duration_mid)&0x0f)*60L +
|
||||
((e->duration_lo)>>4)*10 + ((e->duration_lo)&0x0f);
|
||||
|
||||
if (start_time && duration)
|
||||
times.insert(SItime(start_time, duration));
|
||||
|
||||
running = (int)e->running_status;
|
||||
|
||||
table_id = 0xFF; /* not set */
|
||||
version = 0xFF;
|
||||
service_id = 0;
|
||||
original_network_id = 0;
|
||||
transport_stream_id = 0;
|
||||
}
|
||||
|
||||
SIevent::SIevent(const t_original_network_id _original_network_id, const t_transport_stream_id _transport_stream_id, const t_service_id _service_id,
|
||||
const unsigned short _event_id)
|
||||
{
|
||||
original_network_id = _original_network_id;
|
||||
transport_stream_id = _transport_stream_id;
|
||||
service_id = _service_id;
|
||||
eventID = _event_id;
|
||||
table_id = 0xFF; /* not set */
|
||||
version = 0xFF;
|
||||
/* contentClassification = "";
|
||||
userClassification = "";
|
||||
itemDescription = "";
|
||||
item = "";
|
||||
extendedText = "";*/
|
||||
}
|
||||
|
||||
// Std-Copy
|
||||
SIevent::SIevent(const SIevent &e)
|
||||
{
|
||||
eventID=e.eventID;
|
||||
langName=e.langName;
|
||||
langText=e.langText;
|
||||
// startzeit=e.startzeit;
|
||||
// dauer=e.dauer;
|
||||
times=e.times;
|
||||
service_id = e.service_id;
|
||||
original_network_id = e.original_network_id;
|
||||
transport_stream_id = e.transport_stream_id;
|
||||
itemDescription=e.itemDescription;
|
||||
item=e.item;
|
||||
langExtendedText=e.langExtendedText;
|
||||
contentClassification=e.contentClassification;
|
||||
userClassification=e.userClassification;
|
||||
components=e.components;
|
||||
ratings=e.ratings;
|
||||
linkage_descs=e.linkage_descs;
|
||||
running=e.running;
|
||||
vps = e.vps;
|
||||
table_id = e.table_id;
|
||||
version = e.version;
|
||||
}
|
||||
|
||||
int SIevent::saveXML(FILE *file, const char *serviceName) const
|
||||
{
|
||||
if(saveXML0(file))
|
||||
return 1;
|
||||
if(serviceName) {
|
||||
if(fprintf(file, " <service_name>")<0)
|
||||
return 2;
|
||||
saveStringToXMLfile(file, serviceName);
|
||||
if(fprintf(file, "</service_name>\n")<0)
|
||||
return 3;
|
||||
}
|
||||
return saveXML2(file);
|
||||
}
|
||||
|
||||
char SIevent::getFSK() const
|
||||
{
|
||||
for (SIparentalRatings::iterator it = ratings.begin(); it != ratings.end(); ++it)
|
||||
{
|
||||
if (it->countryCode == "DEU")
|
||||
{
|
||||
if ((it->rating >= 0x01) && (it->rating <= 0x0F))
|
||||
return (it->rating + 3); // 0x01 to 0x0F minimum age = rating + 3 years
|
||||
else
|
||||
return (it->rating == 0 ? 0 : 18); // return FSK 18 for : 0x10 to 0xFF defined by the broadcaster
|
||||
}
|
||||
}
|
||||
if (!ratings.empty())
|
||||
{
|
||||
if ((ratings.begin()->rating >= 0x01) && (ratings.begin()->rating <= 0x0F))
|
||||
return (ratings.begin()->rating + 3);
|
||||
else
|
||||
return (ratings.begin()->rating == 0 ? 0 : 18);
|
||||
}
|
||||
|
||||
return 0x00; // 0x00 undefined
|
||||
}
|
||||
|
||||
int SIevent::saveXML0(FILE *file) const
|
||||
{
|
||||
if(fprintf(file, "\t\t<event id=\"%04x\">\n", eventID)<0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SIevent::saveXML2(FILE *file) const
|
||||
{
|
||||
for (std::map<std::string, std::string>::const_iterator
|
||||
i = langName.begin() ;
|
||||
i != langName.end() ;
|
||||
i++) {
|
||||
if (i->second.length()) {
|
||||
fprintf(file, "\t\t\t<name lang=\"%s\" string=\"", i->first.c_str());
|
||||
saveStringToXMLfile(file, i->second.c_str());
|
||||
fprintf(file, "\"/>\n");
|
||||
}
|
||||
}
|
||||
for (std::map<std::string, std::string>::const_iterator
|
||||
i = langText.begin() ;
|
||||
i != langText.end() ;
|
||||
i++) {
|
||||
if (i->second.length()) {
|
||||
fprintf(file, "\t\t\t<text lang=\"%s\" string=\"", i->first.c_str());
|
||||
saveStringToXMLfile(file, i->second.c_str());
|
||||
fprintf(file, "\"/>\n");
|
||||
}
|
||||
}
|
||||
if(item.length()) {
|
||||
fprintf(file, "\t\t\t<item string=\"");
|
||||
saveStringToXMLfile(file, item.c_str());
|
||||
fprintf(file, "\"/>\n");
|
||||
}
|
||||
if(itemDescription.length()) {
|
||||
fprintf(file, "\t\t\t<item_description string=\"");
|
||||
saveStringToXMLfile(file, itemDescription.c_str());
|
||||
fprintf(file, "\"/>\n");
|
||||
}
|
||||
for (std::map<std::string, std::string>::const_iterator
|
||||
i = langExtendedText.begin() ;
|
||||
i != langExtendedText.end() ;
|
||||
i++) {
|
||||
if (i->second.length()) {
|
||||
fprintf(file, "\t\t\t<extended_text lang=\"%s\" string=\"", i->first.c_str());
|
||||
saveStringToXMLfile(file, i->second.c_str());
|
||||
fprintf(file, "\"/>\n");
|
||||
}
|
||||
}
|
||||
for_each(times.begin(), times.end(), saveSItimeXML(file));
|
||||
for(unsigned i=0; i<contentClassification.length(); i++)
|
||||
fprintf(file, "\t\t\t<content class=\"%02x\" user=\"%02x\"/>\n", contentClassification[i], userClassification[i]);
|
||||
for_each(components.begin(), components.end(), saveSIcomponentXML(file));
|
||||
for_each(ratings.begin(), ratings.end(), saveSIparentalRatingXML(file));
|
||||
for_each(linkage_descs.begin(), linkage_descs.end(), saveSIlinkageXML(file));
|
||||
fprintf(file, "\t\t</event>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string SIevent::getName() const
|
||||
{
|
||||
if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) {
|
||||
std::map<std::string, std::string>::const_iterator it = langName.begin() ;
|
||||
if (it != langName.end()) return it->second;
|
||||
else return("");
|
||||
} else {
|
||||
std::string retval;
|
||||
SIlanguage::filter(langName, 1, retval);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
void SIevent::setName(const std::string &lang, const std::string &name)
|
||||
{
|
||||
std::string tmp = name;
|
||||
std::replace(tmp.begin(), tmp.end(), '\n', ' ');
|
||||
//printf("setName: lang %s text %s\n", lang.c_str(), name.c_str());
|
||||
if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) {
|
||||
langName[languangeOFF] = tmp; //name;
|
||||
} else {
|
||||
langName[lang] = tmp; //name;
|
||||
}
|
||||
}
|
||||
|
||||
std::string SIevent::getText() const
|
||||
{
|
||||
if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) {
|
||||
std::map<std::string, std::string>::const_iterator it = langText.begin() ;
|
||||
if (it != langText.end()) return it->second;
|
||||
else return("");
|
||||
} else {
|
||||
std::string retval;
|
||||
SIlanguage::filter(langText, 0, retval);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
void SIevent::setText(const std::string &lang, const std::string &text)
|
||||
{
|
||||
//printf("setText: lang %s text %s\n", lang.c_str(), text.c_str());
|
||||
if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) {
|
||||
langText[languangeOFF] = text;
|
||||
} else {
|
||||
langText[lang] = text;
|
||||
}
|
||||
}
|
||||
|
||||
std::string SIevent::getExtendedText() const
|
||||
{
|
||||
if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) {
|
||||
std::map<std::string, std::string>::const_iterator it = langExtendedText.begin() ;
|
||||
if (it != langExtendedText.end()) return it->second;
|
||||
else return("");
|
||||
} else {
|
||||
std::string retval;
|
||||
SIlanguage::filter(langExtendedText, 0, retval);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
void SIevent::appendExtendedText(const std::string &lang, const std::string &text)
|
||||
{
|
||||
if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) {
|
||||
langExtendedText[languangeOFF] += text;
|
||||
} else {
|
||||
langExtendedText[lang] += text;
|
||||
}
|
||||
}
|
||||
|
||||
void SIevent::setExtendedText(const std::string &lang, const std::string &text)
|
||||
{
|
||||
//printf("setExtendedText: lang %s text %s\n", lang.c_str(), text.c_str());
|
||||
if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) {
|
||||
langExtendedText[languangeOFF] = text;
|
||||
} else {
|
||||
langExtendedText[lang] = text;
|
||||
}
|
||||
}
|
||||
|
||||
void SIevent::dump(void) const
|
||||
{
|
||||
printf("Unique key: %llx\n", uniqueKey());
|
||||
if(original_network_id)
|
||||
printf("Original-Network-ID: %hu\n", original_network_id);
|
||||
if (service_id)
|
||||
printf("Service-ID: %hu\n", service_id);
|
||||
printf("Event-ID: %hu\n", eventID);
|
||||
if(item.length())
|
||||
printf("Item: %s\n", item.c_str());
|
||||
if(itemDescription.length())
|
||||
printf("Item-Description: %s\n", itemDescription.c_str());
|
||||
|
||||
for (std::map<std::string, std::string>::const_iterator it = langName.begin() ;
|
||||
it != langName.end() ; ++it)
|
||||
printf("Name (%s): %s\n", it->first.c_str(), it->second.c_str());
|
||||
for (std::map<std::string, std::string>::const_iterator it = langText.begin() ;
|
||||
it != langText.end() ; ++it)
|
||||
printf("Text (%s): %s\n", it->first.c_str(), it->second.c_str());
|
||||
for (std::map<std::string, std::string>::const_iterator it = langExtendedText.begin() ;
|
||||
it != langExtendedText.end() ; ++it)
|
||||
printf("Extended-Text (%s): %s\n", it->first.c_str(), it->second.c_str());
|
||||
|
||||
if(contentClassification.length()) {
|
||||
printf("Content classification:");
|
||||
for(unsigned i=0; i<contentClassification.length(); i++)
|
||||
printf(" 0x%02hhx", contentClassification[i]);
|
||||
printf("\n");
|
||||
}
|
||||
if(userClassification.length()) {
|
||||
printf("User classification:");
|
||||
for(unsigned i=0; i<userClassification.length(); i++)
|
||||
printf(" 0x%02hhx", userClassification[i]);
|
||||
printf("\n");
|
||||
}
|
||||
/*
|
||||
if(startzeit)
|
||||
printf("Startzeit: %s", ctime(&startzeit));
|
||||
if(dauer)
|
||||
printf("Dauer: %02u:%02u:%02u (%umin, %us)\n", dauer/3600, (dauer%3600)/60, dauer%60, dauer/60, dauer);
|
||||
*/
|
||||
for_each(times.begin(), times.end(), printSItime());
|
||||
for_each(components.begin(), components.end(), printSIcomponent());
|
||||
for_each(ratings.begin(), ratings.end(), printSIparentalRating());
|
||||
for_each(linkage_descs.begin(), linkage_descs.end(), printSIlinkage());
|
||||
}
|
||||
|
||||
void SIevent::dumpSmall(void) const
|
||||
{
|
||||
for (std::map<std::string, std::string>::const_iterator it = langName.begin() ;
|
||||
it != langName.end() ; ++it)
|
||||
printf("Name (%s): %s\n", it->first.c_str(), it->second.c_str());
|
||||
for (std::map<std::string, std::string>::const_iterator it = langText.begin() ;
|
||||
it != langText.end() ; ++it)
|
||||
printf("Text (%s): %s\n", it->first.c_str(), it->second.c_str());
|
||||
for (std::map<std::string, std::string>::const_iterator it = langExtendedText.begin() ;
|
||||
it != langExtendedText.end() ; ++it)
|
||||
printf("Extended-Text (%s): %s\n", it->first.c_str(), it->second.c_str());
|
||||
/*
|
||||
if(startzeit)
|
||||
printf("Startzeit: %s", ctime(&startzeit));
|
||||
if(dauer)
|
||||
printf("Dauer: %02u:%02u:%02u (%umin, %us)\n", dauer/3600, (dauer%3600)/60, dauer%60, dauer/60, dauer);
|
||||
*/
|
||||
for_each(times.begin(), times.end(), printSItime());
|
||||
for_each(ratings.begin(), ratings.end(), printSIparentalRating());
|
||||
for_each(linkage_descs.begin(), linkage_descs.end(), printSIlinkage());
|
||||
}
|
||||
/*
|
||||
// Liest n Bytes aus einem Socket per read
|
||||
inline int readNbytes(int fd, char *buf, int n)
|
||||
{
|
||||
int j;
|
||||
for(j=0; j<n;) {
|
||||
int r=read (fd, buf, n-j);
|
||||
if(r<=0) {
|
||||
perror ("read");
|
||||
return -1;
|
||||
}
|
||||
j+=r;
|
||||
buf+=r;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
*/
|
||||
|
||||
#ifndef DO_NOT_INCLUDE_STUFF_NOT_NEEDED_FOR_SECTIONSD
|
||||
// Liest n Bytes aus einem Socket per read
|
||||
// Liefert 0 bei timeout
|
||||
// und -1 bei Fehler
|
||||
// ansonsten die Anzahl gelesener Bytes
|
||||
inline int readNbytes(int fd, char *buf, int n, unsigned timeoutInSeconds)
|
||||
{
|
||||
int j;
|
||||
for(j=0; j<n;) {
|
||||
struct pollfd ufds;
|
||||
// memset(&ufds, 0, sizeof(ufds));
|
||||
ufds.fd=fd;
|
||||
ufds.events=POLLIN|POLLPRI;
|
||||
ufds.revents=0;
|
||||
int rc=poll(&ufds, 1, timeoutInSeconds*1000);
|
||||
if(!rc)
|
||||
return 0; // timeout
|
||||
else if(rc<0) {
|
||||
perror ("poll");
|
||||
return -1;
|
||||
}
|
||||
int r=read (fd, buf, n-j);
|
||||
if(r<=0) {
|
||||
perror ("read");
|
||||
return -1;
|
||||
}
|
||||
j+=r;
|
||||
buf+=r;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
SIevent SIevent::readActualEvent(t_service_id serviceID, unsigned timeoutInSeconds)
|
||||
{
|
||||
int fd;
|
||||
SIevent evt; // Std-Event das bei Fehler zurueckgeliefert wird
|
||||
struct SI_section_header header;
|
||||
char *buf;
|
||||
unsigned short section_length;
|
||||
|
||||
if ((fd = open(DEMUX_DEVICE, O_RDWR)) == -1) {
|
||||
perror(DEMUX_DEVICE);
|
||||
return evt;
|
||||
}
|
||||
|
||||
if (!setfilter(fd, 0x12, 0x4e, 0xff, DMX_IMMEDIATE_START | DMX_CHECK_CRC)) {
|
||||
close(fd);
|
||||
return evt;
|
||||
}
|
||||
|
||||
time_t szeit = time(NULL);
|
||||
|
||||
// Segment mit Event fuer sid suchen
|
||||
do {
|
||||
int rc = readNbytes(fd, (char *)&header, sizeof(header), timeoutInSeconds);
|
||||
|
||||
if(!rc)
|
||||
break; // timeout
|
||||
|
||||
else if(rc<0) {
|
||||
close(fd);
|
||||
perror ("read header");
|
||||
return evt;
|
||||
}
|
||||
|
||||
section_length = (header.section_length_hi << 8) | header.section_length_lo;
|
||||
|
||||
buf = new char[sizeof(header) + section_length - 5];
|
||||
|
||||
if (!buf) {
|
||||
close(fd);
|
||||
printf("Not enough memory!\n");
|
||||
return evt;
|
||||
}
|
||||
|
||||
// Den Header kopieren
|
||||
memmove(buf, &header, sizeof(header));
|
||||
rc = readNbytes(fd, &buf[sizeof(header)], section_length - 5, timeoutInSeconds);
|
||||
|
||||
if(!rc) {
|
||||
delete[] buf;
|
||||
break; // timeout
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
close(fd);
|
||||
delete[] buf;
|
||||
perror ("read section");
|
||||
return evt;
|
||||
}
|
||||
|
||||
if (header.current_next_indicator) {
|
||||
// Wir wollen nur aktuelle sections
|
||||
SIsectionEIT e(SIsection(sizeof(header) + section_length - 5, buf));
|
||||
time_t zeit = time(NULL);
|
||||
for (SIevents::iterator k = e.events().begin(); k != e.events().end(); ++k)
|
||||
if (k->service_id == serviceID)
|
||||
for (SItimes::iterator t = k->times.begin(); t != k->times.end(); ++t)
|
||||
if ((t->startzeit <= zeit) && (zeit <= (long)(t->startzeit+t->dauer))) {
|
||||
close(fd);
|
||||
return SIevent(*k);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
} while (time(NULL) < szeit + (long)timeoutInSeconds);
|
||||
|
||||
close(fd);
|
||||
return evt;
|
||||
}
|
||||
|
||||
void SIevents::removeOldEvents(long seconds)
|
||||
{
|
||||
time_t current_time = time(NULL);
|
||||
|
||||
for(SIevents::iterator it = begin(); it != end(); )
|
||||
{
|
||||
// "it->times.erase(kt);":
|
||||
// passing `const SItimes' as `this' argument of `void set<SItime,less<SItime>,allocator<SItime> >::erase(_Rb_tree_iterator<SItime,const SItime &,const SItime *>)' discards qualifiers
|
||||
|
||||
// hence we have to modify a copy
|
||||
|
||||
SIevent copy_of_event(*it);
|
||||
bool copy_has_changed = false;
|
||||
|
||||
for (SItimes::iterator jt = copy_of_event.times.begin(); jt != copy_of_event.times.end(); )
|
||||
{
|
||||
if ((jt->startzeit) + (int)(jt->dauer) < current_time - seconds)
|
||||
{
|
||||
copy_of_event.times.erase(jt++);
|
||||
copy_has_changed = true;
|
||||
}
|
||||
else
|
||||
++jt;
|
||||
}
|
||||
if (copy_has_changed)
|
||||
{
|
||||
erase(it++);
|
||||
|
||||
// Set has the important property that inserting a new element into a set does not
|
||||
// invalidate iterators that point to existing elements.
|
||||
if (copy_of_event.times.size() != 0)
|
||||
#ifdef DEBUG
|
||||
assert((++insert(it, copy_of_event)) == it);
|
||||
#else
|
||||
insert(it, copy_of_event); // it is the hint where to insert (I hope that doesn't invalidate it)
|
||||
// insert(copy_of_event); // alternative method without hint
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Entfernt anhand der Services alle time shifted events (ohne Text,
|
||||
// mit service-id welcher im nvod steht)
|
||||
// und sortiert deren Zeiten in die Events mit dem Text ein.
|
||||
void SIevents::mergeAndRemoveTimeShiftedEvents(const SIservices &services)
|
||||
{
|
||||
// Wir gehen alle services durch, suchen uns die services mit nvods raus
|
||||
// und fuegen dann die Zeiten der Events mit der service-id eines nvods
|
||||
// in das entsprechende Event mit der service-id das die nvods hat ein.
|
||||
// die 'nvod-events' werden auch geloescht
|
||||
|
||||
// SIevents eventsToDelete; // Hier rein kommen Events die geloescht werden sollen
|
||||
for(SIservices::iterator k=services.begin(); k!=services.end(); ++k)
|
||||
if(k->nvods.size()) {
|
||||
// NVOD-Referenzen gefunden
|
||||
// Zuerst mal das Event mit dem Text holen
|
||||
iterator e;
|
||||
for(e=begin(); e!=end(); ++e)
|
||||
if(e->service_id == k->service_id)
|
||||
break;
|
||||
if(e!=end()) {
|
||||
// *e == event mit dem Text
|
||||
SIevent newEvent(*e); // Kopie des Events
|
||||
// Jetzt die nvods druchgehen und deren Uhrzeiten in obiges Event einfuegen
|
||||
for(SInvodReferences::iterator n=k->nvods.begin(); n!=k->nvods.end(); ++n) {
|
||||
// Alle druchgehen und deren Events suchen
|
||||
for(iterator en=begin(); en!=end(); en++) {
|
||||
if(en->service_id==n->getServiceID()) {
|
||||
newEvent.times.insert(en->times.begin(), en->times.end());
|
||||
// newEvent.times.insert(SItime(en->startzeit, en->dauer));
|
||||
// eventsToDelete.insert(SIevent(*en));
|
||||
}
|
||||
}
|
||||
}
|
||||
erase(e); // Altes Event loeschen -> iterator (e) ung<6E>ltig
|
||||
insert(newEvent); // und das erweiterte Event wieder einfuegen
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// delete all events with serviceID that have a service type 0
|
||||
//
|
||||
for (iterator it = begin(); it != end(); )
|
||||
{
|
||||
SIservices::iterator s = services.find(SIservice(it->service_id, it->original_network_id, it->transport_stream_id));
|
||||
if ((s != services.end()) && (s->serviceTyp == 0))
|
||||
{
|
||||
// Set is a Sorted Associative Container
|
||||
// Erasing an element from a set also does not invalidate any iterators,
|
||||
// except, of course, for iterators that actually point to the element
|
||||
// that is being erased.
|
||||
erase(it++);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
#endif
|
488
src/eitd/SIevents.hpp
Normal file
488
src/eitd/SIevents.hpp
Normal file
@@ -0,0 +1,488 @@
|
||||
#ifndef SIEVENTS_HPP
|
||||
#define SIEVENTS_HPP
|
||||
//
|
||||
// $Id: SIevents.hpp,v 1.29 2008/08/16 19:23:18 seife Exp $
|
||||
//
|
||||
// classes SIevent and SIevents (dbox-II-project)
|
||||
//
|
||||
// Homepage: http://dbox2.elxsi.de
|
||||
//
|
||||
// Copyright (C) 2001 fnbrd (fnbrd@gmx.de)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
|
||||
#include <endian.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <sectionsdclient/sectionsdtypes.h>
|
||||
#include "edvbstring.h"
|
||||
//#include "SIutils.hpp"
|
||||
|
||||
// forward references
|
||||
class SIservice;
|
||||
class SIservices;
|
||||
class SIbouquets;
|
||||
|
||||
struct eit_event {
|
||||
unsigned event_id_hi : 8;
|
||||
unsigned event_id_lo : 8;
|
||||
unsigned start_time_hi : 8;
|
||||
unsigned start_time_hi2 : 8;
|
||||
unsigned start_time_mid : 8;
|
||||
unsigned start_time_lo2 : 8;
|
||||
unsigned start_time_lo : 8;
|
||||
unsigned duration_hi : 8;
|
||||
unsigned duration_mid : 8;
|
||||
unsigned duration_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned running_status : 3;
|
||||
unsigned free_CA_mode : 1;
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
#else
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
unsigned free_CA_mode : 1;
|
||||
unsigned running_status : 3;
|
||||
#endif
|
||||
unsigned descriptors_loop_length_lo : 8;
|
||||
} __attribute__ ((packed)) ;
|
||||
|
||||
|
||||
struct descr_component_header {
|
||||
unsigned descriptor_tag : 8;
|
||||
unsigned descriptor_length : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved_future_use : 4;
|
||||
unsigned stream_content : 4;
|
||||
#else
|
||||
unsigned stream_content : 4;
|
||||
unsigned reserved_future_use : 4;
|
||||
#endif
|
||||
unsigned component_type : 8;
|
||||
unsigned component_tag : 8;
|
||||
unsigned iso_639_2_language_code_hi : 8;
|
||||
unsigned iso_639_2_language_code_mid : 8;
|
||||
unsigned iso_639_2_language_code_lo : 8;
|
||||
} __attribute__ ((packed)) ;
|
||||
|
||||
struct descr_linkage_header {
|
||||
unsigned descriptor_tag : 8;
|
||||
unsigned descriptor_length : 8;
|
||||
unsigned transport_stream_id_hi : 8;
|
||||
unsigned transport_stream_id_lo : 8;
|
||||
unsigned original_network_id_hi : 8;
|
||||
unsigned original_network_id_lo : 8;
|
||||
unsigned service_id_hi : 8;
|
||||
unsigned service_id_lo : 8;
|
||||
unsigned linkage_type : 8;
|
||||
} __attribute__ ((packed)) ;
|
||||
|
||||
struct descr_pdc_header {
|
||||
unsigned descriptor_tag : 8;
|
||||
unsigned descriptor_length : 8;
|
||||
unsigned pil0 : 8;
|
||||
unsigned pil1 : 8;
|
||||
unsigned pil2 : 8;
|
||||
} __attribute__ ((packed)) ;
|
||||
|
||||
class SIlinkage {
|
||||
public:
|
||||
SIlinkage(const struct descr_linkage_header *link) {
|
||||
linkageType = link->linkage_type;
|
||||
transportStreamId = (link->transport_stream_id_hi << 8) | link->transport_stream_id_lo;
|
||||
originalNetworkId = (link->original_network_id_hi << 8) | link->original_network_id_lo;
|
||||
serviceId = (link->service_id_hi << 8) | link->service_id_lo;
|
||||
if (link->descriptor_length > sizeof(struct descr_linkage_header) - 2)
|
||||
//name = std::string(((const char *)link) + sizeof(struct descr_linkage_header), link->descriptor_length - (sizeof(struct descr_linkage_header) - 2));
|
||||
name = convertDVBUTF8(((const char *)link)+sizeof(struct descr_linkage_header), link->descriptor_length-(sizeof(struct descr_linkage_header)-2), 0, 0);
|
||||
}
|
||||
|
||||
// Std-copy
|
||||
SIlinkage(const SIlinkage &l) {
|
||||
linkageType = l.linkageType;
|
||||
transportStreamId = l.transportStreamId;
|
||||
originalNetworkId = l.originalNetworkId;
|
||||
serviceId = l.serviceId;
|
||||
name = l.name;
|
||||
}
|
||||
|
||||
// default
|
||||
SIlinkage(void) {
|
||||
linkageType = 0;
|
||||
transportStreamId = 0;
|
||||
originalNetworkId = 0;
|
||||
serviceId = 0;
|
||||
// name = ;
|
||||
}
|
||||
|
||||
// Der Operator zum sortieren
|
||||
bool operator < (const SIlinkage& l) const {
|
||||
return name < l.name;
|
||||
}
|
||||
|
||||
void dump(void) const {
|
||||
printf("Linakge Type: 0x%02hhx\n", linkageType);
|
||||
if (name.length())
|
||||
printf("Name: %s\n", name.c_str());
|
||||
printf("Transport Stream Id: 0x%04hhx\n", transportStreamId);
|
||||
printf("Original Network Id: 0x%04hhx\n", originalNetworkId);
|
||||
printf("Service Id: 0x%04hhx\n", serviceId);
|
||||
}
|
||||
|
||||
int saveXML(FILE *file) const {
|
||||
fprintf(file, "\t\t\t<linkage type=\"%02x\" linkage_descriptor=\"", linkageType);
|
||||
saveStringToXMLfile(file, name.c_str());
|
||||
fprintf(file, "\" transport_stream_id=\"%04x\" original_network_id=\"%04x\" service_id=\"%04x\" />\n", transportStreamId, originalNetworkId, serviceId);
|
||||
// %s, , name.c_str())<0)
|
||||
// return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char linkageType; // Linkage Descriptor
|
||||
std::string name; // Text aus dem Linkage Descriptor
|
||||
t_transport_stream_id transportStreamId; // Linkage Descriptor
|
||||
t_original_network_id originalNetworkId; // Linkage Descriptor
|
||||
t_service_id serviceId; // Linkage Descriptor
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSIlinkage : public std::unary_function<class SIlinkage, void>
|
||||
{
|
||||
void operator() (const SIlinkage &l) { l.dump();}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct saveSIlinkageXML : public std::unary_function<class SIlinkage, void>
|
||||
{
|
||||
FILE *f;
|
||||
saveSIlinkageXML(FILE *fi) { f=fi;}
|
||||
void operator() (const SIlinkage &l) { l.saveXML(f);}
|
||||
};
|
||||
|
||||
//typedef std::multiset <SIlinkage, std::less<SIlinkage> > SIlinkage_descs;
|
||||
typedef std::vector<class SIlinkage> SIlinkage_descs;
|
||||
|
||||
class SIcomponent {
|
||||
public:
|
||||
SIcomponent(const struct descr_component_header *comp) {
|
||||
streamContent=comp->stream_content;
|
||||
componentType=comp->component_type;
|
||||
componentTag=comp->component_tag;
|
||||
if(comp->descriptor_length>sizeof(struct descr_component_header)-2)
|
||||
//component=std::string(((const char *)comp)+sizeof(struct descr_component_header), comp->descriptor_length-(sizeof(struct descr_component_header)-2));
|
||||
component=convertDVBUTF8(((const char *)comp)+sizeof(struct descr_component_header), comp->descriptor_length-(sizeof(struct descr_component_header)-2), 0, 0);
|
||||
}
|
||||
// Std-copy
|
||||
SIcomponent(const SIcomponent &c) {
|
||||
streamContent=c.streamContent;
|
||||
componentType=c.componentType;
|
||||
componentTag=c.componentTag;
|
||||
component=c.component;
|
||||
}
|
||||
|
||||
SIcomponent(void) {
|
||||
streamContent=0;
|
||||
componentType=0;
|
||||
componentTag=0;
|
||||
}
|
||||
// Der Operator zum sortieren
|
||||
bool operator < (const SIcomponent& c) const {
|
||||
return streamContent < c.streamContent;
|
||||
// return component < c.component;
|
||||
}
|
||||
void dump(void) const {
|
||||
if(component.length())
|
||||
printf("Component: %s\n", component.c_str());
|
||||
printf("Stream Content: 0x%02hhx\n", streamContent);
|
||||
printf("Component type: 0x%02hhx\n", componentType);
|
||||
printf("Component tag: 0x%02hhx\n", componentTag);
|
||||
}
|
||||
int saveXML(FILE *file) const {
|
||||
fprintf(file, "\t\t\t<component tag=\"%02x\" type=\"%02x\" stream_content=\"%02x\" text=\"", componentTag, componentType, streamContent);
|
||||
saveStringToXMLfile(file,component.c_str());
|
||||
fprintf(file, "\"/>\n");
|
||||
// %s
|
||||
// return 1;
|
||||
// saveStringToXMLfile(file, component.c_str());
|
||||
// fprintf(file, "\"/>\n");
|
||||
return 0;
|
||||
}
|
||||
std::string component; // Text aus dem Component Descriptor
|
||||
unsigned char componentType; // Component Descriptor
|
||||
unsigned char componentTag; // Component Descriptor
|
||||
unsigned char streamContent; // Component Descriptor
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSIcomponent : public std::unary_function<class SIcomponent, void>
|
||||
{
|
||||
void operator() (const SIcomponent &c) { c.dump();}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct saveSIcomponentXML : public std::unary_function<class SIcomponent, void>
|
||||
{
|
||||
FILE *f;
|
||||
saveSIcomponentXML(FILE *fi) { f=fi;}
|
||||
void operator() (const SIcomponent &c) { c.saveXML(f);}
|
||||
};
|
||||
|
||||
typedef std::multiset <SIcomponent, std::less<SIcomponent> > SIcomponents;
|
||||
|
||||
class SIparentalRating {
|
||||
public:
|
||||
SIparentalRating(const std::string &cc, unsigned char rate) {
|
||||
rating=rate;
|
||||
countryCode=cc;
|
||||
}
|
||||
// Std-Copy
|
||||
SIparentalRating(const SIparentalRating &r) {
|
||||
rating=r.rating;
|
||||
countryCode=r.countryCode;
|
||||
}
|
||||
// Der Operator zum sortieren
|
||||
bool operator < (const SIparentalRating& c) const {
|
||||
return countryCode < c.countryCode;
|
||||
}
|
||||
void dump(void) const {
|
||||
printf("Rating: %s %hhu (+3)\n", countryCode.c_str(), rating);
|
||||
}
|
||||
int saveXML(FILE *file) const {
|
||||
if(fprintf(file, "\t\t\t<parental_rating country=\"%s\" rating=\"%hhu\"/>\n", countryCode.c_str(), rating)<0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
std::string countryCode;
|
||||
unsigned char rating; // Bei 1-16 -> Minumim Alter = rating +3
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSIparentalRating : public std::unary_function<SIparentalRating, void>
|
||||
{
|
||||
void operator() (const SIparentalRating &r) { r.dump();}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct saveSIparentalRatingXML : public std::unary_function<SIparentalRating, void>
|
||||
{
|
||||
FILE *f;
|
||||
saveSIparentalRatingXML(FILE *fi) { f=fi;}
|
||||
void operator() (const SIparentalRating &r) { r.saveXML(f);}
|
||||
};
|
||||
|
||||
typedef std::set <SIparentalRating, std::less<SIparentalRating> > SIparentalRatings;
|
||||
|
||||
class SItime {
|
||||
public:
|
||||
SItime(time_t s, unsigned d) {
|
||||
startzeit=s;
|
||||
dauer=d; // in Sekunden, 0 -> time shifted (cinedoms)
|
||||
}
|
||||
// Std-Copy
|
||||
SItime(const SItime &t) {
|
||||
startzeit=t.startzeit;
|
||||
dauer=t.dauer;
|
||||
}
|
||||
// Der Operator zum sortieren
|
||||
bool operator < (const SItime& t) const {
|
||||
return startzeit < t.startzeit;
|
||||
}
|
||||
void dump(void) const {
|
||||
printf("Startzeit: %s", ctime(&startzeit));
|
||||
printf("Dauer: %02u:%02u:%02u (%umin, %us)\n", dauer/3600, (dauer%3600)/60, dauer%60, dauer/60, dauer);
|
||||
}
|
||||
int saveXML(FILE *file) const { // saves the time
|
||||
// Ist so noch nicht in Ordnung, das sollte untergliedert werden,
|
||||
// da sonst evtl. time,date,duration,time,date,... auftritt
|
||||
// und eine rein sequentielle Ordnung finde ich nicht ok.
|
||||
/*
|
||||
struct tm *zeit=localtime(&startzeit);
|
||||
fprintf(file, "\t\t\t\t\t<time>%02d:%02d:%02d</time>\n", zeit->tm_hour, zeit->tm_min, zeit->tm_sec);
|
||||
fprintf(file, "\t\t\t\t\t<date>%02d.%02d.%04d</date>\n", zeit->tm_mday, zeit->tm_mon+1, zeit->tm_year+1900);
|
||||
fprintf(file, "\t\t\t\t\t<duration>%u</duration>\n", dauer);
|
||||
*/
|
||||
fprintf(file, "\t\t\t<time start_time=\"%u\" duration=\"%u\"/>\n", (unsigned int) startzeit, dauer);
|
||||
return 0;
|
||||
}
|
||||
time_t startzeit; // lokale Zeit, 0 -> time shifted (cinedoms)
|
||||
unsigned dauer; // in Sekunden, 0 -> time shifted (cinedoms)
|
||||
};
|
||||
|
||||
typedef std::set <SItime, std::less<SItime> > SItimes;
|
||||
|
||||
// Fuer for_each
|
||||
struct printSItime : public std::unary_function<SItime, void>
|
||||
{
|
||||
void operator() (const SItime &t) { t.dump();}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct saveSItimeXML : public std::unary_function<SItime, void>
|
||||
{
|
||||
FILE *f;
|
||||
saveSItimeXML(FILE *fi) { f=fi;}
|
||||
void operator() (const SItime &t) { t.saveXML(f);}
|
||||
};
|
||||
|
||||
class SIevent {
|
||||
public:
|
||||
t_service_id service_id;
|
||||
t_original_network_id original_network_id;
|
||||
t_transport_stream_id transport_stream_id;
|
||||
|
||||
SIevent(const struct eit_event *);
|
||||
// Std-Copy
|
||||
SIevent(const SIevent &);
|
||||
SIevent(const t_original_network_id, const t_transport_stream_id, const t_service_id, const unsigned short);
|
||||
SIevent(void) {
|
||||
service_id = 0;
|
||||
original_network_id = 0;
|
||||
transport_stream_id = 0;
|
||||
eventID = 0;
|
||||
vps = 0;
|
||||
table_id = 0xFF; /* 0xFF means "not set" */
|
||||
version = 0xFF;
|
||||
// dauer=0;
|
||||
// startzeit=0;
|
||||
}
|
||||
unsigned short eventID;
|
||||
// Name aus dem Short-Event-Descriptor
|
||||
std::string getName() const;
|
||||
void setName(const std::string &lang, const std::string &name);
|
||||
|
||||
// Text aus dem Short-Event-Descriptor
|
||||
std::string getText() const;
|
||||
void setText(const std::string &lang, const std::string &text);
|
||||
|
||||
std::string itemDescription; // Aus dem Extended Descriptor
|
||||
std::string item; // Aus dem Extended Descriptor
|
||||
|
||||
// Aus dem Extended Descriptor
|
||||
std::string getExtendedText() const;
|
||||
void appendExtendedText(const std::string &lang, const std::string &text);
|
||||
void setExtendedText(const std::string &lang, const std::string &text);
|
||||
|
||||
std::string contentClassification; // Aus dem Content Descriptor, als String, da mehrere vorkommen koennen
|
||||
std::string userClassification; // Aus dem Content Descriptor, als String, da mehrere vorkommen koennen
|
||||
// time_t startzeit; // lokale Zeit, 0 -> time shifted (cinedoms)
|
||||
// unsigned dauer; // in Sekunden, 0 -> time shifted (cinedoms)
|
||||
|
||||
t_channel_id get_channel_id(void) const {
|
||||
return CREATE_CHANNEL_ID;
|
||||
}
|
||||
|
||||
event_id_t uniqueKey(void) const {
|
||||
return CREATE_EVENT_ID(CREATE_CHANNEL_ID, eventID);
|
||||
}
|
||||
int runningStatus(void) const {
|
||||
return running;
|
||||
}
|
||||
SIcomponents components;
|
||||
SIparentalRatings ratings;
|
||||
SIlinkage_descs linkage_descs;
|
||||
SItimes times;
|
||||
time_t vps;
|
||||
unsigned char table_id;
|
||||
unsigned char version;
|
||||
// Der Operator zum sortieren
|
||||
bool operator < (const SIevent& e) const {
|
||||
return uniqueKey()<e.uniqueKey();
|
||||
}
|
||||
int saveXML(FILE *file) const { // saves the event
|
||||
return saveXML0(file) || saveXML2(file);
|
||||
}
|
||||
int saveXML(FILE *file, const char *serviceName) const; // saves the event
|
||||
void dump(void) const; // dumps the event to stdout
|
||||
void dumpSmall(void) const; // dumps the event to stdout (not all information)
|
||||
#ifndef DO_NOT_INCLUDE_STUFF_NOT_NEEDED_FOR_SECTIONSD
|
||||
// Liefert das aktuelle EPG des senders mit der uebergebenen serviceID,
|
||||
// bei Fehler ist die serviceID des zurueckgelieferten Events 0
|
||||
static SIevent readActualEvent(t_service_id serviceID, unsigned timeoutInSeconds=2);
|
||||
#endif
|
||||
char getFSK() const;
|
||||
protected:
|
||||
int saveXML0(FILE *f) const;
|
||||
int saveXML2(FILE *f) const;
|
||||
private:
|
||||
std::map<std::string, std::string> langName;
|
||||
std::map<std::string, std::string> langText;
|
||||
std::map<std::string, std::string> langExtendedText;
|
||||
int running;
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSIevent : public std::unary_function<SIevent, void>
|
||||
{
|
||||
void operator() (const SIevent &e) { e.dump();}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct saveSIeventXML : public std::unary_function<SIevent, void>
|
||||
{
|
||||
FILE *f;
|
||||
saveSIeventXML(FILE *fi) { f=fi;}
|
||||
void operator() (const SIevent &e) { e.saveXML(f);}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct saveSIeventXMLwithServiceName : public std::unary_function<SIevent, void>
|
||||
{
|
||||
FILE *f;
|
||||
const SIservices *s;
|
||||
saveSIeventXMLwithServiceName(FILE *fi, const SIservices &svs) {f=fi; s=&svs;}
|
||||
void operator() (const SIevent &e) {
|
||||
SIservices::iterator k=s->find(SIservice(e.service_id, e.original_network_id, e.transport_stream_id));
|
||||
if(k!=s->end()) {
|
||||
if(k->serviceName.length())
|
||||
e.saveXML(f, k->serviceName.c_str());
|
||||
}
|
||||
else
|
||||
e.saveXML(f);
|
||||
}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSIeventWithService : public std::unary_function<SIevent, void>
|
||||
{
|
||||
printSIeventWithService(const SIservices &svs) { s=&svs;}
|
||||
void operator() (const SIevent &e) {
|
||||
SIservices::iterator k=s->find(SIservice(e.service_id, e.original_network_id, e.transport_stream_id));
|
||||
if(k!=s->end()) {
|
||||
char servicename[50];
|
||||
strncpy(servicename, k->serviceName.c_str(), sizeof(servicename)-1);
|
||||
servicename[sizeof(servicename)-1]=0;
|
||||
removeControlCodes(servicename);
|
||||
printf("Service-Name: %s\n", servicename);
|
||||
// printf("Provider-Name: %s\n", k->providerName.c_str());
|
||||
}
|
||||
e.dump();
|
||||
// e.dumpSmall();
|
||||
printf("\n");
|
||||
}
|
||||
const SIservices *s;
|
||||
};
|
||||
|
||||
class SIevents : public std::set <SIevent, std::less<SIevent> >
|
||||
{
|
||||
public:
|
||||
// Entfernt anhand der Services alle time shifted events (Service-Typ 0)
|
||||
// und sortiert deren Zeiten in die Events mit dem Text ein.
|
||||
void mergeAndRemoveTimeShiftedEvents(const SIservices &);
|
||||
// Loescht alte Events (aufgrund aktueller Zeit - seconds und Zeit im Event)
|
||||
void removeOldEvents(long seconds);
|
||||
};
|
||||
|
||||
#endif // SIEVENTS_HPP
|
220
src/eitd/SIlanguage.cpp
Normal file
220
src/eitd/SIlanguage.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
//
|
||||
// $Id: SIlanguage.cpp,v 1.4 2006/04/21 20:40:13 houdini Exp $
|
||||
//
|
||||
// Class for filtering preferred language
|
||||
//
|
||||
// Copyright (C) 2001 arzka (dbox2@oh3mqu.pp.hyper.fi)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Log: SIlanguage.cpp,v $
|
||||
// Revision 1.4 2006/04/21 20:40:13 houdini
|
||||
// improvments when not using the MultiLanguageEPG feature
|
||||
//
|
||||
// Revision 1.3 2006/04/13 19:10:54 mws
|
||||
// bugfix returned wrong value for error while saving;
|
||||
// preincrement iterators;
|
||||
//
|
||||
// Revision 1.2 2006/04/12 21:23:58 Arzka
|
||||
// Optimization.
|
||||
// Removed unnecessary copying of std:map and
|
||||
// removed few avoidable std::string creation
|
||||
//
|
||||
// Revision 1.1 2006/03/26 20:13:49 Arzka
|
||||
// Added support for selecting EPG language
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#include "SIlanguage.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <pthread.h>
|
||||
#include <fstream>
|
||||
|
||||
#include <sectionsdclient/sectionsdclient.h>
|
||||
|
||||
#define LANGUAGEFILE "/var/tuxbox/config/epglanguages.conf"
|
||||
|
||||
std::vector<std::string> SIlanguage::languages;
|
||||
pthread_mutex_t SIlanguage::languages_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/*
|
||||
ALL = Show all available languages
|
||||
FIRST_FIRST = Show first found language from list. If not found show first of available language
|
||||
FIRST_ALL = Show first found language from list. If not found show all available languages.
|
||||
ALL_FIRST = Show all wanted languages if possible. If not found show first of av ailable language
|
||||
ALL_ALL = Show all wanted languages if possible. If not found show all available languages.
|
||||
*/
|
||||
//CSectionsdClient::SIlanguageMode_t SIlanguage::mode = CSectionsdClient::ALL;
|
||||
CSectionsdClient::SIlanguageMode_t SIlanguage::mode = CSectionsdClient::FIRST_ALL;
|
||||
|
||||
void SIlanguage::filter(const std::map<std::string, std::string>& s, int max, std::string& retval)
|
||||
{
|
||||
pthread_mutex_lock(&languages_lock);
|
||||
// languages cannot get iterated through
|
||||
// if another thread is updating it simultaneously
|
||||
int count = max;
|
||||
|
||||
if (mode != CSectionsdClient::ALL) {
|
||||
for (std::vector<std::string>::const_iterator it = languages.begin() ;
|
||||
it != languages.end() ; ++it) {
|
||||
std::map<std::string,std::string>::const_iterator text;
|
||||
if ((text = s.find(*it)) != s.end()) {
|
||||
if (count != max) {
|
||||
retval.append(" \n");
|
||||
}
|
||||
retval.append(text->second);
|
||||
if (--count == 0) break;
|
||||
if (mode == CSectionsdClient::FIRST_FIRST ||
|
||||
mode == CSectionsdClient::FIRST_ALL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (retval.length() == 0) {
|
||||
// return all available languages
|
||||
if (s.begin() != s.end()) {
|
||||
for (std::map<std::string, std::string>::const_iterator it = s.begin() ;
|
||||
it != s.end() ; ++it) {
|
||||
if (it != s.begin()) {
|
||||
retval.append(" \n");
|
||||
}
|
||||
retval.append(it->second);
|
||||
if (--max == 0) break;
|
||||
if (mode == CSectionsdClient::FIRST_FIRST ||
|
||||
mode == CSectionsdClient::ALL_FIRST) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&languages_lock);
|
||||
}
|
||||
|
||||
|
||||
bool SIlanguage::loadLanguages()
|
||||
{
|
||||
pthread_mutex_lock(&languages_lock);
|
||||
std::ifstream file(LANGUAGEFILE);
|
||||
std::string word;
|
||||
CSectionsdClient::SIlanguageMode_t tmpMode = CSectionsdClient::FIRST_ALL;
|
||||
std::vector<std::string> tmpLang;
|
||||
|
||||
if (!(file >> word)) goto error;
|
||||
if (word == "FIRST_FIRST") {
|
||||
tmpMode = CSectionsdClient::FIRST_FIRST;
|
||||
} else if (word == "FIRST_ALL") {
|
||||
tmpMode = CSectionsdClient::FIRST_ALL;
|
||||
} else if (word == "ALL_FIRST") {
|
||||
tmpMode = CSectionsdClient::ALL_FIRST;
|
||||
} else if (word == "ALL_ALL") {
|
||||
tmpMode = CSectionsdClient::ALL_ALL;
|
||||
} else if (word == "OFF") {
|
||||
tmpMode = CSectionsdClient::LANGUAGE_MODE_OFF;
|
||||
}
|
||||
|
||||
while (!file.eof()) {
|
||||
if ((file >> word)) {
|
||||
tmpLang.push_back(word);
|
||||
}
|
||||
}
|
||||
|
||||
if (tmpLang.empty()) tmpLang.push_back("OFF");
|
||||
languages = tmpLang;
|
||||
mode = tmpMode;
|
||||
pthread_mutex_unlock(&languages_lock);
|
||||
return true;
|
||||
|
||||
error:
|
||||
tmpLang.push_back("OFF");
|
||||
languages = tmpLang;
|
||||
mode = tmpMode;
|
||||
pthread_mutex_unlock(&languages_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SIlanguage::saveLanguages()
|
||||
{
|
||||
pthread_mutex_lock(&languages_lock);
|
||||
std::ofstream file(LANGUAGEFILE);
|
||||
switch(mode) {
|
||||
case CSectionsdClient::ALL:
|
||||
file << "ALL\n";
|
||||
break;
|
||||
case CSectionsdClient::FIRST_FIRST:
|
||||
file << "FIRST_FIRST\n";
|
||||
break;
|
||||
case CSectionsdClient::FIRST_ALL:
|
||||
file << "FIRST_ALL\n";
|
||||
break;
|
||||
case CSectionsdClient::ALL_FIRST:
|
||||
file << "ALL_FIRST\n";
|
||||
break;
|
||||
case CSectionsdClient::ALL_ALL:
|
||||
file << "ALL_ALL\n";
|
||||
break;
|
||||
case CSectionsdClient::LANGUAGE_MODE_OFF:
|
||||
file << "OFF\n";
|
||||
break;
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::iterator it = languages.begin() ;
|
||||
it != languages.end() ; ++it) {
|
||||
file << *it;
|
||||
file << "\n";
|
||||
if (file.fail()) goto error;
|
||||
}
|
||||
|
||||
file.close();
|
||||
if (file.fail()) goto error;
|
||||
|
||||
pthread_mutex_unlock(&languages_lock);
|
||||
return true;
|
||||
|
||||
error:
|
||||
pthread_mutex_unlock(&languages_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
void SIlanguage::setLanguages(const std::vector<std::string>& newLanguages)
|
||||
{
|
||||
pthread_mutex_lock(&languages_lock);
|
||||
languages = newLanguages;
|
||||
pthread_mutex_unlock(&languages_lock);
|
||||
}
|
||||
|
||||
std::vector<std::string> SIlanguage::getLanguages()
|
||||
{
|
||||
pthread_mutex_lock(&languages_lock);
|
||||
std::vector<std::string> retval(languages); // Store it before unlock
|
||||
pthread_mutex_unlock(&languages_lock);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void SIlanguage::setMode(CSectionsdClient::SIlanguageMode_t newMode)
|
||||
{
|
||||
mode = newMode;
|
||||
}
|
||||
|
||||
CSectionsdClient::SIlanguageMode_t SIlanguage::getMode()
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
62
src/eitd/SIlanguage.hpp
Normal file
62
src/eitd/SIlanguage.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef SILANGUAGES_HPP
|
||||
#define SILANGUAGES_HPP
|
||||
//
|
||||
// $Id: SIlanguage.hpp,v 1.2 2006/04/12 21:23:58 Arzka Exp $
|
||||
//
|
||||
// Class for filtering preferred language
|
||||
//
|
||||
// Copyright (C) 2001 arzka (dbox2@oh3mqu.pp.hyper.fi)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Log: SIlanguage.hpp,v $
|
||||
// Revision 1.2 2006/04/12 21:23:58 Arzka
|
||||
// Optimization.
|
||||
// Removed unnecessary copying of std:map and
|
||||
// removed few avoidable std::string creation
|
||||
//
|
||||
// Revision 1.1 2006/03/26 20:13:49 Arzka
|
||||
// Added support for selecting EPG language
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <sectionsdclient/sectionsdclient.h>
|
||||
|
||||
#define LANGUAGEFILE "/var/tuxbox/config/epglanguages.conf"
|
||||
|
||||
class SIlanguage {
|
||||
public:
|
||||
static void filter(const std::map<std::string, std::string>& s, int max, std::string& retval);
|
||||
static bool loadLanguages();
|
||||
static bool saveLanguages();
|
||||
static void setLanguages(const std::vector<std::string>& newLanguages);
|
||||
static std::vector<std::string> getLanguages();
|
||||
static void setMode(CSectionsdClient::SIlanguageMode_t newMode);
|
||||
static CSectionsdClient::SIlanguageMode_t getMode();
|
||||
|
||||
private:
|
||||
SIlanguage();
|
||||
~SIlanguage();
|
||||
static std::vector<std::string> languages;
|
||||
static pthread_mutex_t languages_lock;
|
||||
static CSectionsdClient::SIlanguageMode_t mode;
|
||||
};
|
||||
|
||||
#endif
|
183
src/eitd/SInetworks.hpp
Normal file
183
src/eitd/SInetworks.hpp
Normal file
@@ -0,0 +1,183 @@
|
||||
#ifndef SINETWORKS_HPP
|
||||
#define SINETWORKS_HPP
|
||||
//
|
||||
// $Id: SInetworks.hpp,v 1.3 2006/02/08 21:15:50 houdini Exp $
|
||||
//
|
||||
// classes SIservices and SIservices (dbox-II-project)
|
||||
//
|
||||
// Homepage: http://dbox2.elxsi.de
|
||||
//
|
||||
// Copyright (C) 2001 fnbrd (fnbrd@gmx.de),
|
||||
// 2002 thegoodguy (thegoodguy@berlios.de)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <endian.h>
|
||||
|
||||
#include <sectionsdclient/sectionsdMsg.h>
|
||||
|
||||
// forward references
|
||||
class SIservice;
|
||||
class SIevent;
|
||||
class SInetwork;
|
||||
/*
|
||||
struct loop_len {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved_future_use : 4;
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
#else
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
unsigned reserved_future_use : 4;
|
||||
#endif
|
||||
unsigned descriptors_loop_length_lo : 8;
|
||||
} __attribute__ ((packed)) ; // 2 Bytes
|
||||
*/
|
||||
struct nit_transponder {
|
||||
|
||||
unsigned transport_stream_id_hi : 8;
|
||||
unsigned transport_stream_id_lo : 8;
|
||||
unsigned original_network_id_hi : 8;
|
||||
unsigned original_network_id_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved_future_use : 4;
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
#else
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
unsigned reserved_future_use : 4;
|
||||
#endif
|
||||
unsigned descriptors_loop_length_lo : 8;
|
||||
|
||||
} __attribute__ ((packed)) ; // 6 Bytes
|
||||
|
||||
struct satellite_delivery_descriptor {
|
||||
unsigned frequency_1 : 8;
|
||||
unsigned frequency_2 : 8;
|
||||
unsigned frequency_3 : 8;
|
||||
unsigned frequency_4 : 8;
|
||||
unsigned orbital_pos_hi : 8;
|
||||
unsigned orbital_pos_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned west_east_flag : 1;
|
||||
unsigned polarization : 2;
|
||||
unsigned modulation : 5;
|
||||
#else
|
||||
unsigned modulation : 5;
|
||||
unsigned polarization : 2;
|
||||
unsigned west_east_flag : 1;
|
||||
#endif
|
||||
unsigned symbol_rate_1 : 8;
|
||||
unsigned symbol_rate_2 : 8;
|
||||
unsigned symbol_rate_3 : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned symbol_rate_4 : 4;
|
||||
unsigned fec_inner : 4;
|
||||
#else
|
||||
unsigned fec_inner : 4;
|
||||
unsigned symbol_rate_4 : 4;
|
||||
#endif
|
||||
} __attribute__ ((packed)) ; // 11 Bytes
|
||||
|
||||
struct cable_delivery_descriptor {
|
||||
unsigned frequency_1 : 8;
|
||||
unsigned frequency_2 : 8;
|
||||
unsigned frequency_3 : 8;
|
||||
unsigned frequency_4 : 8;
|
||||
unsigned reserved_hi : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved_lo : 4;
|
||||
unsigned fec_outer : 4;
|
||||
#else
|
||||
unsigned fec_outer : 4;
|
||||
unsigned reserved_lo : 4;
|
||||
#endif
|
||||
unsigned modulation : 8;
|
||||
unsigned symbol_rate_1 : 8;
|
||||
unsigned symbol_rate_2 : 8;
|
||||
unsigned symbol_rate_3 : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned symbol_rate_4 : 4;
|
||||
unsigned fec_inner : 4;
|
||||
#else
|
||||
unsigned fec_inner : 4;
|
||||
unsigned symbol_rate_4 : 4;
|
||||
#endif
|
||||
} __attribute__ ((packed)) ; // 11 Bytes
|
||||
|
||||
class SInetwork {
|
||||
public:
|
||||
SInetwork(const struct nit_transponder *s) {
|
||||
|
||||
network_id = 0;
|
||||
transport_stream_id = 0;
|
||||
original_network_id = 0;
|
||||
delivery_type = 0;
|
||||
is_actual = false;
|
||||
}
|
||||
|
||||
// Um einen service zum Suchen zu erstellen
|
||||
SInetwork(const t_network_id _network_id, const t_original_network_id _original_network_id, const t_transport_stream_id _transport_stream_id)
|
||||
{
|
||||
network_id = _network_id;
|
||||
original_network_id = _original_network_id;
|
||||
transport_stream_id = _transport_stream_id;
|
||||
}
|
||||
// Std-Copy
|
||||
SInetwork(const SInetwork &s) {
|
||||
|
||||
network_id = s.network_id;
|
||||
original_network_id = s.original_network_id;
|
||||
transport_stream_id = s.transport_stream_id;
|
||||
delivery_type = s.delivery_type;
|
||||
is_actual = s.is_actual;
|
||||
memmove(delivery_descriptor, s.delivery_descriptor, sizeof(struct satellite_delivery_descriptor));
|
||||
}
|
||||
|
||||
t_network_id network_id;
|
||||
t_original_network_id original_network_id;
|
||||
t_transport_stream_id transport_stream_id;
|
||||
unsigned short delivery_type;
|
||||
bool is_actual;
|
||||
char delivery_descriptor[sizeof(struct satellite_delivery_descriptor)];
|
||||
|
||||
bool operator < (const SInetwork& s) const {
|
||||
return uniqueKey() < s.uniqueKey();
|
||||
}
|
||||
|
||||
t_transponder_id uniqueKey(void) const {
|
||||
return CREATE_TRANSPONDER_ID_FROM_ORIGINALNETWORK_TRANSPORTSTREAM_ID(original_network_id, transport_stream_id);
|
||||
}
|
||||
|
||||
void dump(void) const {
|
||||
|
||||
printf("Original-Network-ID: %hu\n", original_network_id);
|
||||
printf("Transport-Stream-ID: %hu\n", transport_stream_id);
|
||||
}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSInetwork : public std::unary_function<SInetwork, void>
|
||||
{
|
||||
void operator() (const SInetwork &s) { s.dump();}
|
||||
};
|
||||
|
||||
// Als Klasse, da ich nicht weiss, wie man eine Forward-Referenz auf ein typedef macht
|
||||
class SInetworks : public std::set <SInetwork, std::less<SInetwork> >
|
||||
{
|
||||
};
|
||||
|
||||
#endif // SINETWORKS_HPP
|
1636
src/eitd/SIsections.cpp
Normal file
1636
src/eitd/SIsections.cpp
Normal file
File diff suppressed because it is too large
Load Diff
984
src/eitd/SIsections.hpp
Normal file
984
src/eitd/SIsections.hpp
Normal file
@@ -0,0 +1,984 @@
|
||||
#ifndef SISECTIONS_HPP
|
||||
#define SISECTIONS_HPP
|
||||
//
|
||||
// $Id: SIsections.hpp,v 1.28 2009/07/26 17:02:46 rhabarber1848 Exp $
|
||||
//
|
||||
// classes for SI sections (dbox-II-project)
|
||||
//
|
||||
// Homepage: http://dbox2.elxsi.de
|
||||
//
|
||||
// Copyright (C) 2001 fnbrd (fnbrd@gmx.de)
|
||||
// Copyright (C) 2003 Andreas Oberritter <obi@tuxbox.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
|
||||
#include <endian.h>
|
||||
#ifdef UPDATE_NETWORKS
|
||||
#include "SInetworks.hpp"
|
||||
#include "SIbouquets.hpp"
|
||||
#endif
|
||||
struct SI_section_SDT_header {
|
||||
unsigned table_id : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned section_syntax_indicator : 1;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned section_length_hi : 4;
|
||||
#else
|
||||
unsigned section_length_hi : 4;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned section_syntax_indicator : 1;
|
||||
#endif
|
||||
unsigned section_length_lo : 8;
|
||||
unsigned transport_stream_id_hi : 8;
|
||||
unsigned transport_stream_id_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved2 : 2;
|
||||
unsigned version_number : 5;
|
||||
unsigned current_next_indicator : 1;
|
||||
#else
|
||||
unsigned current_next_indicator : 1;
|
||||
unsigned version_number : 5;
|
||||
unsigned reserved2 : 2;
|
||||
#endif
|
||||
unsigned section_number : 8;
|
||||
unsigned last_section_number : 8;
|
||||
unsigned original_network_id_hi : 8;
|
||||
unsigned original_network_id_lo : 8;
|
||||
unsigned reserved_future_use2 : 8;
|
||||
} __attribute__ ((packed)) ; // 11 bytes
|
||||
|
||||
struct SI_section_NIT_header {
|
||||
unsigned table_id : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned section_syntax_indicator : 1;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned section_length_hi : 4;
|
||||
#else
|
||||
unsigned section_length_hi : 4;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned section_syntax_indicator : 1;
|
||||
#endif
|
||||
unsigned section_length_lo : 8;
|
||||
unsigned network_id_hi : 8;
|
||||
unsigned network_id_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved2 : 2;
|
||||
unsigned version_number : 5;
|
||||
unsigned current_next_indicator : 1;
|
||||
#else
|
||||
unsigned current_next_indicator : 1;
|
||||
unsigned version_number : 5;
|
||||
unsigned reserved2 : 2;
|
||||
#endif
|
||||
unsigned section_number : 8;
|
||||
unsigned last_section_number : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved_future_use2 : 4;
|
||||
unsigned network_descriptors_length_hi : 4;
|
||||
#else
|
||||
unsigned network_descriptors_length_hi : 4;
|
||||
unsigned reserved_future_use2 : 4;
|
||||
#endif
|
||||
unsigned network_descriptors_length_lo : 8;
|
||||
} __attribute__ ((packed)) ; // 10 bytes
|
||||
|
||||
struct SI_section_BAT_header {
|
||||
unsigned table_id : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned section_syntax_indicator : 1;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned section_length_hi : 4;
|
||||
#else
|
||||
unsigned section_length_hi : 4;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned section_syntax_indicator : 1;
|
||||
#endif
|
||||
unsigned section_length_lo : 8;
|
||||
unsigned bouquet_id_hi : 8;
|
||||
unsigned bouquet_id_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved2 : 2;
|
||||
unsigned version_number : 5;
|
||||
unsigned current_next_indicator : 1;
|
||||
#else
|
||||
unsigned current_next_indicator : 1;
|
||||
unsigned version_number : 5;
|
||||
unsigned reserved2 : 2;
|
||||
#endif
|
||||
unsigned section_number : 8;
|
||||
unsigned last_section_number : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved_future_use2 : 4;
|
||||
unsigned bouquet_descriptors_length_hi : 4;
|
||||
#else
|
||||
unsigned bouquet_descriptors_length_hi : 4;
|
||||
unsigned reserved_future_use2 : 4;
|
||||
#endif
|
||||
unsigned bouquet_descriptors_length_lo : 8;
|
||||
} __attribute__ ((packed)) ; // 10 bytes
|
||||
|
||||
struct SI_section_EIT_header {
|
||||
unsigned table_id : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned section_syntax_indicator : 1;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned section_length_hi : 4;
|
||||
#else
|
||||
unsigned section_length_hi : 4;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned section_syntax_indicator : 1;
|
||||
#endif
|
||||
unsigned section_length_lo : 8;
|
||||
unsigned service_id_hi : 8;
|
||||
unsigned service_id_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved2 : 2;
|
||||
unsigned version_number : 5;
|
||||
unsigned current_next_indicator : 1;
|
||||
#else
|
||||
unsigned current_next_indicator : 1;
|
||||
unsigned version_number : 5;
|
||||
unsigned reserved2 : 2;
|
||||
#endif
|
||||
unsigned section_number : 8;
|
||||
unsigned last_section_number : 8;
|
||||
unsigned transport_stream_id_hi : 8;
|
||||
unsigned transport_stream_id_lo : 8;
|
||||
unsigned original_network_id_hi : 8;
|
||||
unsigned original_network_id_lo : 8;
|
||||
unsigned segment_last_section_number : 8;
|
||||
unsigned last_table_id : 8;
|
||||
} __attribute__ ((packed)) ; // 14 bytes
|
||||
|
||||
// Muss evtl. angepasst werden falls damit RST, TDT und TOT gelesen werden sollen
|
||||
// ^^^
|
||||
// RST usw. haben section_syntax_indicator == 0, andere == 1 (obi)
|
||||
struct SI_section_header {
|
||||
unsigned table_id : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned section_syntax_indicator : 1;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned section_length_hi : 4;
|
||||
#else
|
||||
unsigned section_length_hi : 4;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned section_syntax_indicator : 1;
|
||||
#endif
|
||||
unsigned section_length_lo : 8;
|
||||
unsigned table_id_extension_hi : 8;
|
||||
unsigned table_id_extension_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved2 : 2;
|
||||
unsigned version_number : 5;
|
||||
unsigned current_next_indicator : 1;
|
||||
#else
|
||||
unsigned current_next_indicator : 1;
|
||||
unsigned version_number : 5;
|
||||
unsigned reserved2 : 2;
|
||||
#endif
|
||||
unsigned section_number : 8;
|
||||
unsigned last_section_number : 8;
|
||||
} __attribute__ ((packed)) ; // 8 bytes
|
||||
|
||||
#ifdef ENABLE_PPT
|
||||
struct SI_section_PPT_header { // Premiere Private Table
|
||||
unsigned table_id : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned section_syntax_indicator : 1;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned section_length_hi : 4;
|
||||
#else
|
||||
unsigned section_length_hi : 4;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned section_syntax_indicator : 1;
|
||||
#endif
|
||||
unsigned section_length_lo : 8;
|
||||
unsigned table_id_extension_hi : 8;
|
||||
unsigned table_id_extension_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved2 : 2;
|
||||
unsigned version_number : 5;
|
||||
unsigned current_next_indicator : 1;
|
||||
#else
|
||||
unsigned current_next_indicator : 1;
|
||||
unsigned version_number : 5;
|
||||
unsigned reserved2 : 2;
|
||||
#endif
|
||||
unsigned section_number : 8;
|
||||
unsigned last_section_number : 8;
|
||||
|
||||
unsigned content_id_32_25 : 8;
|
||||
unsigned content_id_24_17 : 8;
|
||||
unsigned content_id_16_9 : 8;
|
||||
unsigned content_id_8_0 : 8;
|
||||
unsigned duration_hi : 8;
|
||||
unsigned duration_mid : 8;
|
||||
unsigned duration_lo : 8;
|
||||
unsigned reserved3 : 4;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned descriptor_section_length_hi : 4;
|
||||
unsigned descriptor_section_length_lo : 8;
|
||||
#else
|
||||
unsigned descriptor_section_length_lo : 8;
|
||||
unsigned descriptor_section_length_hi : 4;
|
||||
#endif
|
||||
} __attribute__ ((packed)) ; // 8 bytes
|
||||
#endif
|
||||
|
||||
class SIsection
|
||||
{
|
||||
public:
|
||||
SIsection(void) { buffer = 0; bufferLength = 0;}
|
||||
|
||||
#if 0
|
||||
// Kopierte den Puffer in eigenen Puffer
|
||||
SIsection(const char *buf, unsigned bufLength) {
|
||||
buffer = 0; bufferLength = 0;
|
||||
if ((buf) && (bufLength >= sizeof(struct SI_section_header))) {
|
||||
buffer = new char[bufLength];
|
||||
if (buffer) {
|
||||
bufferLength = bufLength;
|
||||
memmove(buffer, buf, bufLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Benutzt den uebergebenen Puffer (sollte mit new char[n] allokiert sein)
|
||||
SIsection(unsigned bufLength, char *buf) {
|
||||
buffer = 0; bufferLength = 0;
|
||||
if ((buf) && (bufLength >= sizeof(struct SI_section_header))) {
|
||||
buffer = buf;
|
||||
bufferLength = bufLength;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Konstruktor um eine (leere) SIsection mit den fuer Vergleiche
|
||||
// noetigen Inhalte (s. key) zu erstellen
|
||||
SIsection(const struct SI_section_header *header) {
|
||||
bufferLength = 0;
|
||||
buffer = new char[sizeof(struct SI_section_header)];
|
||||
if (buffer) {
|
||||
memmove(buffer, header, sizeof(struct SI_section_header));
|
||||
bufferLength = sizeof(struct SI_section_header);
|
||||
}
|
||||
}
|
||||
|
||||
// Std-Copy
|
||||
SIsection(const SIsection &s) {
|
||||
buffer = 0; bufferLength = 0;
|
||||
if (s.buffer) {
|
||||
buffer = new char[s.bufferLength];
|
||||
if (buffer) {
|
||||
bufferLength = s.bufferLength;
|
||||
memmove(buffer, s.buffer, bufferLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Destruktor
|
||||
virtual ~SIsection(void) {
|
||||
bufferLength = 0;
|
||||
}
|
||||
|
||||
unsigned char tableID(void) const {
|
||||
return buffer ? ((struct SI_section_header *)buffer)->table_id : (unsigned char) -1;
|
||||
}
|
||||
|
||||
unsigned short tableIDextension(void) const {
|
||||
return buffer ? ((((struct SI_section_header *)buffer)->table_id_extension_hi << 8) |
|
||||
((struct SI_section_header *)buffer)->table_id_extension_lo) : (unsigned short) -1;
|
||||
}
|
||||
|
||||
unsigned char sectionNumber(void) const {
|
||||
return buffer ? ((struct SI_section_header *)buffer)->section_number : (unsigned char) -1;
|
||||
}
|
||||
|
||||
unsigned char versionNumber(void) const {
|
||||
return buffer ? ((struct SI_section_header *)buffer)->version_number : (unsigned char) -1;
|
||||
}
|
||||
|
||||
unsigned char currentNextIndicator(void) const {
|
||||
return buffer ? ((struct SI_section_header *)buffer)->current_next_indicator : (unsigned char) -1;
|
||||
}
|
||||
|
||||
unsigned char lastSectionNumber(void) const {
|
||||
return buffer ? ((struct SI_section_header *)buffer)->last_section_number : (unsigned char) -1;
|
||||
}
|
||||
|
||||
struct SI_section_header const *header(void) const {
|
||||
return (struct SI_section_header *)buffer;
|
||||
}
|
||||
|
||||
static uint64_t key(const struct SI_section_header *header) {
|
||||
// Der eindeutige Key einer SIsection besteht aus 1 Byte Table-ID,
|
||||
// 2 Byte Table-ID-extension, 1 Byte Section number
|
||||
// 1 Byte Version number und 1 Byte current_next_indicator
|
||||
if (!header)
|
||||
return (uint64_t) -1;
|
||||
return (((uint64_t)header->table_id) << 40) +
|
||||
(((uint64_t)header->table_id_extension_hi) << 32) +
|
||||
(((uint64_t)header->table_id_extension_lo) << 24) +
|
||||
(((uint64_t)header->section_number) << 16) +
|
||||
(((uint64_t)header->version_number) << 8) +
|
||||
(((uint64_t)header->current_next_indicator));
|
||||
}
|
||||
|
||||
uint64_t key(void) const {
|
||||
return buffer ? key(header()) : (uint64_t) -1;
|
||||
}
|
||||
|
||||
// Der Operator zum sortieren
|
||||
bool operator < (const SIsection& s) const {
|
||||
return key() < s.key();
|
||||
}
|
||||
|
||||
static void dumpSmallSectionHeader(const struct SI_section_header *header) {
|
||||
if (!header)
|
||||
return;
|
||||
printf("\ntable_id: 0x%02x ", header->table_id);
|
||||
printf("table_id_extension: 0x%02x%02x", header->table_id_extension_hi, header->table_id_extension_lo);
|
||||
printf("section_number: 0x%02x\n", header->section_number);
|
||||
}
|
||||
|
||||
static void dumpSmallSectionHeader(const SIsection &s) {
|
||||
dumpSmallSectionHeader((struct SI_section_header *)s.buffer);
|
||||
}
|
||||
|
||||
void dumpSmallSectionHeader(void) const {
|
||||
dumpSmallSectionHeader((struct SI_section_header *)buffer);
|
||||
}
|
||||
|
||||
int saveBufferToFile(FILE *file) const {
|
||||
if (!file)
|
||||
return 1;
|
||||
return (fwrite(buffer, bufferLength, 1, file) != 1);
|
||||
}
|
||||
|
||||
int saveBufferToFile(const char *filename) const {
|
||||
if (!filename)
|
||||
return 2;
|
||||
|
||||
FILE *file = fopen(filename, "wb");
|
||||
|
||||
if (file) {
|
||||
int rc = saveBufferToFile(file);
|
||||
fclose(file);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void dump1(const struct SI_section_header *header) {
|
||||
if (!header)
|
||||
return;
|
||||
printf("\ntable_id: 0x%02x\n", header->table_id);
|
||||
printf("section_syntax_indicator: 0x%02x\n", header->section_syntax_indicator);
|
||||
printf("section_length: %hu\n", (header->section_length_hi << 8) | header->section_length_lo);
|
||||
}
|
||||
|
||||
static void dump2(const struct SI_section_header *header) {
|
||||
if (!header)
|
||||
return;
|
||||
printf("version_number: 0x%02x\n", header->version_number);
|
||||
printf("current_next_indicator: 0x%02x\n", header->current_next_indicator);
|
||||
printf("section_number: 0x%02x\n", header->section_number);
|
||||
printf("last_section_number: 0x%02x\n", header->last_section_number);
|
||||
}
|
||||
|
||||
static void dump(const struct SI_section_header *header) {
|
||||
if (!header)
|
||||
return;
|
||||
dump1(header);
|
||||
printf("table_id_extension: 0x%02x%02x\n", header->table_id_extension_hi, header->table_id_extension_lo);
|
||||
dump2(header);
|
||||
}
|
||||
|
||||
static void dump(const SIsection &s) {
|
||||
dump((struct SI_section_header *)s.buffer);
|
||||
}
|
||||
|
||||
void dump(void) const {
|
||||
dump((struct SI_section_header *)buffer);
|
||||
}
|
||||
|
||||
protected:
|
||||
char *buffer;
|
||||
unsigned bufferLength;
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSIsection : public std::unary_function<SIsection, void>
|
||||
{
|
||||
void operator() (const SIsection &s) { s.dump();}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSmallSIsectionHeader : public std::unary_function<SIsection, void>
|
||||
{
|
||||
void operator() (const SIsection &s) { s.dumpSmallSectionHeader();}
|
||||
};
|
||||
|
||||
class SIsections : public std::set <SIsection, std::less<SIsection> >
|
||||
{
|
||||
public:
|
||||
// Liefert 0 falls kein Fehler
|
||||
// Algo:
|
||||
// (1) Segment lesen (wird zum ersten Segment deklariert)
|
||||
// (2) Falls Segmentnummer = letze Segmentnummer = 0 dann fertig, sonst
|
||||
// (3) alle Segment lesen bis erstes wieder kommt
|
||||
// (4) fehlende Segmente (s. last_section_number) versuchen zu lesen
|
||||
// Der Timeout gilt fuer jeden der 3 Abschnitte, d.h. maximal dauert
|
||||
// es 3 x timeout.
|
||||
// Mit readNext=0 werden nur aktuelle Sections gelesen (current_next_indicator = 1)
|
||||
int readSections(unsigned short pid, unsigned char filter, unsigned char mask, int readNext=0, unsigned timeoutInSeconds=10);
|
||||
};
|
||||
|
||||
class SIsectionEIT : public SIsection
|
||||
{
|
||||
public:
|
||||
SIsectionEIT(const SIsection &s) : SIsection(s) {
|
||||
parsed = 0;
|
||||
parse();
|
||||
}
|
||||
|
||||
// Std-Copy
|
||||
SIsectionEIT(const SIsectionEIT &s) : SIsection(s) {
|
||||
evts = s.evts;
|
||||
parsed = s.parsed;
|
||||
}
|
||||
|
||||
// Benutzt den uebergebenen Puffer (sollte mit new char[n] allokiert sein)
|
||||
SIsectionEIT(unsigned bufLength, char *buf) : SIsection(bufLength, buf) {
|
||||
parsed = 0;
|
||||
parse();
|
||||
}
|
||||
|
||||
t_service_id service_id(void) const {
|
||||
return buffer ? ((((struct SI_section_EIT_header *)buffer)->service_id_hi << 8) |
|
||||
((struct SI_section_EIT_header *)buffer)->service_id_lo): 0;
|
||||
}
|
||||
|
||||
t_original_network_id original_network_id(void) const {
|
||||
return buffer ? ((((struct SI_section_EIT_header *)buffer)->original_network_id_hi << 8) |
|
||||
((struct SI_section_EIT_header *)buffer)->original_network_id_lo) : 0;
|
||||
}
|
||||
|
||||
t_transport_stream_id transport_stream_id(void) const {
|
||||
return buffer ? ((((struct SI_section_EIT_header *)buffer)->transport_stream_id_hi << 8) |
|
||||
((struct SI_section_EIT_header *)buffer)->transport_stream_id_lo) : 0;
|
||||
}
|
||||
|
||||
struct SI_section_EIT_header const *header(void) const {
|
||||
return (struct SI_section_EIT_header *)buffer;
|
||||
}
|
||||
|
||||
static void dump(const struct SI_section_EIT_header *header) {
|
||||
if (!header)
|
||||
return;
|
||||
SIsection::dump1((const struct SI_section_header *)header);
|
||||
printf("service_id: 0x%02x%02x\n", header->service_id_hi, header->service_id_lo);
|
||||
SIsection::dump2((const struct SI_section_header *)header);
|
||||
printf("transport_stream_id 0x%02x%02x\n", header->transport_stream_id_hi, header->transport_stream_id_lo);
|
||||
printf("original_network_id 0x%02x%02x\n", header->original_network_id_hi, header->original_network_id_lo);
|
||||
printf("segment_last_section_number: 0x%02x\n", header->segment_last_section_number);
|
||||
printf("last_table_id 0x%02x\n", header->last_table_id);
|
||||
}
|
||||
|
||||
static void dump(const SIsectionEIT &s) {
|
||||
dump((struct SI_section_EIT_header *)s.buffer);
|
||||
for_each(s.evts.begin(), s.evts.end(), printSIevent());
|
||||
}
|
||||
|
||||
void dump(void) const {
|
||||
dump((struct SI_section_EIT_header *)buffer);
|
||||
for_each(evts.begin(), evts.end(), printSIevent());
|
||||
}
|
||||
|
||||
const SIevents &events(void) const {
|
||||
//if(!parsed)
|
||||
// parse(); -> nicht const
|
||||
return evts;
|
||||
}
|
||||
|
||||
int is_parsed(void) const {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
protected:
|
||||
SIevents evts;
|
||||
int parsed;
|
||||
void parse(void);
|
||||
void parseDescriptors(const char *desc, unsigned len, SIevent &e);
|
||||
void parseShortEventDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parseExtendedEventDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parseContentDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parseComponentDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parseParentalRatingDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parseLinkageDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parsePDCDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
#ifdef ENABLE_FREESATEPG
|
||||
std::string freesatHuffmanDecode(std::string input);
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef ENABLE_PPT
|
||||
class SIsectionPPT : public SIsection
|
||||
{
|
||||
public:
|
||||
SIsectionPPT(const SIsection &s) : SIsection(s) {
|
||||
parsed = 0;
|
||||
parse();
|
||||
}
|
||||
|
||||
// Std-Copy
|
||||
SIsectionPPT(const SIsectionPPT &s) : SIsection(s) {
|
||||
evts = s.evts;
|
||||
parsed = s.parsed;
|
||||
}
|
||||
|
||||
// Benutzt den uebergebenen Puffer (sollte mit new char[n] allokiert sein)
|
||||
SIsectionPPT(unsigned bufLength, char *buf) : SIsection(bufLength, buf) {
|
||||
parsed = 0;
|
||||
parse();
|
||||
}
|
||||
|
||||
long content_id(void) const {
|
||||
return buffer ? ((((struct SI_section_PPT_header *)buffer)->content_id_32_25<< 24) |
|
||||
(((struct SI_section_PPT_header *)buffer)->content_id_24_17<< 16) |
|
||||
(((struct SI_section_PPT_header *)buffer)->content_id_16_9<< 8) |
|
||||
((struct SI_section_PPT_header *)buffer)->content_id_8_0): 0;
|
||||
}
|
||||
|
||||
long duration(void) const {
|
||||
|
||||
if (!buffer) return(0);
|
||||
|
||||
if (!((((struct SI_section_PPT_header *)buffer)->duration_hi == 0xff) &&
|
||||
(((struct SI_section_PPT_header *)buffer)->duration_mid == 0xff) &&
|
||||
(((struct SI_section_PPT_header *)buffer)->duration_lo == 0xff)))
|
||||
return ((((struct SI_section_PPT_header *)buffer)->duration_hi)>>4)*10*3600L + ((((struct SI_section_PPT_header *)buffer)->duration_hi)&0x0f)*3600L +
|
||||
((((struct SI_section_PPT_header *)buffer)->duration_mid)>>4)*10*60L + ((((struct SI_section_PPT_header *)buffer)->duration_mid)&0x0f)*60L +
|
||||
((((struct SI_section_PPT_header *)buffer)->duration_lo)>>4)*10 + ((((struct SI_section_PPT_header *)buffer)->duration_lo)&0x0f);
|
||||
return(0);
|
||||
}
|
||||
|
||||
short int descriptor_section_length(void) const {
|
||||
return buffer ? ((((struct SI_section_PPT_header *)buffer)->descriptor_section_length_hi << 8) |
|
||||
((struct SI_section_PPT_header *)buffer)->descriptor_section_length_lo) : 0;
|
||||
}
|
||||
|
||||
struct SI_section_PPT_header const *header(void) const {
|
||||
return (struct SI_section_PPT_header *)buffer;
|
||||
}
|
||||
|
||||
static void dump(const struct SI_section_PPT_header *header) {
|
||||
if (!header)
|
||||
return;
|
||||
SIsection::dump1((const struct SI_section_header *)header);
|
||||
printf("table_id_extension: 0x%02x%02x\n", header->table_id_extension_hi, header->table_id_extension_lo);
|
||||
SIsection::dump1((const struct SI_section_header *)header);
|
||||
printf("content id 0x%02x%02x%02x%02x\n", header->content_id_32_25, header->content_id_24_17, header->content_id_16_9, header->content_id_8_0);
|
||||
printf("duration 0x%02x%02x%02x\n", header->duration_hi, header->duration_mid, header->duration_lo);
|
||||
printf("reserved3 0x%02x\n", header->reserved3);
|
||||
printf("descriptor section length 0x%02x%02x\n", header->descriptor_section_length_hi, header->descriptor_section_length_lo);
|
||||
}
|
||||
|
||||
static void dump(const SIsectionPPT &s) {
|
||||
dump((struct SI_section_PPT_header *)s.buffer);
|
||||
for_each(s.evts.begin(), s.evts.end(), printSIevent());
|
||||
}
|
||||
|
||||
void dump(void) const {
|
||||
dump((struct SI_section_PPT_header *)buffer);
|
||||
for_each(evts.begin(), evts.end(), printSIevent());
|
||||
}
|
||||
|
||||
const SIevents &events(void) const {
|
||||
//if(!parsed)
|
||||
// parse(); -> nicht const
|
||||
return evts;
|
||||
}
|
||||
|
||||
int is_parsed(void) const {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
protected:
|
||||
SIevents evts;
|
||||
int parsed;
|
||||
void parse(void);
|
||||
void parseDescriptors(const char *desc, unsigned len, SIevent &e);
|
||||
void parseShortEventDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parseExtendedEventDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parseContentDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parseComponentDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parseParentalRatingDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parseLinkageDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
|
||||
void parsePrivateContentOrderDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parsePrivateParentalInformationDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
void parsePrivateContentTransmissionDescriptor(const char *buf, SIevent &e, unsigned maxlen);
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef DO_NOT_INCLUDE_STUFF_NOT_NEEDED_FOR_SECTIONSD
|
||||
// Fuer for_each
|
||||
struct printSIsectionEIT : public std::unary_function<SIsectionEIT, void>
|
||||
{
|
||||
void operator() (const SIsectionEIT &s) { s.dump();}
|
||||
};
|
||||
|
||||
#ifdef ENABLE_PPT
|
||||
// Fuer for_each
|
||||
struct printSIsectionPPT : public std::unary_function<SIsectionPPT, void>
|
||||
{
|
||||
void operator() (const SIsectionPPT &s) { s.dump();}
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
// Fuer for_each
|
||||
struct parseSIsectionEIT : public std::unary_function<SIsectionEIT, void>
|
||||
{
|
||||
void operator() (const SIsectionEIT &s) { s.parse();}
|
||||
};
|
||||
*/
|
||||
|
||||
// Menge aller present/following EITs (actual TS)
|
||||
class SIsectionsEIT : public std::set <SIsectionEIT, std::less<SIsectionEIT> >
|
||||
{
|
||||
public:
|
||||
int readSections(void) {
|
||||
SIsections sections;
|
||||
int rc=sections.readSections(0x12, 0x4e, 0xff);
|
||||
|
||||
for (SIsections::iterator k=sections.begin(); k!=sections.end(); k++)
|
||||
insert(*k);
|
||||
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef ENABLE_PPT
|
||||
// Menge aller present/following PPTs (actual TS)
|
||||
class SIsectionsPPT : public std::set <SIsectionPPT, std::less<SIsectionPPT> >
|
||||
{
|
||||
public:
|
||||
int readSections(int pid) {
|
||||
// int readSections(void) {
|
||||
SIsections sections;
|
||||
int rc=sections.readSections(pid, 0xa1, 0xfe);
|
||||
|
||||
for (SIsections::iterator k=sections.begin(); k!=sections.end(); k++)
|
||||
insert(*k);
|
||||
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// Menge aller schedule EITs (actual TS)
|
||||
class SIsectionsEITschedule : public std::set <SIsectionEIT, std::less<SIsectionEIT> >
|
||||
{
|
||||
public:
|
||||
int readSections(void) {
|
||||
SIsections sections;
|
||||
int rc=sections.readSections(0x12, 0x50, 0xf0);
|
||||
|
||||
for (SIsections::iterator k=sections.begin(); k!=sections.end(); k++)
|
||||
insert(*k);
|
||||
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class SIsectionSDT : public SIsection
|
||||
{
|
||||
public:
|
||||
SIsectionSDT(const SIsection &s) : SIsection(s) {
|
||||
parsed = 0;
|
||||
parse();
|
||||
}
|
||||
|
||||
// Std-Copy
|
||||
SIsectionSDT(const SIsectionSDT &s) : SIsection(s) {
|
||||
svs = s.svs;
|
||||
parsed = s.parsed;
|
||||
}
|
||||
|
||||
// Benutzt den uebergebenen Puffer (sollte mit new char[n] allokiert sein)
|
||||
SIsectionSDT(unsigned bufLength, char *buf) : SIsection(bufLength, buf) {
|
||||
parsed = 0;
|
||||
parse();
|
||||
}
|
||||
|
||||
t_transport_stream_id transport_stream_id(void) const {
|
||||
return buffer ? ((((struct SI_section_SDT_header *)buffer)->transport_stream_id_hi << 8) |
|
||||
((struct SI_section_SDT_header *)buffer)->transport_stream_id_lo) : 0;
|
||||
}
|
||||
|
||||
struct SI_section_SDT_header const *header(void) const {
|
||||
return (struct SI_section_SDT_header *)buffer;
|
||||
}
|
||||
|
||||
t_original_network_id original_network_id(void) const {
|
||||
return buffer ? ((((struct SI_section_SDT_header *)buffer)->original_network_id_hi << 8) |
|
||||
((struct SI_section_SDT_header *)buffer)->original_network_id_lo) : 0;
|
||||
}
|
||||
|
||||
static void dump(const struct SI_section_SDT_header *header) {
|
||||
if (!header)
|
||||
return;
|
||||
SIsection::dump1((const struct SI_section_header *)header);
|
||||
printf("transport_stream_id: 0x%02x%02x\n", header->transport_stream_id_hi, header->transport_stream_id_lo);
|
||||
SIsection::dump2((const struct SI_section_header *)header);
|
||||
printf("original_network_id: 0x%02x%02x\n", header->original_network_id_hi, header->original_network_id_lo);
|
||||
}
|
||||
|
||||
static void dump(const SIsectionSDT &s) {
|
||||
dump((struct SI_section_SDT_header *)s.buffer);
|
||||
for_each(s.svs.begin(), s.svs.end(), printSIservice());
|
||||
}
|
||||
|
||||
void dump(void) const {
|
||||
dump((struct SI_section_SDT_header *)buffer);
|
||||
for_each(svs.begin(), svs.end(), printSIservice());
|
||||
}
|
||||
|
||||
const SIservices &services(void) const {
|
||||
//if(!parsed)
|
||||
// parse(); -> nicht const
|
||||
return svs;
|
||||
}
|
||||
|
||||
private:
|
||||
SIservices svs;
|
||||
int parsed;
|
||||
void parse(void);
|
||||
void parseDescriptors(const char *desc, unsigned len, SIservice &s);
|
||||
void parseServiceDescriptor(const char *buf, SIservice &s);
|
||||
void parsePrivateDataDescriptor(const char *buf, SIservice &s);
|
||||
void parseNVODreferenceDescriptor(const char *buf, SIservice &s);
|
||||
};
|
||||
|
||||
#ifdef UPDATE_NETWORKS
|
||||
class SIsectionBAT : public SIsection
|
||||
{
|
||||
public:
|
||||
SIsectionBAT(const SIsection &s) : SIsection(s) {
|
||||
parsed = 0;
|
||||
parse();
|
||||
}
|
||||
|
||||
// Std-Copy
|
||||
SIsectionBAT(const SIsectionBAT &s) : SIsection(s) {
|
||||
bsv = s.bsv;
|
||||
parsed = s.parsed;
|
||||
}
|
||||
|
||||
// Benutzt den uebergebenen Puffer (sollte mit new char[n] allokiert sein)
|
||||
SIsectionBAT(unsigned bufLength, char *buf) : SIsection(bufLength, buf) {
|
||||
parsed = 0;
|
||||
parse();
|
||||
}
|
||||
|
||||
unsigned short bouquetID(void) const {
|
||||
return buffer ? ((((struct SI_section_BAT_header *)buffer)->bouquet_id_hi << 8) |
|
||||
((struct SI_section_BAT_header *)buffer)->bouquet_id_lo) : (unsigned short) -1;
|
||||
}
|
||||
|
||||
struct SI_section_BAT_header const *header(void) const {
|
||||
return (struct SI_section_BAT_header *)buffer;
|
||||
}
|
||||
|
||||
static void dump(const struct SI_section_BAT_header *header) {
|
||||
if (!header)
|
||||
return;
|
||||
SIsection::dump1((const struct SI_section_header *)header);
|
||||
printf("bouquet_id: 0x%02x%02x\n", header->bouquet_id_hi, header->bouquet_id_lo);
|
||||
SIsection::dump2((const struct SI_section_header *)header);
|
||||
printf("bouquet_descriptors_length %hu\n",
|
||||
(header->bouquet_descriptors_length_hi << 8) | header->bouquet_descriptors_length_lo);
|
||||
}
|
||||
|
||||
static void dump(const SIsectionBAT &s) {
|
||||
dump((struct SI_section_BAT_header *)s.buffer);
|
||||
}
|
||||
|
||||
void dump(void) const {
|
||||
dump((struct SI_section_BAT_header *)buffer);
|
||||
}
|
||||
|
||||
const SIbouquets &bouquets(void) const {
|
||||
//if(!parsed)
|
||||
// parse(); -> nicht const
|
||||
return bsv;
|
||||
}
|
||||
|
||||
protected:
|
||||
SIbouquets bsv;
|
||||
int parsed;
|
||||
void parse(void);
|
||||
// int parseDescriptors(const char *desc, unsigned len, SIbouquet &s, int section_no, int count, const char *bouquetName);
|
||||
// void parseBouquetNameDescriptor(const char *buf, SIbouquet &s);
|
||||
// int parseServiceListDescriptor(const char *buf, SIbouquet &s, int section_no, int count);
|
||||
};
|
||||
|
||||
class SIsectionNIT : public SIsection
|
||||
{
|
||||
public:
|
||||
SIsectionNIT(const SIsection &s) : SIsection(s) {
|
||||
parsed = 0;
|
||||
parse();
|
||||
}
|
||||
|
||||
// Std-Copy
|
||||
SIsectionNIT(const SIsectionNIT &s) : SIsection(s) {
|
||||
ntw = s.ntw;
|
||||
parsed = s.parsed;
|
||||
}
|
||||
|
||||
// Benutzt den uebergebenen Puffer (sollte mit new char[n] allokiert sein)
|
||||
SIsectionNIT(unsigned bufLength, char *buf) : SIsection(bufLength, buf) {
|
||||
parsed = 0;
|
||||
parse();
|
||||
}
|
||||
|
||||
unsigned short networkID(void) const {
|
||||
return buffer ? ((((struct SI_section_NIT_header *)buffer)->network_id_hi << 8) |
|
||||
((struct SI_section_NIT_header *)buffer)->network_id_lo) : (unsigned short) -1;
|
||||
}
|
||||
|
||||
struct SI_section_NIT_header const *header(void) const {
|
||||
return (struct SI_section_NIT_header *)buffer;
|
||||
}
|
||||
|
||||
static void dump(const struct SI_section_NIT_header *header) {
|
||||
if (!header)
|
||||
return;
|
||||
SIsection::dump1((const struct SI_section_header *)header);
|
||||
printf("network_id: 0x%02x%02x\n", header->network_id_hi, header->network_id_lo);
|
||||
SIsection::dump2((const struct SI_section_header *)header);
|
||||
printf("network_descriptors_length %hu\n",
|
||||
(header->network_descriptors_length_hi << 8) | header->network_descriptors_length_lo);
|
||||
}
|
||||
|
||||
static void dump(const SIsectionNIT &s) {
|
||||
dump((struct SI_section_NIT_header *)s.buffer);
|
||||
}
|
||||
|
||||
void dump(void) const {
|
||||
dump((struct SI_section_NIT_header *)buffer);
|
||||
}
|
||||
|
||||
const SInetworks &networks(void) const {
|
||||
//if(!parsed)
|
||||
// parse(); -> nicht const
|
||||
return ntw;
|
||||
}
|
||||
|
||||
protected:
|
||||
SInetworks ntw;
|
||||
int parsed;
|
||||
void parse(void);
|
||||
void parseDescriptors(const char *desc, unsigned len, SInetwork &s);
|
||||
void copyDeliveryDescriptor(const char *buf, SInetwork &s);
|
||||
};
|
||||
#endif
|
||||
#ifndef DO_NOT_INCLUDE_STUFF_NOT_NEEDED_FOR_SECTIONSD
|
||||
// Fuer for_each
|
||||
struct printSIsectionSDT : public std::unary_function<SIsectionSDT, void>
|
||||
{
|
||||
void operator() (const SIsectionSDT &s) { s.dump();}
|
||||
};
|
||||
|
||||
// Menge aller SDTs (actual TS)
|
||||
class SIsectionsSDT : public std::set <SIsectionSDT, std::less<SIsectionSDT> >
|
||||
{
|
||||
public:
|
||||
int readSections(void) {
|
||||
SIsections sections;
|
||||
int rc=sections.readSections(0x11, 0x42, 0xff);
|
||||
|
||||
for (SIsections::iterator k=sections.begin(); k!=sections.end(); k++)
|
||||
insert(*k);
|
||||
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSIsectionBAT : public std::unary_function<SIsectionBAT, void>
|
||||
{
|
||||
void operator() (const SIsectionBAT &s) { s.dump();}
|
||||
};
|
||||
|
||||
// Menge aller BATs
|
||||
class SIsectionsBAT : public std::set <SIsectionBAT, std::less<SIsectionBAT> >
|
||||
{
|
||||
public:
|
||||
int readSections(void) {
|
||||
SIsections sections;
|
||||
int rc=sections.readSections(0x11, 0x4a, 0xff);
|
||||
|
||||
for (SIsections::iterator k=sections.begin(); k!=sections.end(); k++)
|
||||
insert(*k);
|
||||
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSIsectionNIT : public std::unary_function<SIsectionNIT, void>
|
||||
{
|
||||
void operator() (const SIsectionNIT &s) { s.dump();}
|
||||
};
|
||||
|
||||
// Menge aller NITs (actual network)
|
||||
class SIsectionsNIT : public std::set <SIsectionNIT, std::less<SIsectionNIT> >
|
||||
{
|
||||
public:
|
||||
int readSections(void) {
|
||||
SIsections sections;
|
||||
int rc=sections.readSections(0x10, 0x40, 0xff);
|
||||
|
||||
for (SIsections::iterator k=sections.begin(); k!=sections.end(); k++)
|
||||
insert(*k);
|
||||
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // SISECTIONS_HPP
|
208
src/eitd/SIservices.hpp
Normal file
208
src/eitd/SIservices.hpp
Normal file
@@ -0,0 +1,208 @@
|
||||
#ifndef SISERVICES_HPP
|
||||
#define SISERVICES_HPP
|
||||
//
|
||||
// $Id: SIservices.hpp,v 1.15 2009/02/24 19:09:10 seife Exp $
|
||||
//
|
||||
// classes SIservices and SIservices (dbox-II-project)
|
||||
//
|
||||
// Homepage: http://dbox2.elxsi.de
|
||||
//
|
||||
// Copyright (C) 2001 fnbrd (fnbrd@gmx.de),
|
||||
// 2002 thegoodguy (thegoodguy@berlios.de)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring> // memset
|
||||
#include <endian.h>
|
||||
|
||||
#include <sectionsdclient/sectionsdMsg.h>
|
||||
|
||||
|
||||
// forward references
|
||||
class SIservice;
|
||||
class SIevent;
|
||||
|
||||
struct sdt_service {
|
||||
unsigned service_id_hi : 8;
|
||||
unsigned service_id_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved_future_use : 6;
|
||||
unsigned EIT_schedule_flag : 1;
|
||||
unsigned EIT_present_following_flag : 1;
|
||||
unsigned running_status : 3;
|
||||
unsigned free_CA_mode : 1;
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
#else
|
||||
unsigned EIT_present_following_flag : 1;
|
||||
unsigned EIT_schedule_flag : 1;
|
||||
unsigned reserved_future_use : 6;
|
||||
unsigned descriptors_loop_length_hi : 4;
|
||||
unsigned free_CA_mode : 1;
|
||||
unsigned running_status : 3;
|
||||
#endif
|
||||
unsigned descriptors_loop_length_lo : 8;
|
||||
} __attribute__ ((packed)) ; // 5 Bytes
|
||||
|
||||
|
||||
class SInvodReference
|
||||
{
|
||||
public:
|
||||
t_service_id service_id;
|
||||
t_original_network_id original_network_id;
|
||||
t_transport_stream_id transport_stream_id;
|
||||
|
||||
SInvodReference(const t_transport_stream_id new_transport_stream_id, const t_original_network_id new_original_network_id, const t_service_id new_service_id)
|
||||
{
|
||||
service_id = new_service_id;
|
||||
original_network_id = new_original_network_id;
|
||||
transport_stream_id = new_transport_stream_id;
|
||||
}
|
||||
|
||||
SInvodReference(const SInvodReference &ref)
|
||||
{
|
||||
service_id = ref.service_id;
|
||||
original_network_id = ref.original_network_id;
|
||||
transport_stream_id = ref.transport_stream_id;
|
||||
}
|
||||
|
||||
bool operator < (const SInvodReference& ref) const
|
||||
{
|
||||
return uniqueKey() < ref.uniqueKey();
|
||||
}
|
||||
|
||||
void dump(void) const
|
||||
{
|
||||
printf("NVOD Ref. Service-ID: %hu\n", service_id);
|
||||
printf("NVOD Ref. Original-Network-ID: %hu\n", original_network_id);
|
||||
printf("NVOD Ref. Transport-Stream-ID: %hu\n", transport_stream_id);
|
||||
}
|
||||
|
||||
void toStream(char * &p) const
|
||||
{
|
||||
*(t_service_id *)p = service_id; p += sizeof(t_service_id);
|
||||
*(t_original_network_id *)p = original_network_id; p += sizeof(t_original_network_id);
|
||||
*(t_transport_stream_id *)p = transport_stream_id; p += sizeof(t_transport_stream_id);
|
||||
}
|
||||
|
||||
t_service_id getServiceID() const
|
||||
{
|
||||
return service_id;
|
||||
}
|
||||
|
||||
t_channel_id uniqueKey(void) const {
|
||||
return CREATE_CHANNEL_ID; // cf. zapittypes.h
|
||||
}
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSInvodReference : public std::unary_function<class SInvodReference, void>
|
||||
{
|
||||
void operator() (const SInvodReference &ref) { ref.dump();}
|
||||
};
|
||||
|
||||
typedef std::set <SInvodReference, std::less<SInvodReference> > SInvodReferences;
|
||||
|
||||
class SIservice {
|
||||
public:
|
||||
SIservice(const struct sdt_service *s) {
|
||||
service_id = (s->service_id_hi << 8) | s->service_id_lo;
|
||||
original_network_id = 0;
|
||||
transport_stream_id = 0;
|
||||
serviceTyp = 0;
|
||||
flags.EIT_schedule_flag = s->EIT_schedule_flag;
|
||||
flags.EIT_present_following_flag = s->EIT_present_following_flag;
|
||||
flags.running_status = s->running_status;
|
||||
flags.free_CA_mode = s->free_CA_mode;
|
||||
is_actual = false;
|
||||
}
|
||||
// Um einen service zum Suchen zu erstellen
|
||||
SIservice(const t_service_id _service_id, const t_original_network_id _original_network_id, const t_transport_stream_id _transport_stream_id)
|
||||
{
|
||||
service_id = _service_id;
|
||||
original_network_id = _original_network_id;
|
||||
transport_stream_id = _transport_stream_id;
|
||||
serviceTyp=0;
|
||||
memset(&flags, 0, sizeof(flags));
|
||||
}
|
||||
// Std-Copy
|
||||
SIservice(const SIservice &s) {
|
||||
service_id = s.service_id;
|
||||
original_network_id = s.original_network_id;
|
||||
transport_stream_id = s.transport_stream_id;
|
||||
serviceTyp=s.serviceTyp;
|
||||
providerName=s.providerName;
|
||||
serviceName=s.serviceName;
|
||||
flags=s.flags;
|
||||
nvods=s.nvods;
|
||||
is_actual=s.is_actual;
|
||||
}
|
||||
t_service_id service_id;
|
||||
t_original_network_id original_network_id; // Ist innerhalb einer section unnoetig
|
||||
t_transport_stream_id transport_stream_id;
|
||||
unsigned char serviceTyp;
|
||||
int is_actual;
|
||||
SInvodReferences nvods;
|
||||
std::string serviceName; // Name aus dem Service-Descriptor
|
||||
std::string providerName; // Name aus dem Service-Descriptor
|
||||
int eitScheduleFlag(void) {return (int)flags.EIT_schedule_flag;}
|
||||
int eitPresentFollowingFlag(void) {return (int)flags.EIT_present_following_flag;}
|
||||
int runningStatus(void) {return (int)flags.running_status;}
|
||||
int freeCAmode(void) {return (int)flags.free_CA_mode;}
|
||||
|
||||
bool operator < (const SIservice& s) const {
|
||||
return uniqueKey() < s.uniqueKey();
|
||||
}
|
||||
|
||||
t_channel_id uniqueKey(void) const {
|
||||
//return CREATE_CHANNEL_ID;
|
||||
//notice that tsid & onid were changed for compatibility sake - order should be onid tsid when being sorted
|
||||
return CREATE_CHANNEL_ID_FROM_SERVICE_ORIGINALNETWORK_TRANSPORTSTREAM_ID(service_id, transport_stream_id, original_network_id);
|
||||
}
|
||||
|
||||
void dump(void) const {
|
||||
printf("Original-Network-ID: %hu\n", original_network_id);
|
||||
printf("Service-ID: %hu\n", service_id);
|
||||
printf("Service-Typ: %hhu\n", serviceTyp);
|
||||
if(providerName.length())
|
||||
printf("Provider-Name: %s\n", providerName.c_str());
|
||||
if(serviceName.length())
|
||||
printf("Service-Name: %s\n", serviceName.c_str());
|
||||
for_each(nvods.begin(), nvods.end(), printSInvodReference());
|
||||
printf("\n");
|
||||
}
|
||||
protected:
|
||||
struct {
|
||||
unsigned char EIT_schedule_flag : 1;
|
||||
unsigned char EIT_present_following_flag : 1;
|
||||
unsigned char running_status : 3;
|
||||
unsigned char free_CA_mode : 1;
|
||||
} flags;
|
||||
};
|
||||
|
||||
// Fuer for_each
|
||||
struct printSIservice : public std::unary_function<SIservice, void>
|
||||
{
|
||||
void operator() (const SIservice &s) { s.dump();}
|
||||
};
|
||||
|
||||
// Als Klasse, da ich nicht weiss, wie man eine Forward-Referenz auf ein typedef macht
|
||||
class SIservices : public std::set <SIservice, std::less<SIservice> >
|
||||
{
|
||||
};
|
||||
|
||||
#endif // SISERVICES_HPP
|
300
src/eitd/SIutils.cpp
Normal file
300
src/eitd/SIutils.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
//
|
||||
// $Id: SIutils.cpp,v 1.15 2005/11/03 21:08:52 mogway Exp $
|
||||
//
|
||||
// utility functions for the SI-classes (dbox-II-project)
|
||||
//
|
||||
// Homepage: http://dbox2.elxsi.de
|
||||
//
|
||||
// Copyright (C) 2001 fnbrd (fnbrd@gmx.de)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Log: SIutils.cpp,v $
|
||||
// Revision 1.15 2005/11/03 21:08:52 mogway
|
||||
// sectionsd update by Houdini
|
||||
//
|
||||
// Changes:
|
||||
// - EIT und SDT DMX buffer verändert
|
||||
// -> keine(weniger) POLLER, kostet Speicher beim EITDMX, spart Speicher beim SDTDMX
|
||||
//
|
||||
// - vor dem Parsen der Sections werden die Buffer nicht mehr (unnötig) ein zweites mal allokiert und umkopiert -> mehr Performance, weniger Speicherfragmentierung
|
||||
//
|
||||
// - unnötige/unbenutze Funktionen auskommentiert -> das gestrippte sectionsd binary wird 23kB kleiner, Test-/Beispielprogramme wie sdt, epg, nit, ... können dann nicht mehr kompiliert werden.
|
||||
//
|
||||
// Revision 1.14 2003/03/03 13:38:33 obi
|
||||
// - cleaned up changeUTCtoCtime a bit
|
||||
// - finish pthreads using pthread_exit(NULL) instead of return 0
|
||||
// - use settimeofday() instead of stime()
|
||||
//
|
||||
// Revision 1.13 2002/11/03 22:26:54 thegoodguy
|
||||
// Use more frequently types defined in zapittypes.h(not complete), fix some warnings, some code cleanup
|
||||
//
|
||||
// Revision 1.12 2001/07/17 14:15:52 fnbrd
|
||||
// Kleine Aenderung damit auch static geht.
|
||||
//
|
||||
// Revision 1.11 2001/07/14 16:38:46 fnbrd
|
||||
// Mit workaround fuer defektes mktime der glibc
|
||||
//
|
||||
// Revision 1.10 2001/07/12 22:55:51 fnbrd
|
||||
// Fehler behoben
|
||||
//
|
||||
// Revision 1.9 2001/07/12 22:51:25 fnbrd
|
||||
// Time-Thread im sectionsd (noch disabled, da prob mit mktime)
|
||||
//
|
||||
// Revision 1.8 2001/07/06 11:09:56 fnbrd
|
||||
// Noch ne Kleinigkeit gefixt.
|
||||
//
|
||||
// Revision 1.7 2001/07/06 09:46:01 fnbrd
|
||||
// Kleiner Fehler behoben
|
||||
//
|
||||
// Revision 1.6 2001/07/06 09:27:40 fnbrd
|
||||
// Kleine Anpassung
|
||||
//
|
||||
// Revision 1.5 2001/06/10 14:55:51 fnbrd
|
||||
// Kleiner Aenderungen und Ergaenzungen (epgMini).
|
||||
//
|
||||
// Revision 1.4 2001/05/19 22:46:50 fnbrd
|
||||
// Jetzt wellformed xml.
|
||||
//
|
||||
// Revision 1.3 2001/05/18 13:11:46 fnbrd
|
||||
// Fast komplett, fehlt nur noch die Auswertung der time-shifted events
|
||||
// (Startzeit und Dauer der Cinedoms).
|
||||
//
|
||||
// Revision 1.2 2001/05/17 01:53:35 fnbrd
|
||||
// Jetzt mit lokaler Zeit.
|
||||
//
|
||||
// Revision 1.1 2001/05/16 15:23:47 fnbrd
|
||||
// Alles neu macht der Mai.
|
||||
//
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
// Houdini: not used in the code at the moment, found in SIsections.cpp
|
||||
#if 0
|
||||
static const char descr_tbl[][50] = {
|
||||
// defined by ISO/IEC 13818-1 P64
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Video Stream",
|
||||
"Audio Stream",
|
||||
"Hierarchy",
|
||||
"Registration",
|
||||
"Data Stream Alignment",
|
||||
"Target Background Grid",
|
||||
"Video Window",
|
||||
"CA",
|
||||
"ISO 639 Language",
|
||||
"System Clock",
|
||||
"Multiplex Buffer Utilization",
|
||||
"Copyright",
|
||||
"Maximum Bitrate",
|
||||
"Private Data Indicator",
|
||||
"Smoothing Buffer",
|
||||
"STD",
|
||||
"IBP",
|
||||
"ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved",
|
||||
// defined by ETSI
|
||||
"Network Name",
|
||||
"Service List",
|
||||
"Stuffing",
|
||||
"Satellite Delivery System",
|
||||
"Cable Delivery System",
|
||||
"Reserved for future use",
|
||||
"Reserved for future use",
|
||||
"Bouquet Name",
|
||||
"Service",
|
||||
"Country Availability",
|
||||
"Linkage",
|
||||
"NVOD Reference",
|
||||
"Time Shifted Service",
|
||||
"Short Event",
|
||||
"Extended Event",
|
||||
"Time Shifted Event",
|
||||
"Component",
|
||||
"Mosaic",
|
||||
"Stream Identifier",
|
||||
"CA Identifier",
|
||||
"Content",
|
||||
"Parental Rating",
|
||||
"Teletext",
|
||||
"Telephone",
|
||||
"Local Time Offset",
|
||||
"Subtitling",
|
||||
"Terrestrial Delivery System",
|
||||
"Multilingual Network Name",
|
||||
"Multilingual Bouquet Name",
|
||||
"Multilingual Service Name",
|
||||
"Multilingual Component",
|
||||
"Private Data Specifier",
|
||||
"Service Move",
|
||||
"Short Smoothing Buffer",
|
||||
"Reserved for future use",
|
||||
"User defined",
|
||||
"FORBIDDEN"
|
||||
};
|
||||
|
||||
// Thanks to tmbinc
|
||||
const char *decode_descr (unsigned char _index) {
|
||||
int index = _index;
|
||||
|
||||
if (_index>=0x13 && _index<=0x3F)
|
||||
index = 0x13;
|
||||
|
||||
if (_index>=0x40)
|
||||
index -= (0x3F - 0x13);
|
||||
|
||||
if (_index>=0x62 && _index<=0x7F)
|
||||
index = 0x62 - (_index - index);
|
||||
|
||||
if (_index>=0x80)
|
||||
index -= (0x7F - 0x62);
|
||||
|
||||
if (_index>=0x80 && _index<=0xFE)
|
||||
index = 0x80 - (_index - index);
|
||||
|
||||
if (_index == 0xFF)
|
||||
index = 0xFF - (_index - index) - (0xFE - 0x80);
|
||||
|
||||
return descr_tbl[index];
|
||||
}
|
||||
#endif
|
||||
|
||||
// Thanks to kwon
|
||||
time_t changeUTCtoCtime(const unsigned char *buffer, int local_time)
|
||||
{
|
||||
int year, month, day, y_, m_, k, hour, minutes, seconds, mjd;
|
||||
|
||||
if (!memcmp(buffer, "\xff\xff\xff\xff\xff", 5))
|
||||
return 0; // keine Uhrzeit
|
||||
|
||||
mjd = (buffer[0] << 8) | buffer[1];
|
||||
hour = buffer[2];
|
||||
minutes = buffer[3];
|
||||
seconds = buffer[4];
|
||||
|
||||
y_ = (int) ((mjd - 15078.2) / 365.25);
|
||||
m_ = (int) ((mjd - 14956.1 - (int) (y_ * 365.25)) / 30.6001);
|
||||
day = mjd - 14956 - (int) (y_ * 365.25) - (int) (m_ * 30.60001);
|
||||
|
||||
k = !!((m_ == 14) || (m_ == 15));
|
||||
|
||||
year = y_ + k + 1900;
|
||||
month = m_ - 1 - k * 12;
|
||||
|
||||
struct tm time;
|
||||
memset(&time, 0, sizeof(struct tm));
|
||||
|
||||
time.tm_mday = day;
|
||||
time.tm_mon = month - 1;
|
||||
time.tm_year = year - 1900;
|
||||
time.tm_hour = (hour >> 4) * 10 + (hour & 0x0f);
|
||||
time.tm_min = (minutes >> 4) * 10 + (minutes & 0x0f);
|
||||
time.tm_sec = (seconds >> 4) * 10 + (seconds & 0x0f);
|
||||
|
||||
#if 0
|
||||
printf ("Startzeit: GMT: %.2d.%.2d.%.4d %.2x:%.2x:%.2x\n",
|
||||
day, month, year, hour, minutes, seconds);
|
||||
printf ("Startzeit: GMT: %.2d.%.2d.%.4d %.2d:%.2d:%.2d\n",
|
||||
time.tm_mday, time.tm_mon + 1, time.tm_year + 1900,
|
||||
time.tm_hour, time.tm_min, time.tm_sec);
|
||||
#endif
|
||||
|
||||
return mktime(&time) + (local_time ? -timezone : 0);
|
||||
}
|
||||
|
||||
// Thanks to tmbinc
|
||||
int saveStringToXMLfile(FILE *out, const char *c, int /*withControlCodes*/)
|
||||
{
|
||||
if(!c)
|
||||
return 1;
|
||||
// Die Umlaute sind ISO-8859-9 [5]
|
||||
/*
|
||||
char buf[6000];
|
||||
int inlen=strlen(c);
|
||||
int outlen=sizeof(buf);
|
||||
// UTF8Toisolat1((unsigned char *)buf, &outlen, (const unsigned char *)c, &inlen);
|
||||
isolat1ToUTF8((unsigned char *)buf, &outlen, (const unsigned char *)c, &inlen);
|
||||
buf[outlen]=0;
|
||||
c=buf;
|
||||
*/
|
||||
for(; *c; c++) {
|
||||
switch ((unsigned char)*c) {
|
||||
case '<':
|
||||
fprintf(out, "<");
|
||||
break;
|
||||
case '>':
|
||||
fprintf(out, ">");
|
||||
break;
|
||||
case '&':
|
||||
fprintf(out, "&");
|
||||
break;
|
||||
case '\"':
|
||||
fprintf(out, """);
|
||||
break;
|
||||
case '\'':
|
||||
fprintf(out, "'");
|
||||
break;
|
||||
#if 0
|
||||
case 0x81:
|
||||
case 0x82:
|
||||
break;
|
||||
case 0x86:
|
||||
if(withControlCodes)
|
||||
fprintf(out, "<b>");
|
||||
break;
|
||||
case 0x87:
|
||||
if(withControlCodes)
|
||||
fprintf(out, "</b>");
|
||||
break;
|
||||
case 0x8a:
|
||||
if(withControlCodes)
|
||||
fprintf(out, "<br/>");
|
||||
break;
|
||||
default:
|
||||
if (*c<32)
|
||||
break;
|
||||
if ((*c>=32) && (((unsigned char)*c)<128))
|
||||
fprintf(out, "%c", *c);
|
||||
else
|
||||
fprintf(out, "&#%d;", *c);
|
||||
#else
|
||||
default:
|
||||
if ((unsigned char)*c<32)
|
||||
break;
|
||||
fprintf(out, "%c", *c);
|
||||
#endif
|
||||
} // case
|
||||
|
||||
} // for
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Entfernt die ControlCodes aus dem String (-> String wird evtl. kuerzer)
|
||||
void removeControlCodes(char *string)
|
||||
{
|
||||
if(!string)
|
||||
return;
|
||||
for(; *string; )
|
||||
if (!((*string>=32) && (((unsigned char)*string)<128)))
|
||||
memmove(string, string+1, strlen(string+1)+1);
|
||||
else
|
||||
string++;
|
||||
return ;
|
||||
}
|
||||
|
57
src/eitd/SIutils.hpp
Normal file
57
src/eitd/SIutils.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef SIUTILS_HPP
|
||||
#define SIUTILS_HPP
|
||||
//
|
||||
// $Id: SIutils.hpp,v 1.5 2006/05/19 21:28:08 houdini Exp $
|
||||
//
|
||||
// utility functions for the SI-classes (dbox-II-project)
|
||||
//
|
||||
// Homepage: http://dbox2.elxsi.de
|
||||
//
|
||||
// Copyright (C) 2001 fnbrd (fnbrd@gmx.de)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Log: SIutils.hpp,v $
|
||||
// Revision 1.5 2006/05/19 21:28:08 houdini
|
||||
// - Nirvanas save/restore EPG patch #g
|
||||
// - automatic update of subchannels for Premiere (disable with <sectionsd -nu>)
|
||||
// - Fix for ZDF audio option "mono/H<>rfilm"
|
||||
// - improved navigation speed in bouquet/channel list
|
||||
// - zapit/pzapit new option (-sbo) save bouquets.xml including Bouquet "Andere" which saves me a lot of time :-)
|
||||
//
|
||||
// Revision 1.4 2001/07/14 16:38:46 fnbrd
|
||||
// Mit workaround fuer defektes mktime der glibc
|
||||
//
|
||||
// Revision 1.3 2001/06/10 14:55:51 fnbrd
|
||||
// Kleiner Aenderungen und Ergaenzungen (epgMini).
|
||||
//
|
||||
// Revision 1.2 2001/05/19 22:46:50 fnbrd
|
||||
// Jetzt wellformed xml.
|
||||
//
|
||||
// Revision 1.1 2001/05/16 15:23:47 fnbrd
|
||||
// Alles neu macht der Mai.
|
||||
//
|
||||
//
|
||||
time_t changeUTCtoCtime(const unsigned char *buffer, int local_time=1);
|
||||
|
||||
// returns the descriptor type as readable text
|
||||
const char *decode_descr (unsigned char tag_value);
|
||||
|
||||
int saveStringToXMLfile(FILE *out, const char *string, int withControlCodes=0);
|
||||
|
||||
// Entfernt die ControlCodes aus dem String (-> String wird evtl. kuerzer)
|
||||
void removeControlCodes(char *string);
|
||||
|
||||
#endif // SIUTILS_HPP
|
35
src/eitd/debug.cpp
Normal file
35
src/eitd/debug.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Header: /cvs/tuxbox/apps/tuxbox/neutrino/daemons/sectionsd/debug.cpp,v 1.3 2008/06/15 10:19:38 seife Exp $
|
||||
*
|
||||
* Debug tools (sectionsd) - d-box2 linux project
|
||||
*
|
||||
* (C) 2003 by thegoodguy <thegoodguy@berlios.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
bool sections_debug;
|
||||
|
||||
void printdate_ms(FILE *f) {
|
||||
timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
struct tm *tm = localtime(&now.tv_sec);
|
||||
/* use strftime for that? */
|
||||
fprintf(f, "%02d:%02d:%02d.%03ld ", tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec/1000);
|
||||
}
|
862
src/eitd/dmx.cpp
Normal file
862
src/eitd/dmx.cpp
Normal file
@@ -0,0 +1,862 @@
|
||||
/*
|
||||
* $Header: /cvs/tuxbox/apps/tuxbox/neutrino/daemons/sectionsd/dmx.cpp,v 1.51 2009/06/14 21:46:03 rhabarber1848 Exp $
|
||||
*
|
||||
* DMX class (sectionsd) - d-box2 linux project
|
||||
*
|
||||
* (C) 2001 by fnbrd,
|
||||
* 2003 by thegoodguy <thegoodguy@berlios.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <dmx.h>
|
||||
#include <dmxapi.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
|
||||
#include <driver/abstime.h>
|
||||
|
||||
/*
|
||||
#define DEBUG_MUTEX 1
|
||||
#define DEBUG_CACHED_SECTIONS 1
|
||||
*/
|
||||
|
||||
typedef std::map<sections_id_t, version_number_t, std::less<sections_id_t> > MyDMXOrderUniqueKey;
|
||||
static MyDMXOrderUniqueKey myDMXOrderUniqueKey;
|
||||
|
||||
extern void showProfiling(std::string text);
|
||||
|
||||
DMX::DMX(const unsigned short p, const unsigned short bufferSizeInKB, const bool c, int dmx_source)
|
||||
{
|
||||
dmx_num = dmx_source;
|
||||
fd = -1;
|
||||
lastChanged = time_monotonic();
|
||||
filter_index = 0;
|
||||
pID = p;
|
||||
dmxBufferSizeInKB = bufferSizeInKB;
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
/* hack, to keep the TD changes in one place. */
|
||||
dmxBufferSizeInKB = 128; /* 128kB is enough on TD */
|
||||
dmx_num = 0; /* always use demux 0 */
|
||||
#endif
|
||||
pthread_mutex_init(&pauselock, NULL); // default = fast mutex
|
||||
#ifdef DEBUG_MUTEX
|
||||
pthread_mutexattr_t start_stop_mutex_attr;
|
||||
pthread_mutexattr_init(&start_stop_mutex_attr);
|
||||
pthread_mutexattr_settype(&start_stop_mutex_attr, PTHREAD_MUTEX_ERRORCHECK_NP);
|
||||
pthread_mutex_init(&start_stop_mutex, &start_stop_mutex_attr);
|
||||
#else
|
||||
pthread_mutex_init(&start_stop_mutex, NULL); // default = fast mutex
|
||||
#endif
|
||||
pthread_cond_init (&change_cond, NULL);
|
||||
real_pauseCounter = 0;
|
||||
current_service = 0;
|
||||
|
||||
first_skipped = 0;
|
||||
cache = c;
|
||||
}
|
||||
|
||||
DMX::~DMX()
|
||||
{
|
||||
first_skipped = 0;
|
||||
myDMXOrderUniqueKey.clear();
|
||||
pthread_mutex_destroy(&pauselock);
|
||||
pthread_mutex_destroy(&start_stop_mutex);
|
||||
pthread_cond_destroy (&change_cond);
|
||||
closefd();
|
||||
}
|
||||
|
||||
ssize_t DMX::read(char * const /*buf*/, const size_t /*buflength*/, const unsigned /*timeoutMInSeconds*/)
|
||||
{
|
||||
//FIXME is this used ??
|
||||
printf("[sectionsd] ******************************* DMX::read called *******************************\n");
|
||||
return 0;
|
||||
//return readNbytes(fd, buf, buflength, timeoutMInSeconds);
|
||||
}
|
||||
|
||||
void DMX::close(void)
|
||||
{
|
||||
if(dmx)
|
||||
delete dmx;
|
||||
dmx = NULL;
|
||||
}
|
||||
|
||||
void DMX::closefd(void)
|
||||
{
|
||||
if (isOpen())
|
||||
{
|
||||
//close(fd);
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
dmx->Close();
|
||||
#else
|
||||
dmx->Stop();
|
||||
#endif
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void DMX::addfilter(const unsigned char filter, const unsigned char mask)
|
||||
{
|
||||
s_filters tmp;
|
||||
tmp.filter = filter;
|
||||
tmp.mask = mask;
|
||||
filters.push_back(tmp);
|
||||
}
|
||||
|
||||
int DMX::immediate_stop(void)
|
||||
{
|
||||
if (!isOpen())
|
||||
return 1;
|
||||
|
||||
closefd();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DMX::stop(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
lock();
|
||||
|
||||
rc = immediate_stop();
|
||||
|
||||
unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void DMX::lock(void)
|
||||
{
|
||||
//dprintf("DMX::lock, thread %lu\n", pthread_self());
|
||||
#ifdef DEBUG_MUTEX
|
||||
int rc = pthread_mutex_lock(&start_stop_mutex);
|
||||
if (rc != 0)
|
||||
{
|
||||
fprintf(stderr, "[sectionsd] mutex_lock: %d %d %d\n", rc, EINVAL, EDEADLK);
|
||||
fflush(stderr);
|
||||
fprintf(stderr, "[sectionsd] pid: %d\n", getpid());
|
||||
fflush(stderr);
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&start_stop_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DMX::unlock(void)
|
||||
{
|
||||
//dprintf("DMX::unlock, thread %lu\n", pthread_self());
|
||||
#ifdef DEBUG_MUTEX
|
||||
int rc = pthread_mutex_unlock(&start_stop_mutex);
|
||||
if (rc != 0)
|
||||
{
|
||||
fprintf(stderr, "[sectionsd] mutex_unlock: %d %d %d\n", rc, EINVAL, EPERM);
|
||||
fflush(stderr);
|
||||
fprintf(stderr, "[sectionsd] pid: %d\n", getpid());
|
||||
fflush(stderr);
|
||||
}
|
||||
#else
|
||||
pthread_mutex_unlock(&start_stop_mutex);
|
||||
#endif
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
sections_id_t DMX::create_sections_id(const unsigned char table_id, const unsigned short extension_id, const unsigned char section_number, const unsigned short onid, const unsigned short tsid)
|
||||
{
|
||||
return (sections_id_t) ( ((sections_id_t) table_id << 56) |
|
||||
((sections_id_t) extension_id << 40) |
|
||||
((sections_id_t) section_number << 32) |
|
||||
((sections_id_t) onid << 16) |
|
||||
((sections_id_t) tsid));
|
||||
}
|
||||
|
||||
bool DMX::check_complete(const unsigned char table_id, const unsigned short extension_id, const unsigned short onid, const unsigned short tsid, const unsigned char last)
|
||||
{
|
||||
int current_section_number = 0;
|
||||
|
||||
if (((table_id == 0x4e) || (table_id == 0x50)) && (current_service == extension_id)) {
|
||||
if (last == 0)
|
||||
return true;
|
||||
MyDMXOrderUniqueKey::iterator di = myDMXOrderUniqueKey.find(create_sections_id(
|
||||
table_id,
|
||||
extension_id,
|
||||
current_section_number,
|
||||
onid,
|
||||
tsid));
|
||||
if (di != myDMXOrderUniqueKey.end()) {
|
||||
di++;
|
||||
}
|
||||
while ((di != myDMXOrderUniqueKey.end()) && ((uint8_t) ((di->first >> 56) & 0xff) == table_id) &&
|
||||
((uint16_t) ((di->first >> 40) & 0xffff) == extension_id) &&
|
||||
(((uint8_t) ((di->first >> 32) & 0xff) == current_section_number + 1) ||
|
||||
((uint8_t) ((di->first >> 32) & 0xff) == current_section_number + 8)) &&
|
||||
((uint16_t) ((di->first >> 16) & 0xffff) == onid) &&
|
||||
((uint16_t) (di->first & 0xffff) == tsid))
|
||||
{
|
||||
if ((uint8_t) ((di->first >> 32) & 0xff) == last) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
current_section_number = (uint8_t) (di->first >> 32) & 0xff;
|
||||
di++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMX::getSection(char *buf, const unsigned timeoutInMSeconds, int &timeouts)
|
||||
{
|
||||
struct minimal_section_header {
|
||||
unsigned table_id : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned section_syntax_indicator : 1;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned section_length_hi : 4;
|
||||
#else
|
||||
unsigned section_length_hi : 4;
|
||||
unsigned reserved1 : 2;
|
||||
unsigned reserved_future_use : 1;
|
||||
unsigned section_syntax_indicator : 1;
|
||||
#endif
|
||||
unsigned section_length_lo : 8;
|
||||
} __attribute__ ((packed)); // 3 bytes total
|
||||
|
||||
struct extended_section_header {
|
||||
unsigned table_extension_id_hi : 8;
|
||||
unsigned table_extension_id_lo : 8;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned reserved : 2;
|
||||
unsigned version_number : 5;
|
||||
unsigned current_next_indicator : 1;
|
||||
#else
|
||||
unsigned current_next_indicator : 1;
|
||||
unsigned version_number : 5;
|
||||
unsigned reserved : 2;
|
||||
#endif
|
||||
unsigned section_number : 8;
|
||||
unsigned last_section_number : 8;
|
||||
} __attribute__ ((packed)); // 5 bytes total
|
||||
|
||||
struct eit_extended_section_header {
|
||||
unsigned transport_stream_id_hi : 8;
|
||||
unsigned transport_stream_id_lo : 8;
|
||||
unsigned original_network_id_hi : 8;
|
||||
unsigned original_network_id_lo : 8;
|
||||
unsigned segment_last_section_number : 8;
|
||||
unsigned last_table_id : 8;
|
||||
} __attribute__ ((packed)); // 6 bytes total
|
||||
|
||||
minimal_section_header *initial_header;
|
||||
extended_section_header *extended_header;
|
||||
eit_extended_section_header *eit_extended_header;
|
||||
int rc;
|
||||
unsigned short section_length;
|
||||
unsigned short current_onid = 0;
|
||||
unsigned short current_tsid = 0;
|
||||
|
||||
/* filter == 0 && maks == 0 => EIT dummy filter to slow down EIT thread startup */
|
||||
if (pID == 0x12 && filters[filter_index].filter == 0 && filters[filter_index].mask == 0)
|
||||
{
|
||||
//dprintf("dmx: dummy filter, sleeping for %d ms\n", timeoutInMSeconds);
|
||||
usleep(timeoutInMSeconds * 1000);
|
||||
timeouts++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
lock();
|
||||
|
||||
//rc = read(buf, 4098, timeoutInMSeconds);
|
||||
rc = dmx->Read((unsigned char *) buf, 4098, timeoutInMSeconds);
|
||||
|
||||
if (rc < 3)
|
||||
{
|
||||
unlock();
|
||||
if (rc <= 0)
|
||||
{
|
||||
dprintf("dmx.read timeout - filter: %x - timeout# %d\n", filters[filter_index].filter, timeouts);
|
||||
timeouts++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf("dmx.read rc: %d - filter: %x\n", rc, filters[filter_index].filter);
|
||||
// restart DMX
|
||||
real_pause();
|
||||
real_unpause();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
initial_header = (minimal_section_header*)buf;
|
||||
section_length = (initial_header->section_length_hi * 256) | initial_header->section_length_lo;
|
||||
|
||||
if (section_length <= 0)
|
||||
{
|
||||
unlock();
|
||||
fprintf(stderr, "[sectionsd] section_length <= 0: %d [%s:%s:%d] please report!\n", section_length, __FILE__,__FUNCTION__,__LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
timeouts = 0;
|
||||
|
||||
if (rc != section_length + 3)
|
||||
{
|
||||
xprintf("rc != section_length + 3 (%d != %d + 3)\n", rc, section_length);
|
||||
unlock();
|
||||
// DMX restart required? This should never happen anyway.
|
||||
real_pause();
|
||||
real_unpause();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check if the filter worked correctly
|
||||
if (((initial_header->table_id ^ filters[filter_index].filter) & filters[filter_index].mask) != 0)
|
||||
{
|
||||
printf("[sectionsd] filter 0x%x mask 0x%x -> skip sections for table 0x%x\n", filters[filter_index].filter, filters[filter_index].mask, initial_header->table_id);
|
||||
unlock();
|
||||
real_pause();
|
||||
real_unpause();
|
||||
return -1;
|
||||
}
|
||||
|
||||
unlock();
|
||||
// skip sections which are too short
|
||||
if ((section_length < 5) ||
|
||||
(initial_header->table_id >= 0x4e && initial_header->table_id <= 0x6f && section_length < 14))
|
||||
{
|
||||
dprintf("section too short: table %x, length: %d\n", initial_header->table_id, section_length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check if it's extended syntax, e.g. NIT, BAT, SDT, EIT
|
||||
if (initial_header->section_syntax_indicator != 0)
|
||||
{
|
||||
extended_header = (extended_section_header *)(buf+3);
|
||||
|
||||
// only current sections
|
||||
if (extended_header->current_next_indicator != 0) {
|
||||
// if ((initial_header.table_id >= 0x4e) && (initial_header.table_id <= 0x6f))
|
||||
if (pID == 0x12) {
|
||||
eit_extended_header = (eit_extended_section_header *)(buf+8);
|
||||
current_onid = eit_extended_header->original_network_id_hi * 256 +
|
||||
eit_extended_header->original_network_id_lo;
|
||||
current_tsid = eit_extended_header->transport_stream_id_hi * 256 +
|
||||
eit_extended_header->transport_stream_id_lo;
|
||||
}
|
||||
else {
|
||||
current_onid = 0;
|
||||
current_tsid = 0;
|
||||
}
|
||||
|
||||
int eh_tbl_extension_id = extended_header->table_extension_id_hi * 256
|
||||
+ extended_header->table_extension_id_lo;
|
||||
|
||||
/* if we are not caching the already read sections (CN-thread), check EIT version and get out */
|
||||
if (!cache)
|
||||
{
|
||||
if (initial_header->table_id == 0x4e &&
|
||||
eh_tbl_extension_id == current_service &&
|
||||
extended_header->version_number != eit_version) {
|
||||
dprintf("EIT old: %d new version: %d\n",eit_version,extended_header->version_number);
|
||||
eit_version = extended_header->version_number;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
// the current section
|
||||
sections_id_t s_id = create_sections_id(initial_header->table_id,
|
||||
eh_tbl_extension_id,
|
||||
extended_header->section_number,
|
||||
current_onid,
|
||||
current_tsid);
|
||||
//find current section in list
|
||||
MyDMXOrderUniqueKey::iterator di = myDMXOrderUniqueKey.find(s_id);
|
||||
if (di != myDMXOrderUniqueKey.end())
|
||||
{
|
||||
//the current section was read before
|
||||
if (di->second == extended_header->version_number) {
|
||||
#ifdef DEBUG_CACHED_SECTIONS
|
||||
dprintf("[sectionsd] skipped duplicate section for table 0x%02x table_extension 0x%04x section 0x%02x\n",
|
||||
initial_header->table_id,
|
||||
eh_tbl_extension_id,
|
||||
extended_header->section_number);
|
||||
#endif
|
||||
//the version number is still up2date
|
||||
if (first_skipped == 0) {
|
||||
//the last section was new - this is the 1st dup
|
||||
first_skipped = s_id;
|
||||
}
|
||||
else {
|
||||
//this is not the 1st new - check if it's the last
|
||||
//or to be more precise only dups occured since
|
||||
if (first_skipped == s_id)
|
||||
timeouts = -1;
|
||||
}
|
||||
//since version is still up2date, check if table complete
|
||||
if (check_complete(initial_header->table_id,
|
||||
eh_tbl_extension_id,
|
||||
current_onid,
|
||||
current_tsid,
|
||||
extended_header->last_section_number))
|
||||
timeouts = -2;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG_CACHED_SECTIONS
|
||||
dprintf("[sectionsd] version update from 0x%02x to 0x%02x for table 0x%02x table_extension 0x%04x section 0x%02x\n",
|
||||
di->second,
|
||||
extended_header->version_number,
|
||||
initial_header->table_id,
|
||||
eh_tbl_extension_id,
|
||||
extended_header->section_number);
|
||||
#endif
|
||||
//update version number
|
||||
di->second = extended_header->version_number;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_CACHED_SECTIONS
|
||||
dprintf("[sectionsd] new section for table 0x%02x table_extension 0x%04x section 0x%02x\n",
|
||||
initial_header->table_id,
|
||||
eh_tbl_extension_id,
|
||||
extended_header->section_number);
|
||||
#endif
|
||||
//section was not read before - insert in list
|
||||
myDMXOrderUniqueKey.insert(std::make_pair(s_id, extended_header->version_number));
|
||||
//check if table is now complete
|
||||
if (check_complete(initial_header->table_id,
|
||||
eh_tbl_extension_id,
|
||||
current_onid,
|
||||
current_tsid,
|
||||
extended_header->last_section_number))
|
||||
timeouts = -2;
|
||||
}
|
||||
//if control comes to here the sections skipped counter must be restarted
|
||||
first_skipped = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int DMX::immediate_start(void)
|
||||
{
|
||||
if (isOpen())
|
||||
{
|
||||
xprintf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>DMX::imediate_start: isOpen()<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
|
||||
closefd();
|
||||
}
|
||||
|
||||
if (real_pauseCounter != 0) {
|
||||
dprintf("DMX::immediate_start: realPausecounter !=0 (%d)!\n", real_pauseCounter);
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
if ((fd = open(DEMUX_DEVICE, O_RDWR|O_NONBLOCK)) == -1)
|
||||
{
|
||||
perror("[sectionsd] open dmx");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (ioctl(fd, DMX_SET_BUFFER_SIZE, (unsigned long)(dmxBufferSizeInKB*1024UL)) == -1)
|
||||
{
|
||||
closefd();
|
||||
perror("[sectionsd] DMX: DMX_SET_BUFFER_SIZE");
|
||||
return 3;
|
||||
}
|
||||
#endif
|
||||
if(dmx == NULL) {
|
||||
dmx = new cDemux(dmx_num);
|
||||
#if !HAVE_TRIPLEDRAGON
|
||||
dmx->Open(DMX_PSI_CHANNEL, NULL, dmxBufferSizeInKB*1024UL);
|
||||
#endif
|
||||
}
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
dmx->Open(DMX_PSI_CHANNEL, NULL, dmxBufferSizeInKB*1024UL);
|
||||
#endif
|
||||
fd = 1;
|
||||
|
||||
/* setfilter() only if this is no dummy filter... */
|
||||
#if 0
|
||||
if (filters[filter_index].filter && filters[filter_index].mask &&
|
||||
!setfilter(fd, pID, filters[filter_index].filter, filters[filter_index].mask, DMX_IMMEDIATE_START | DMX_CHECK_CRC))
|
||||
#endif
|
||||
if (filters[filter_index].filter && filters[filter_index].mask)
|
||||
{
|
||||
unsigned char filter[DMX_FILTER_SIZE];
|
||||
unsigned char mask[DMX_FILTER_SIZE];
|
||||
|
||||
filter[0] = filters[filter_index].filter;
|
||||
mask[0] = filters[filter_index].mask;
|
||||
dmx->sectionFilter(pID, filter, mask, 1);
|
||||
//FIXME error check
|
||||
//closefd();
|
||||
//return 4;
|
||||
}
|
||||
/* this is for dmxCN only... */
|
||||
eit_version = 0xff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DMX::start(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
lock();
|
||||
|
||||
rc = immediate_start();
|
||||
|
||||
unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int DMX::real_pause(void)
|
||||
{
|
||||
if (!isOpen()) {
|
||||
dprintf("DMX::real_pause: (!isOpen())\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
lock();
|
||||
|
||||
if (real_pauseCounter == 0)
|
||||
{
|
||||
immediate_stop();
|
||||
}
|
||||
//else
|
||||
// dprintf("real_pause: counter %d\n", real_pauseCounter);
|
||||
|
||||
unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DMX::real_unpause(void)
|
||||
{
|
||||
lock();
|
||||
|
||||
if (real_pauseCounter == 0)
|
||||
{
|
||||
immediate_start();
|
||||
//dprintf("real_unpause DONE: %d\n", real_pauseCounter);
|
||||
}
|
||||
//else
|
||||
// dprintf("real_unpause NOT DONE: %d\n", real_pauseCounter);
|
||||
|
||||
unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DMX::request_pause(void)
|
||||
{
|
||||
real_pause(); // unlocked
|
||||
|
||||
lock();
|
||||
//dprintf("request_pause: %d\n", real_pauseCounter);
|
||||
|
||||
real_pauseCounter++;
|
||||
|
||||
unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int DMX::request_unpause(void)
|
||||
{
|
||||
lock();
|
||||
|
||||
//dprintf("request_unpause: %d\n", real_pauseCounter);
|
||||
--real_pauseCounter;
|
||||
|
||||
unlock();
|
||||
|
||||
real_unpause(); // unlocked
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
to be removed....
|
||||
int DMX::pause(void)
|
||||
{
|
||||
pthread_mutex_lock(&pauselock);
|
||||
|
||||
//dprintf("lock from pc: %d\n", pauseCounter);
|
||||
pauseCounter++;
|
||||
|
||||
pthread_mutex_unlock(&pauselock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DMX::unpause(void)
|
||||
{
|
||||
pthread_mutex_lock(&pauselock);
|
||||
|
||||
//dprintf("unlock from pc: %d\n", pauseCounter);
|
||||
--pauseCounter;
|
||||
|
||||
pthread_mutex_unlock(&pauselock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *dmx_filter_types [] = {
|
||||
"dummy filter",
|
||||
"actual transport stream, scheduled",
|
||||
"other transport stream, now/next",
|
||||
"other transport stream, scheduled 1",
|
||||
"other transport stream, scheduled 2"
|
||||
};
|
||||
|
||||
int DMX::change(const int new_filter_index, const int new_current_service)
|
||||
{
|
||||
if (sections_debug)
|
||||
showProfiling("changeDMX: before pthread_mutex_lock(&start_stop_mutex)");
|
||||
lock();
|
||||
|
||||
if (sections_debug)
|
||||
showProfiling("changeDMX: after pthread_mutex_lock(&start_stop_mutex)");
|
||||
|
||||
filter_index = new_filter_index;
|
||||
first_skipped = 0;
|
||||
|
||||
#if 0
|
||||
/* i have to think about this. This #if 0 now makes .change() automatically unpause the
|
||||
* demux. No idea if there are negative side effects - we will find out :) -- seife
|
||||
*/
|
||||
if (!isOpen())
|
||||
{
|
||||
pthread_cond_signal(&change_cond);
|
||||
unlock();
|
||||
dprintf("DMX::change(%d): not open!\n",new_filter_index);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
if (new_current_service != -1)
|
||||
current_service = new_current_service;
|
||||
|
||||
if (real_pauseCounter > 0)
|
||||
{
|
||||
printf("changeDMX: for 0x%x not ignored! even though real_pauseCounter> 0 (%d)\n",
|
||||
filters[new_filter_index].filter, real_pauseCounter);
|
||||
/* immediate_start() checks for real_pauseCounter again (and
|
||||
does nothing in that case), so we can just continue here. */
|
||||
}
|
||||
|
||||
if (sections_debug) { // friendly debug output...
|
||||
if(pID==0x12 && filters[0].filter != 0x4e) { // Only EIT
|
||||
printdate_ms(stderr);
|
||||
fprintf(stderr, "changeDMX [EIT]-> %d (0x%x/0x%x) %s (%ld seconds)\n",
|
||||
new_filter_index, filters[new_filter_index].filter,
|
||||
filters[new_filter_index].mask, dmx_filter_types[new_filter_index],
|
||||
time_monotonic()-lastChanged);
|
||||
} else {
|
||||
printdate_ms(stderr);
|
||||
fprintf(stderr, "changeDMX [%x]-> %d (0x%x/0x%x) (%ld seconds)\n", pID,
|
||||
new_filter_index, filters[new_filter_index].filter,
|
||||
filters[new_filter_index].mask, time_monotonic()-lastChanged);
|
||||
}
|
||||
}
|
||||
|
||||
closefd();
|
||||
|
||||
int rc = immediate_start();
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (sections_debug)
|
||||
showProfiling("after DMX_SET_FILTER");
|
||||
|
||||
pthread_cond_signal(&change_cond);
|
||||
|
||||
lastChanged = time_monotonic();
|
||||
|
||||
unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Liest n Bytes aus einem Socket per read
|
||||
// Liefert 0 bei timeout
|
||||
// und -1 bei Fehler
|
||||
// ansonsten die Anzahl gelesener Bytes
|
||||
/* inline */
|
||||
ssize_t DMX::readNbytes(int _fd, char *buf, const size_t n, unsigned timeoutInMSeconds)
|
||||
{
|
||||
int rc;
|
||||
struct pollfd ufds;
|
||||
ufds.fd = _fd;
|
||||
ufds.events = POLLIN;
|
||||
ufds.revents = 0;
|
||||
|
||||
rc = ::poll(&ufds, 1, timeoutInMSeconds);
|
||||
|
||||
if (!rc)
|
||||
return 0; // timeout
|
||||
else if (rc < 0)
|
||||
{
|
||||
/* we consciously ignore EINTR, since it does not happen in practice */
|
||||
perror ("[sectionsd] DMX::readNbytes poll");
|
||||
return -1;
|
||||
}
|
||||
if ((ufds.revents & POLLERR) != 0) /* POLLERR means buffer error, i.e. buffer overflow */
|
||||
{
|
||||
printdate_ms(stderr);
|
||||
fprintf(stderr, "[sectionsd] DMX::readNbytes received POLLERR, pid 0x%x, filter[%d] "
|
||||
"filter 0x%02x mask 0x%02x\n", pID, filter_index,
|
||||
filters[filter_index].filter, filters[filter_index].mask);
|
||||
return -1;
|
||||
}
|
||||
if (!(ufds.revents&POLLIN))
|
||||
{
|
||||
xprintf("%s: not ufds.revents&POLLIN, please report!\n", __FUNCTION__);
|
||||
// POLLHUP, beim dmx bedeutet das DMXDEV_STATE_TIMEDOUT
|
||||
// kommt wenn ein Timeout im Filter gesetzt wurde
|
||||
// dprintf("revents: 0x%hx\n", ufds.revents);
|
||||
// usleep(100*1000UL); // wir warten 100 Millisekunden bevor wir es nochmal probieren
|
||||
// if (timeoutInMSeconds <= 200000)
|
||||
return 0; // timeout
|
||||
// timeoutInMSeconds -= 200000;
|
||||
// goto retry;
|
||||
}
|
||||
|
||||
int r = ::read(_fd, buf, n);
|
||||
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
perror ("[sectionsd] DMX::readNbytes read");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int DMX::setPid(const unsigned short new_pid)
|
||||
{
|
||||
lock();
|
||||
|
||||
if (!isOpen())
|
||||
{
|
||||
pthread_cond_signal(&change_cond);
|
||||
unlock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (real_pauseCounter > 0)
|
||||
{
|
||||
dprintf("changeDMX: for 0x%x ignored! because of real_pauseCounter> 0 (%d)\n", new_pid, real_pauseCounter);
|
||||
unlock();
|
||||
return 0; // not running (e.g. streaming)
|
||||
}
|
||||
closefd();
|
||||
|
||||
pID = new_pid;
|
||||
int rc = immediate_start();
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
pthread_cond_signal(&change_cond);
|
||||
|
||||
lastChanged = time_monotonic();
|
||||
|
||||
unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DMX::setCurrentService(int new_current_service)
|
||||
{
|
||||
return change(0, new_current_service);
|
||||
}
|
||||
|
||||
int DMX::dropCachedSectionIDs()
|
||||
{
|
||||
lock();
|
||||
|
||||
/* i think that those checks are wrong for dropCachedSectionIDs(), since
|
||||
this is called from the housekeeping thread while sectionsd might be
|
||||
idle waiting for the EIT update filter to trigger -- seife
|
||||
*/
|
||||
#if 0
|
||||
if (!isOpen())
|
||||
{
|
||||
pthread_cond_signal(&change_cond);
|
||||
unlock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (real_pauseCounter > 0)
|
||||
{
|
||||
unlock();
|
||||
return 0; // not running (e.g. streaming)
|
||||
}
|
||||
closefd();
|
||||
#endif
|
||||
|
||||
myDMXOrderUniqueKey.clear();
|
||||
|
||||
#if 0
|
||||
int rc = immediate_start();
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
unlock();
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
pthread_cond_signal(&change_cond);
|
||||
|
||||
unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char DMX::get_eit_version()
|
||||
{
|
||||
return eit_version;
|
||||
}
|
||||
|
||||
unsigned int DMX::get_current_service()
|
||||
{
|
||||
return current_service;
|
||||
}
|
208
src/eitd/dmxapi.cpp
Normal file
208
src/eitd/dmxapi.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* $Header: /cvs/tuxbox/apps/tuxbox/neutrino/daemons/sectionsd/dmxapi.cpp,v 1.5 2005/01/13 10:48:02 diemade Exp $
|
||||
*
|
||||
* DMX low level functions (sectionsd) - d-box2 linux project
|
||||
*
|
||||
* (C) 2003 by thegoodguy <thegoodguy@berlios.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h> /* perror */
|
||||
#include <string.h> /* memset */
|
||||
#include <sys/ioctl.h> /* ioctl */
|
||||
#include <fcntl.h> /* open */
|
||||
#include <unistd.h> /* close, read */
|
||||
#include <arpa/inet.h> /* htons */
|
||||
#include <time.h> /* ctime */
|
||||
#include <dmxapi.h>
|
||||
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
#include <dmx_td.h>
|
||||
#else
|
||||
#include <dmx_cs.h>
|
||||
#endif
|
||||
|
||||
#include "SIutils.hpp"
|
||||
#include "debug.h"
|
||||
|
||||
#ifndef DO_NOT_INCLUDE_STUFF_NOT_NEEDED_FOR_SECTIONSD
|
||||
bool setfilter(const int fd, const uint16_t pid, const uint8_t filter, const uint8_t mask, const uint32_t flags)
|
||||
{
|
||||
struct dmx_sct_filter_params flt;
|
||||
|
||||
memset(&flt, 0, sizeof(struct dmx_sct_filter_params));
|
||||
|
||||
flt.pid = pid;
|
||||
flt.filter.filter[0] = filter;
|
||||
flt.filter.mask [0] = mask;
|
||||
flt.timeout = 0;
|
||||
flt.flags = flags;
|
||||
|
||||
if (::ioctl(fd, DMX_SET_FILTER, &flt) == -1)
|
||||
{
|
||||
perror("[sectionsd] DMX: DMX_SET_FILTER");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct SI_section_TOT_header
|
||||
{
|
||||
unsigned char table_id : 8;
|
||||
unsigned char section_syntax_indicator : 1;
|
||||
unsigned char reserved_future_use : 1;
|
||||
unsigned char reserved1 : 2;
|
||||
unsigned short section_length : 12;
|
||||
UTC_t UTC_time; /* :40 */
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned char reserved2 : 4;
|
||||
unsigned char descr_loop_length_hi : 4;
|
||||
#else
|
||||
unsigned char descr_loop_length_hi : 4;
|
||||
unsigned char reserved2 : 4;
|
||||
#endif
|
||||
unsigned short descr_loop_length_lo : 8;
|
||||
}
|
||||
__attribute__ ((packed)); /* 10 bytes */
|
||||
|
||||
struct SI_section_TDT_header
|
||||
{
|
||||
unsigned char table_id : 8;
|
||||
unsigned char section_syntax_indicator : 1;
|
||||
unsigned char reserved_future_use : 1;
|
||||
unsigned char reserved1 : 2;
|
||||
unsigned short section_length : 12;
|
||||
/* uint64_t UTC_time : 40;*/
|
||||
UTC_t UTC_time;
|
||||
}
|
||||
__attribute__ ((packed)); /* 8 bytes */
|
||||
|
||||
struct descrLocalTimeOffset
|
||||
{
|
||||
unsigned char country_code[3];
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned char country_region_id : 6;
|
||||
unsigned char reserved_1 : 1;
|
||||
unsigned char local_time_offset_polarity : 1;
|
||||
#else
|
||||
unsigned char local_time_offset_polarity : 1;
|
||||
unsigned char reserved_1 : 1;
|
||||
unsigned char country_region_id : 6;
|
||||
#endif
|
||||
unsigned int local_time_offset : 16;
|
||||
unsigned int time_of_change_MJD : 16;
|
||||
unsigned int time_of_change_UTC : 24;
|
||||
unsigned int next_time_offset : 16;
|
||||
} __attribute__ ((packed)); /* 13 bytes */;
|
||||
|
||||
|
||||
cDemux * dmxUTC;
|
||||
bool getUTC(UTC_t * const UTC, const bool TDT)
|
||||
{
|
||||
unsigned char filter[DMX_FILTER_SIZE];
|
||||
unsigned char mask[DMX_FILTER_SIZE];
|
||||
int timeout;
|
||||
struct SI_section_TOT_header tdt_tot_header;
|
||||
char cUTC[5];
|
||||
bool ret = true;
|
||||
|
||||
unsigned char buf[1023+3];
|
||||
|
||||
if(dmxUTC == NULL) {
|
||||
dmxUTC = new cDemux();
|
||||
dmxUTC->Open(DMX_PSI_CHANNEL);
|
||||
}
|
||||
|
||||
memset(&filter, 0, DMX_FILTER_SIZE);
|
||||
memset(&mask, 0, DMX_FILTER_SIZE);
|
||||
|
||||
filter[0] = TDT ? 0x70 : 0x73;
|
||||
mask [0] = 0xFF;
|
||||
timeout = 31000;
|
||||
// flags = TDT ? (DMX_ONESHOT | DMX_IMMEDIATE_START) : (DMX_ONESHOT | DMX_CHECK_CRC | DMX_IMMEDIATE_START);
|
||||
|
||||
dmxUTC->sectionFilter(0x0014, filter, mask, 5, timeout);
|
||||
|
||||
int size = TDT ? sizeof(struct SI_section_TDT_header) : sizeof(tdt_tot_header);
|
||||
int r = dmxUTC->Read(buf, TDT ? size : sizeof(buf));
|
||||
if (r < size) {
|
||||
if (TDT || sections_debug) /* not having TOT is common, no need to log */
|
||||
perror("[sectionsd] getUTC: read");
|
||||
dmxUTC->Stop();
|
||||
return false;
|
||||
}
|
||||
memset(&tdt_tot_header, 0, sizeof(tdt_tot_header));
|
||||
memmove(&tdt_tot_header, buf, size);
|
||||
|
||||
int64_t tmp = tdt_tot_header.UTC_time.time;
|
||||
memmove(cUTC, (&tdt_tot_header.UTC_time), 5);
|
||||
if ((cUTC[2] > 0x23) || (cUTC[3] > 0x59) || (cUTC[4] > 0x59)) // no valid time
|
||||
{
|
||||
printf("[sectionsd] getUTC: invalid %s section received: %02x %02x %02x %02x %02x\n",
|
||||
TDT ? "TDT" : "TOT", cUTC[0], cUTC[1], cUTC[2], cUTC[3], cUTC[4]);
|
||||
ret = false;
|
||||
}
|
||||
|
||||
(*UTC).time = tmp;
|
||||
|
||||
#if 1
|
||||
short loop_length = tdt_tot_header.descr_loop_length_hi << 8 | tdt_tot_header.descr_loop_length_lo;
|
||||
if (loop_length >= 15) {
|
||||
int off = sizeof(tdt_tot_header);
|
||||
int rem = loop_length;
|
||||
while (rem >= 15)
|
||||
{
|
||||
unsigned char *b2 = &buf[off];
|
||||
if (b2[0] == 0x58) {
|
||||
struct descrLocalTimeOffset *to;
|
||||
to = (struct descrLocalTimeOffset *)&b2[2];
|
||||
unsigned char cc[4];
|
||||
cc[3] = 0;
|
||||
memmove(cc, to->country_code, 3);
|
||||
time_t t = changeUTCtoCtime(&b2[2+6],0);
|
||||
xprintf("getUTC(TOT): len=%d cc=%s reg_id=%d "
|
||||
"pol=%d offs=%04x new=%04x when=%s",
|
||||
b2[1], cc, to->country_region_id,
|
||||
to->local_time_offset_polarity, htons(to->local_time_offset),
|
||||
htons(to->next_time_offset), ctime(&t));
|
||||
} else {
|
||||
xprintf("getUTC(TOT): descriptor != 0x58: 0x%02x\n", b2[0]);
|
||||
}
|
||||
off += b2[1] + 2;
|
||||
rem -= b2[1] + 2;
|
||||
if (off + rem > (int)sizeof(buf))
|
||||
{
|
||||
xprintf("getUTC(TOT): not enough buffer space? (%d/%d)\n", off+rem, sizeof(buf));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TOT without descriptors seems to be not better than a plain TDT, such TOT's are */
|
||||
/* found on transponders which also have wrong time in TDT etc, so don't trust it. */
|
||||
if (loop_length < 15 && !TDT)
|
||||
ret = false;
|
||||
|
||||
//delete dmxUTC;
|
||||
dmxUTC->Stop();
|
||||
|
||||
return ret;
|
||||
}
|
886
src/eitd/edvbstring.cpp
Normal file
886
src/eitd/edvbstring.cpp
Normal file
@@ -0,0 +1,886 @@
|
||||
#include <string>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <debug.h>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
std::map<std::string, int> CountryCodeDefaultMapping;
|
||||
std::map<int, int> TransponderDefaultMapping;
|
||||
std::set<int> TransponderUseTwoCharMapping;
|
||||
|
||||
int readEncodingFile()
|
||||
{
|
||||
FILE *f = fopen("/var/tuxbox/config/encoding.conf", "rt");
|
||||
if (f) {
|
||||
CountryCodeDefaultMapping.clear();
|
||||
TransponderDefaultMapping.clear();
|
||||
TransponderUseTwoCharMapping.clear();
|
||||
char line[256];
|
||||
size_t bufsize=256;
|
||||
char countrycode[256];
|
||||
while(fgets(line, bufsize, f)) {
|
||||
if ( line[0] == '#' )
|
||||
continue;
|
||||
int tsid, onid, encoding;
|
||||
if ( sscanf( line, "%s ISO8859-%d", countrycode, &encoding ) == 2 )
|
||||
CountryCodeDefaultMapping[countrycode]=encoding;
|
||||
else if ( (sscanf( line, "0x%x 0x%x ISO8859-%d", &tsid, &onid, &encoding ) == 3 )
|
||||
||(sscanf( line, "%d %d ISO8859-%d", &tsid, &onid, &encoding ) == 3 ) )
|
||||
TransponderDefaultMapping[(tsid<<16)|onid]=encoding;
|
||||
else if ( (sscanf( line, "0x%x 0x%x ISO%d", &tsid, &onid, &encoding ) == 3 && encoding == 6937 )
|
||||
||(sscanf( line, "%d %d ISO%d", &tsid, &onid, &encoding ) == 3 && encoding == 6937 ) )
|
||||
TransponderDefaultMapping[(tsid<<16)|onid]=64;
|
||||
else if ( (sscanf( line, "0x%x 0x%x", &tsid, &onid ) == 2 )
|
||||
||(sscanf( line, "%d %d", &tsid, &onid ) == 2 ) )
|
||||
TransponderUseTwoCharMapping.insert((tsid<<16)|onid);
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 8859-x to ucs-16 coding tables. taken from www.unicode.org/Public/MAPPINGS/ISO8859/
|
||||
|
||||
static unsigned long c88592[96]= {
|
||||
0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
|
||||
0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
|
||||
0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
|
||||
0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
|
||||
0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
|
||||
0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 0x0142, /*0x0159,*/ 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
|
||||
};
|
||||
|
||||
static unsigned long c88593[96]= {
|
||||
0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7, 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B,
|
||||
0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C,
|
||||
0x00C0, 0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7, 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
|
||||
0x00E0, 0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x0000, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9
|
||||
};
|
||||
|
||||
static unsigned long c88594[96]= {
|
||||
0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7, 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
|
||||
0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7, 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
|
||||
0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
|
||||
0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
|
||||
0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
|
||||
0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9
|
||||
};
|
||||
|
||||
static unsigned long c88595[96]= {
|
||||
0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
|
||||
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
|
||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
|
||||
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
||||
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
|
||||
0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F
|
||||
};
|
||||
|
||||
static unsigned long c88596[96]= {
|
||||
0x00A0, 0x0000, 0x0000, 0x0000, 0x00A4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x060C, 0x00AD, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x061B, 0x0000, 0x0000, 0x0000, 0x061F,
|
||||
0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
|
||||
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F,
|
||||
0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
};
|
||||
|
||||
static unsigned long c88597[96]= {
|
||||
0x00A0, 0x2018, 0x2019, 0x00A3, 0x20AC, 0x20AF, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x037A, 0x00AB, 0x00AC, 0x00AD, 0x0000, 0x2015,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7, 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
|
||||
0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
|
||||
0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
|
||||
0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
|
||||
0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000
|
||||
};
|
||||
|
||||
static unsigned long c88598[96]= {
|
||||
0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017,
|
||||
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
|
||||
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000
|
||||
};
|
||||
|
||||
static unsigned long c88599[96]= {
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
|
||||
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
|
||||
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
|
||||
};
|
||||
|
||||
static unsigned long c885910[96]= {
|
||||
0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7, 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
|
||||
0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7, 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B,
|
||||
0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168, 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
|
||||
0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138
|
||||
};
|
||||
|
||||
static unsigned long c885911[96]= {
|
||||
0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
|
||||
0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
|
||||
0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
|
||||
0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F,
|
||||
0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
|
||||
0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
};
|
||||
|
||||
static unsigned long c885913[96]= {
|
||||
0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7, 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7, 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
|
||||
0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
|
||||
0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
|
||||
0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
|
||||
0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019
|
||||
};
|
||||
|
||||
static unsigned long c885914[96]= {
|
||||
0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7, 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178,
|
||||
0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56, 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61,
|
||||
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF,
|
||||
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF
|
||||
};
|
||||
|
||||
static unsigned long c885915[96]= {
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7, 0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x00B7, 0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF,
|
||||
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
|
||||
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
|
||||
};
|
||||
|
||||
static unsigned long c885916[96]= {
|
||||
0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7, 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B,
|
||||
0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7, 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C,
|
||||
0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A, 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF,
|
||||
0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B, 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF
|
||||
};
|
||||
static unsigned long iso6937[96]={
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0000, 0x00A7, 0x00A4, 0x2018, 0x201C, 0x00AB, 0x2190, 0x2191, 0x2192, 0x2193,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00D7, 0x00B5, 0x00B6, 0x00B7, 0x00F7, 0x2019, 0x201D, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
|
||||
0x0000, 0xE002, 0xE003, 0xE004, 0xE005, 0xE006, 0xE007, 0xE008, 0xE009, 0xE00C, 0xE00A, 0xE00B, 0x0000, 0xE00D, 0xE00E, 0xE00F,
|
||||
0x2015, 0x00B9, 0x00AE, 0x00A9, 0x2122, 0x266A, 0x00AC, 0x00A6, 0x0000, 0x0000, 0x0000, 0x0000, 0x215B, 0x215C, 0x215D, 0x215E,
|
||||
0x2126, 0x00C6, 0x0110, 0x00AA, 0x0126, 0x0000, 0x0132, 0x013F, 0x0141, 0x00D8, 0x0152, 0x00BA, 0x00DE, 0x0166, 0x014A, 0x0149,
|
||||
0x0138, 0x00E6, 0x0111, 0x00F0, 0x0127, 0x0131, 0x0133, 0x0140, 0x0142, 0x00F8, 0x0153, 0x00DF, 0x00FE, 0x0167, 0x014B, 0x00AD
|
||||
};
|
||||
|
||||
// Two Char Mapping ( many polish services and UPC Direct/HBO services)
|
||||
// get from http://mitglied.lycos.de/buran/charsets/videotex-suppl.html
|
||||
//static inline unsigned int doVideoTexSuppl(int c1, int c2)
|
||||
static inline unsigned int doVideoTexSuppl(char c1, char c2)
|
||||
{
|
||||
switch (c1)
|
||||
{
|
||||
case 0xC1: // grave
|
||||
switch (c2)
|
||||
{
|
||||
case 0x61:
|
||||
return 224;
|
||||
case 0x41:
|
||||
return 192;
|
||||
case 0x65:
|
||||
return 232;
|
||||
case 0x45:
|
||||
return 200;
|
||||
case 0x69:
|
||||
return 236;
|
||||
case 0x49:
|
||||
return 204;
|
||||
case 0x6f:
|
||||
return 242;
|
||||
case 0x4f:
|
||||
return 210;
|
||||
case 0x75:
|
||||
return 249;
|
||||
case 0x55:
|
||||
return 217;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xC2: // acute
|
||||
switch (c2)
|
||||
{
|
||||
case 0x61:
|
||||
return 225;
|
||||
case 0x41:
|
||||
return 193;
|
||||
case 0x65:
|
||||
return 233;
|
||||
case 0x45:
|
||||
return 201;
|
||||
case 0x69:
|
||||
return 237;
|
||||
case 0x49:
|
||||
return 205;
|
||||
case 0x6f:
|
||||
return 243;
|
||||
case 0x4f:
|
||||
return 211;
|
||||
case 0x75:
|
||||
return 250;
|
||||
case 0x55:
|
||||
return 218;
|
||||
case 0x79:
|
||||
return 253;
|
||||
case 0x59:
|
||||
return 221;
|
||||
case 0x63:
|
||||
return 263;
|
||||
case 0x43:
|
||||
return 262;
|
||||
case 0x6c:
|
||||
return 314;
|
||||
case 0x4c:
|
||||
return 313;
|
||||
case 0x6e:
|
||||
return 324;
|
||||
case 0x4e:
|
||||
return 323;
|
||||
case 0x72:
|
||||
return 341;
|
||||
case 0x52:
|
||||
return 340;
|
||||
case 0x73:
|
||||
return 347;
|
||||
case 0x53:
|
||||
return 346;
|
||||
case 0x7a:
|
||||
return 378;
|
||||
case 0x5a:
|
||||
return 377;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xC3: // cedilla
|
||||
switch (c2)
|
||||
{
|
||||
case 0x61:
|
||||
return 226;
|
||||
case 0x41:
|
||||
return 194;
|
||||
case 0x65:
|
||||
return 234;
|
||||
case 0x45:
|
||||
return 202;
|
||||
case 0x69:
|
||||
return 238;
|
||||
case 0x49:
|
||||
return 206;
|
||||
case 0x6f:
|
||||
return 244;
|
||||
case 0x4f:
|
||||
return 212;
|
||||
case 0x75:
|
||||
return 251;
|
||||
case 0x55:
|
||||
return 219;
|
||||
case 0x79:
|
||||
return 375;
|
||||
case 0x59:
|
||||
return 374;
|
||||
case 0x63:
|
||||
return 265;
|
||||
case 0x43:
|
||||
return 264;
|
||||
case 0x67:
|
||||
return 285;
|
||||
case 0x47:
|
||||
return 284;
|
||||
case 0x68:
|
||||
return 293;
|
||||
case 0x48:
|
||||
return 292;
|
||||
case 0x6a:
|
||||
return 309;
|
||||
case 0x4a:
|
||||
return 308;
|
||||
case 0x73:
|
||||
return 349;
|
||||
case 0x53:
|
||||
return 348;
|
||||
case 0x77:
|
||||
return 373;
|
||||
case 0x57:
|
||||
return 372;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xC4: // tilde
|
||||
switch (c2)
|
||||
{
|
||||
case 0x61:
|
||||
return 227;
|
||||
case 0x41:
|
||||
return 195;
|
||||
case 0x6e:
|
||||
return 241;
|
||||
case 0x4e:
|
||||
return 209;
|
||||
case 0x69:
|
||||
return 297;
|
||||
case 0x49:
|
||||
return 296;
|
||||
case 0x6f:
|
||||
return 245;
|
||||
case 0x4f:
|
||||
return 213;
|
||||
case 0x75:
|
||||
return 361;
|
||||
case 0x55:
|
||||
return 360;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xC6: // breve
|
||||
switch (c2)
|
||||
{
|
||||
case 0x61:
|
||||
return 259;
|
||||
case 0x41:
|
||||
return 258;
|
||||
case 0x67:
|
||||
return 287;
|
||||
case 0x47:
|
||||
return 286;
|
||||
case 0x75:
|
||||
return 365;
|
||||
case 0x55:
|
||||
return 364;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xC7: // dot above
|
||||
switch (c2)
|
||||
{
|
||||
case 0x63:
|
||||
return 267;
|
||||
case 0x43:
|
||||
return 266;
|
||||
case 0x65:
|
||||
return 279;
|
||||
case 0x45:
|
||||
return 278;
|
||||
case 0x67:
|
||||
return 289;
|
||||
case 0x47:
|
||||
return 288;
|
||||
case 0x49:
|
||||
return 304;
|
||||
case 0x7a:
|
||||
return 380;
|
||||
case 0x5a:
|
||||
return 379;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xC8: // diaeresis
|
||||
switch (c2)
|
||||
{
|
||||
case 0x61:
|
||||
return 228;
|
||||
case 0x41:
|
||||
return 196;
|
||||
case 0x65:
|
||||
return 235;
|
||||
case 0x45:
|
||||
return 203;
|
||||
case 0x69:
|
||||
return 239;
|
||||
case 0x49:
|
||||
return 207;
|
||||
case 0x6f:
|
||||
return 246;
|
||||
case 0x4f:
|
||||
return 214;
|
||||
case 0x75:
|
||||
return 252;
|
||||
case 0x55:
|
||||
return 220;
|
||||
case 0x79:
|
||||
return 255;
|
||||
case 0x59:
|
||||
return 376;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xCA: // ring above
|
||||
switch (c2)
|
||||
{
|
||||
case 0x61:
|
||||
return 229;
|
||||
case 0x41:
|
||||
return 197;
|
||||
case 0x75:
|
||||
return 367;
|
||||
case 0x55:
|
||||
return 366;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xCB: // cedilla
|
||||
switch (c2)
|
||||
{
|
||||
case 0x63:
|
||||
return 231;
|
||||
case 0x43:
|
||||
return 199;
|
||||
case 0x67:
|
||||
return 291;
|
||||
case 0x47:
|
||||
return 290;
|
||||
case 0x6b:
|
||||
return 311;
|
||||
case 0x4b:
|
||||
return 310;
|
||||
case 0x6c:
|
||||
return 316;
|
||||
case 0x4c:
|
||||
return 315;
|
||||
case 0x6e:
|
||||
return 326;
|
||||
case 0x4e:
|
||||
return 325;
|
||||
case 0x72:
|
||||
return 343;
|
||||
case 0x52:
|
||||
return 342;
|
||||
case 0x73:
|
||||
return 351;
|
||||
case 0x53:
|
||||
return 350;
|
||||
case 0x74:
|
||||
return 355;
|
||||
case 0x54:
|
||||
return 354;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xCD: // double acute accent
|
||||
switch (c2)
|
||||
{
|
||||
case 0x6f:
|
||||
return 337;
|
||||
case 0x4f:
|
||||
return 336;
|
||||
case 0x75:
|
||||
return 369;
|
||||
case 0x55:
|
||||
return 368;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xCE: // ogonek
|
||||
switch (c2)
|
||||
{
|
||||
case 0x61:
|
||||
return 261;
|
||||
case 0x41:
|
||||
return 260;
|
||||
case 0x65:
|
||||
return 281;
|
||||
case 0x45:
|
||||
return 280;
|
||||
case 0x69:
|
||||
return 303;
|
||||
case 0x49:
|
||||
return 302;
|
||||
case 0x75:
|
||||
return 371;
|
||||
case 0x55:
|
||||
return 370;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 0xCF: // caron
|
||||
switch (c2)
|
||||
{
|
||||
case 0x63:
|
||||
return 269;
|
||||
case 0x43:
|
||||
return 268;
|
||||
case 0x64:
|
||||
return 271;
|
||||
case 0x44:
|
||||
return 270;
|
||||
case 0x65:
|
||||
return 283;
|
||||
case 0x45:
|
||||
return 282;
|
||||
case 0x6c:
|
||||
return 318;
|
||||
case 0x4c:
|
||||
return 317;
|
||||
case 0x6e:
|
||||
return 328;
|
||||
case 0x4e:
|
||||
return 327;
|
||||
case 0x72:
|
||||
return 345;
|
||||
case 0x52:
|
||||
return 344;
|
||||
case 0x73:
|
||||
return 353;
|
||||
case 0x53:
|
||||
return 352;
|
||||
case 0x74:
|
||||
return 357;
|
||||
case 0x54:
|
||||
return 356;
|
||||
case 0x7a:
|
||||
return 382;
|
||||
case 0x5a:
|
||||
return 381;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int recode(unsigned char d, int cp)
|
||||
{
|
||||
if (d < 0xA0)
|
||||
return d;
|
||||
switch (cp)
|
||||
{
|
||||
case 0: // Latin1 <-> unicode mapping
|
||||
case 1: // 8859-1 <-> unicode mapping
|
||||
return d;
|
||||
case 2: // 8859-2 -> unicode mapping
|
||||
return c88592[d-0xA0];
|
||||
case 3: // 8859-3 -> unicode mapping
|
||||
return c88593[d-0xA0];
|
||||
case 4: // 8859-2 -> unicode mapping
|
||||
return c88594[d-0xA0];
|
||||
case 5: // 8859-5 -> unicode mapping
|
||||
return c88595[d-0xA0];
|
||||
case 6: // 8859-6 -> unicode mapping
|
||||
return c88596[d-0xA0];
|
||||
case 7: // 8859-7 -> unicode mapping
|
||||
return c88597[d-0xA0];
|
||||
case 8: // 8859-8 -> unicode mapping
|
||||
return c88598[d-0xA0];
|
||||
case 9: // 8859-9 -> unicode mapping
|
||||
return c88599[d-0xA0];
|
||||
case 10:// 8859-10 -> unicode mapping
|
||||
return c885910[d-0xA0];
|
||||
case 11:// 8859-11 -> unicode mapping
|
||||
return c885911[d-0xA0];
|
||||
/* case 12:// 8859-12 -> unicode mapping // reserved for indian use..
|
||||
return c885912[d-0xA0];*/
|
||||
case 13:// 8859-13 -> unicode mapping
|
||||
return c885913[d-0xA0];
|
||||
case 14:// 8859-14 -> unicode mapping
|
||||
return c885914[d-0xA0];
|
||||
case 15:// 8859-15 -> unicode mapping
|
||||
return c885915[d-0xA0];
|
||||
case 16:// 8859-16 -> unicode mapping
|
||||
return c885916[d-0xA0];
|
||||
case 64:// ISO6937
|
||||
return iso6937[d-0xA0];
|
||||
default:
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
std::string convertDVBUTF8(const char *data, int len, int table, int tsidonid)
|
||||
{
|
||||
int newtable = 0;
|
||||
bool twochar = false;
|
||||
if (!len)
|
||||
return "";
|
||||
|
||||
int i=0, t=0;
|
||||
|
||||
if ( tsidonid )
|
||||
{
|
||||
std::map<int, int>::iterator it =
|
||||
TransponderDefaultMapping.find(tsidonid);
|
||||
if ( it != TransponderDefaultMapping.end() )
|
||||
table = it->second;
|
||||
|
||||
twochar = TransponderUseTwoCharMapping.find(tsidonid) != TransponderUseTwoCharMapping.end();
|
||||
}
|
||||
//printf("table %d tsidonid %04x twochar %d : %20s\n", table, tsidonid, twochar, data);
|
||||
switch(data[0])
|
||||
{
|
||||
case 1 ... 12:
|
||||
newtable=data[i++]+4;
|
||||
// eDebug("(1..12)text encoded in ISO-8859-%d",table);
|
||||
break;
|
||||
case 0x10:
|
||||
{
|
||||
// eDebug("(0x10)text encoded in ISO-8859-%d",n);
|
||||
int n=(data[i+1]<<8)|(data[i+2]);
|
||||
i += 3;
|
||||
switch(n)
|
||||
{
|
||||
case 12:
|
||||
{} //eDebug("unsup. ISO8859-12 enc.", n);
|
||||
default:
|
||||
newtable=n;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x11:// Basic Multilingual Plane of ISO/IEC 10646-1 enc (UTF-16... Unicode)
|
||||
table = 65;
|
||||
tsidonid = 0;
|
||||
++i;
|
||||
break;
|
||||
case 0x12:
|
||||
++i;
|
||||
{} //eDebug("unsup. KSC 5601 enc.");
|
||||
break;
|
||||
case 0x13:
|
||||
++i;
|
||||
{} //eDebug("unsup. GB-2312-1980 enc.");
|
||||
break;
|
||||
case 0x14:
|
||||
++i;
|
||||
{} //eDebug("unsup. Big5 subset of ISO/IEC 10646-1 enc.");
|
||||
break;
|
||||
case 0x0:
|
||||
case 0xD ... 0xF:
|
||||
case 0x15 ... 0x1F:
|
||||
{} //eDebug("reserved %d", data[0]);
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
//printf("convertDVBUTF8: table %d new table %d\n", table, newtable);
|
||||
if(!table)
|
||||
table = newtable;
|
||||
if(table == 64 && (newtable !=0 )){//for ISO6937
|
||||
table = newtable;
|
||||
}
|
||||
|
||||
//dprintf("recode:::: tsidonid %X table %d two-char %d len %d\n", tsidonid, table, twochar, len);
|
||||
unsigned char res[2048];
|
||||
while (i < len)
|
||||
{
|
||||
unsigned long code=0;
|
||||
|
||||
if ( i+1 < len && twochar && (code=doVideoTexSuppl(data[i], data[i+1])) ) {
|
||||
i+=2;
|
||||
//dprintf("recode:::: doVideoTexSuppl code %lX\n", code);
|
||||
}
|
||||
|
||||
if (!code) {
|
||||
if (table == 65) { // unicode
|
||||
if (i+1 < len) {
|
||||
code=(data[i] << 8) | data[i+1];
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
code=recode(data[i++], table);
|
||||
}
|
||||
if (!code)
|
||||
continue;
|
||||
// Unicode->UTF8 encoding
|
||||
if (code < 0x80) // identity ascii <-> utf8 mapping
|
||||
res[t++]=char(code);
|
||||
else if((table == 5) && (code == 0x8A))
|
||||
res[t++]= 0x20;
|
||||
else if ((code == 0x8A))
|
||||
res[t++]= '\n'; // 0x8a is vertical tab. Just use newline for now.
|
||||
else if((code >= 0x80) && (code <= 0x9F))
|
||||
continue;
|
||||
else if (code < 0x800) // two byte mapping
|
||||
{
|
||||
res[t++]=(code>>6)|0xC0;
|
||||
res[t++]=(code&0x3F)|0x80;
|
||||
} else if (code < 0x10000) // three bytes mapping
|
||||
{
|
||||
res[t++]=(code>>12)|0xE0;
|
||||
res[t++]=((code>>6)&0x3F)|0x80;
|
||||
res[t++]=(code&0x3F)|0x80;
|
||||
} else
|
||||
{
|
||||
res[t++]=(code>>18)|0xF0;
|
||||
res[t++]=((code>>12)&0x3F)|0x80;
|
||||
res[t++]=((code>>6)&0x3F)|0x80;
|
||||
res[t++]=(code&0x3F)|0x80;
|
||||
}
|
||||
if (t+4 > 2047)
|
||||
{
|
||||
{} //eDebug("convertDVBUTF8 buffer to small.. break now");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return std::string((char*)res, t);
|
||||
}
|
||||
#if 0
|
||||
eString convertUTF8DVB(const eString &string, int table)
|
||||
{
|
||||
unsigned long *coding_table=0;
|
||||
|
||||
int len=string.length(), t=0;
|
||||
|
||||
unsigned char buf[len];
|
||||
|
||||
for(int i=0; i<len; i++)
|
||||
{
|
||||
unsigned char c1=string[i];
|
||||
unsigned int c;
|
||||
if(c1<0x80)
|
||||
c=c1;
|
||||
else
|
||||
{
|
||||
i++;
|
||||
unsigned char c2=string[i];
|
||||
c=((c1&0x3F)<<6) + (c2&0x3F);
|
||||
if (table==0||table==1||c1<0xA0)
|
||||
;
|
||||
else
|
||||
{
|
||||
if (!coding_table)
|
||||
{
|
||||
switch(table)
|
||||
{
|
||||
case 2:
|
||||
coding_table = c88592;
|
||||
break;
|
||||
case 3:
|
||||
coding_table = c88593;
|
||||
break;
|
||||
case 4:
|
||||
coding_table = c88594;
|
||||
break;
|
||||
case 5:
|
||||
coding_table = c88595;
|
||||
break;
|
||||
case 6:
|
||||
coding_table = c88596;
|
||||
break;
|
||||
case 7:
|
||||
coding_table = c88597;
|
||||
break;
|
||||
case 8:
|
||||
coding_table = c88598;
|
||||
break;
|
||||
case 9:
|
||||
coding_table = c88599;
|
||||
break;
|
||||
case 10:
|
||||
coding_table = c885910;
|
||||
break;
|
||||
case 11:
|
||||
coding_table = c885911;
|
||||
break;
|
||||
/* case 12: // reserved.. for indian use
|
||||
coding_table = c885912;
|
||||
break;*/
|
||||
case 13:
|
||||
coding_table = c885913;
|
||||
break;
|
||||
case 14:
|
||||
coding_table = c885914;
|
||||
break;
|
||||
case 15:
|
||||
coding_table = c885915;
|
||||
break;
|
||||
case 16:
|
||||
coding_table = c885916;
|
||||
break;
|
||||
default:
|
||||
//eFatal("unknown coding table %d", table);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(unsigned int j=0; j<96; j++)
|
||||
{
|
||||
if(coding_table[j]==c)
|
||||
{
|
||||
c=0xA0+j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
buf[t++]=(unsigned char)c;
|
||||
}
|
||||
return eString((char*)buf,t);
|
||||
}
|
||||
#endif
|
||||
const std::string convertLatin1UTF8(const std::string &string)
|
||||
{
|
||||
unsigned int t=0, i=0, len=string.size();
|
||||
|
||||
unsigned char res[2048];
|
||||
|
||||
while (i < len)
|
||||
{
|
||||
unsigned long code=string[i++];
|
||||
// Unicode->UTF8 encoding
|
||||
if (code < 0x80) // identity latin <-> utf8 mapping
|
||||
res[t++]=char(code);
|
||||
else if (code < 0x800) // two byte mapping
|
||||
{
|
||||
res[t++]=(code>>6)|0xC0;
|
||||
res[t++]=(code&0x3F)|0x80;
|
||||
} else if (code < 0x10000) // three bytes mapping
|
||||
{
|
||||
res[t++]=(code>>12)|0xE0;
|
||||
res[t++]=((code>>6)&0x3F)|0x80;
|
||||
res[t++]=(code&0x3F)|0x80;
|
||||
} else
|
||||
{
|
||||
res[t++]=(code>>18)|0xF0;
|
||||
res[t++]=((code>>12)&0x3F)|0x80;
|
||||
res[t++]=((code>>6)&0x3F)|0x80;
|
||||
res[t++]=(code&0x3F)|0x80;
|
||||
}
|
||||
if (t+4 > 2047)
|
||||
{
|
||||
{} //eDebug("convertLatin1UTF8 buffer to small.. break now");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return std::string((char*)res, t);
|
||||
}
|
||||
|
||||
int isUTF8(const std::string &string)
|
||||
{
|
||||
unsigned int len=string.size();
|
||||
|
||||
for (unsigned int i=0; i < len; ++i)
|
||||
{
|
||||
if (!(string[i]&0x80)) // normal ASCII
|
||||
continue;
|
||||
if ((string[i] & 0xE0) == 0xC0) // one char following.
|
||||
{
|
||||
// first, length check:
|
||||
if (i+1 >= len)
|
||||
return 0; // certainly NOT utf-8
|
||||
i++;
|
||||
if ((string[i]&0xC0) != 0x80)
|
||||
return 0; // no, not UTF-8.
|
||||
} else if ((string[i] & 0xF0) == 0xE0)
|
||||
{
|
||||
if ((i+1) >= len)
|
||||
return 0;
|
||||
i++;
|
||||
if ((string[i]&0xC0) != 0x80)
|
||||
return 0;
|
||||
i++;
|
||||
if ((string[i]&0xC0) != 0x80)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1; // can be UTF8 (or pure ASCII, at least no non-UTF-8 8bit characters)
|
||||
}
|
||||
|
9640
src/eitd/sectionsd.cpp
Normal file
9640
src/eitd/sectionsd.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user