mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Fixed handling itemized texts in EPG data
This commit is contained in:
parent
e070d5462c
commit
823081b59e
@ -944,6 +944,7 @@ Thomas Bergwinkl <Thomas.Bergwinkl@t-online.de>
|
|||||||
Stéphane Esté-Gracias <sestegra@free.fr>
|
Stéphane Esté-Gracias <sestegra@free.fr>
|
||||||
for fixing a typo in libsi/si.h
|
for fixing a typo in libsi/si.h
|
||||||
for fixing some descriptor handling in 'libsi'
|
for fixing some descriptor handling in 'libsi'
|
||||||
|
for pointing out a problem with "itemized" texts in EPG data
|
||||||
|
|
||||||
Marc Hoppe <MarcHoppe@gmx.de>
|
Marc Hoppe <MarcHoppe@gmx.de>
|
||||||
for fixing handling the current menu item
|
for fixing handling the current menu item
|
||||||
|
2
HISTORY
2
HISTORY
@ -2725,3 +2725,5 @@ Video Disk Recorder Revision History
|
|||||||
- Fixed handling timers in VPS margin if the EPG scan is turned on (the EPG scan
|
- Fixed handling timers in VPS margin if the EPG scan is turned on (the EPG scan
|
||||||
switched the device away from the channel, so it wouldn't see the change of
|
switched the device away from the channel, so it wouldn't see the change of
|
||||||
the running status).
|
the running status).
|
||||||
|
- Fixed handling "itemized" texts in EPG data (thanks to Stéphane Esté-Gracias
|
||||||
|
for pointing out this problem, and Marcel Wiesweg for improving 'libsi').
|
||||||
|
4
eit.c
4
eit.c
@ -8,7 +8,7 @@
|
|||||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||||
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
|
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
|
||||||
*
|
*
|
||||||
* $Id: eit.c 1.90 2004/03/06 14:24:22 kls Exp $
|
* $Id: eit.c 1.91 2004/03/07 10:36:57 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eit.h"
|
#include "eit.h"
|
||||||
@ -191,7 +191,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
|
|||||||
}
|
}
|
||||||
if (ExtendedEventDescriptors) {
|
if (ExtendedEventDescriptors) {
|
||||||
char buffer[ExtendedEventDescriptors->getMaximumTextLength()];
|
char buffer[ExtendedEventDescriptors->getMaximumTextLength()];
|
||||||
pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer));
|
pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer, ": "));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete ExtendedEventDescriptors;
|
delete ExtendedEventDescriptors;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
* (at your option) any later version. *
|
* (at your option) any later version. *
|
||||||
* *
|
* *
|
||||||
* $Id: descriptor.c 1.7 2004/03/05 15:17:33 kls Exp $
|
* $Id: descriptor.c 1.8 2004/03/07 11:07:57 kls Exp $
|
||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
@ -60,13 +60,13 @@ void ExtendedEventDescriptor::Item::Parse() {
|
|||||||
item.setData(data+offset, mid->item_length);
|
item.setData(data+offset, mid->item_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExtendedEventDescriptors::getTextLength() {
|
/*int ExtendedEventDescriptors::getTextLength() {
|
||||||
int ret=0;
|
int ret=0;
|
||||||
for (int i=0;i<length;i++) {
|
for (int i=0;i<length;i++) {
|
||||||
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
||||||
if (!d)
|
if (!d)
|
||||||
continue;
|
continue;
|
||||||
ret+=d->text.getLength()+1; //plus a blank
|
ret+=d->text.getLength();
|
||||||
ExtendedEventDescriptor::Item item;
|
ExtendedEventDescriptor::Item item;
|
||||||
for (Loop::Iterator it; d->itemLoop.hasNext(it); ) {
|
for (Loop::Iterator it; d->itemLoop.hasNext(it); ) {
|
||||||
item=d->itemLoop.getNext(it);
|
item=d->itemLoop.getNext(it);
|
||||||
@ -76,28 +76,18 @@ int ExtendedEventDescriptors::getTextLength() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
//is there a case where this function does not return the same as getTextLength?
|
|
||||||
int ExtendedEventDescriptors::getMaximumTextLength() {
|
int ExtendedEventDescriptors::getMaximumTextLength() {
|
||||||
int ret=0;
|
return getMaximumTextPlainLength()+getMaximumTextItemizedLength();
|
||||||
for (int i=0;i<length;i++) {
|
|
||||||
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
|
||||||
if (!d)
|
|
||||||
continue;
|
|
||||||
ret+=d->text.getLength()+1; //plus a blank
|
|
||||||
ret+=d->itemLoop.getLength();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ExtendedEventDescriptors::getText() {
|
char *ExtendedEventDescriptors::getText(const char *separation1, const char *separation2) {
|
||||||
char *text=new char[getMaximumTextLength()];
|
char *text=new char[getMaximumTextLength()];
|
||||||
return getText(text);
|
return getText(text, separation1, separation2);
|
||||||
}
|
}
|
||||||
|
|
||||||
//appends the Strings of every Descriptor in the group
|
char *ExtendedEventDescriptors::getText(char *buffer, const char *separation1, const char *separation2) {
|
||||||
char *ExtendedEventDescriptors::getText(char *buffer) {
|
|
||||||
int index=0, len;
|
int index=0, len;
|
||||||
char tempbuf[256];
|
char tempbuf[256];
|
||||||
for (int i=0;i<length;i++) {
|
for (int i=0;i<length;i++) {
|
||||||
@ -110,30 +100,161 @@ char *ExtendedEventDescriptors::getText(char *buffer) {
|
|||||||
memcpy(buffer+index, tempbuf, len);
|
memcpy(buffer+index, tempbuf, len);
|
||||||
index+=len;
|
index+=len;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0;i<length;i++) {
|
||||||
|
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
||||||
|
if (!d)
|
||||||
|
continue;
|
||||||
|
|
||||||
ExtendedEventDescriptor::Item item;
|
ExtendedEventDescriptor::Item item;
|
||||||
for (Loop::Iterator it; d->itemLoop.hasNext(it); ) {
|
for (Loop::Iterator it; d->itemLoop.hasNext(it); ) {
|
||||||
item=d->itemLoop.getNext(it);
|
item=d->itemLoop.getNext(it);
|
||||||
|
|
||||||
item.item.getText(tempbuf);
|
|
||||||
len=strlen(tempbuf);
|
|
||||||
if (len) {
|
|
||||||
memcpy(buffer+index, tempbuf, len);
|
|
||||||
index+=len;
|
|
||||||
}
|
|
||||||
|
|
||||||
item.itemDescription.getText(tempbuf);
|
item.itemDescription.getText(tempbuf);
|
||||||
len=strlen(tempbuf);
|
len=strlen(tempbuf);
|
||||||
if (len) {
|
if (len) {
|
||||||
memcpy(buffer+index, tempbuf, len);
|
memcpy(buffer+index, tempbuf, len);
|
||||||
index+=len;
|
index+=len;
|
||||||
}
|
}
|
||||||
|
strcpy(buffer+index, separation1);
|
||||||
|
index += strlen(separation1);
|
||||||
|
|
||||||
|
item.item.getText(tempbuf);
|
||||||
|
len=strlen(tempbuf);
|
||||||
|
if (len) {
|
||||||
|
memcpy(buffer+index, tempbuf, len);
|
||||||
|
index+=len;
|
||||||
|
}
|
||||||
|
strcpy(buffer+index, separation2);
|
||||||
|
index += strlen(separation2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[index]='\0';
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExtendedEventDescriptors::getMaximumTextPlainLength() {
|
||||||
|
int ret=0;
|
||||||
|
for (int i=0;i<length;i++) {
|
||||||
|
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
||||||
|
if (!d)
|
||||||
|
continue;
|
||||||
|
ret+=d->text.getLength();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ExtendedEventDescriptors::getTextPlain() {
|
||||||
|
char *text=new char[getMaximumTextPlainLength()];
|
||||||
|
return getText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ExtendedEventDescriptors::getTextPlain(char *buffer) {
|
||||||
|
int index=0, len;
|
||||||
|
char tempbuf[256];
|
||||||
|
for (int i=0;i<length;i++) {
|
||||||
|
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
||||||
|
if (!d)
|
||||||
|
continue;
|
||||||
|
d->text.getText(tempbuf);
|
||||||
|
len=strlen(tempbuf);
|
||||||
|
if (len) {
|
||||||
|
memcpy(buffer+index, tempbuf, len);
|
||||||
|
index+=len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer[index]='\0';
|
buffer[index]='\0';
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ExtendedEventDescriptors::getMaximumTextItemizedLength() {
|
||||||
|
int ret=0;
|
||||||
|
for (int i=0;i<length;i++) {
|
||||||
|
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
||||||
|
if (!d)
|
||||||
|
continue;
|
||||||
|
//the size for the two separating characters is included ;-)
|
||||||
|
ret+=d->itemLoop.getLength();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ExtendedEventDescriptors::getTextItemized(const char *separation1, const char *separation2) {
|
||||||
|
char *text=new char[getMaximumTextItemizedLength()];
|
||||||
|
return getText(text, separation1, separation2);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ExtendedEventDescriptors::getTextItemized(char *buffer, const char *separation1, const char *separation2) {
|
||||||
|
int index=0, len;
|
||||||
|
char tempbuf[256];
|
||||||
|
for (int i=0;i<length;i++) {
|
||||||
|
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
||||||
|
if (!d)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ExtendedEventDescriptor::Item item;
|
||||||
|
for (Loop::Iterator it; d->itemLoop.hasNext(it); ) {
|
||||||
|
item=d->itemLoop.getNext(it);
|
||||||
|
|
||||||
|
item.itemDescription.getText(tempbuf);
|
||||||
|
len=strlen(tempbuf);
|
||||||
|
if (len) {
|
||||||
|
memcpy(buffer+index, tempbuf, len);
|
||||||
|
index+=len;
|
||||||
|
}
|
||||||
|
strcpy(buffer+index, separation1);
|
||||||
|
index += strlen(separation1);
|
||||||
|
|
||||||
|
item.item.getText(tempbuf);
|
||||||
|
len=strlen(tempbuf);
|
||||||
|
if (len) {
|
||||||
|
memcpy(buffer+index, tempbuf, len);
|
||||||
|
index+=len;
|
||||||
|
}
|
||||||
|
strcpy(buffer+index, separation2);
|
||||||
|
index += strlen(separation2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer[index]='\0';
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
//returns the itemized text pair by pair. Maximum length for buffers is 256.
|
||||||
|
//Return value is false if and only if the end of the list is reached.
|
||||||
|
bool ExtendedEventDescriptors::getTextItemized(Loop::Iterator &it, bool &valid, char *itemDescription, char *itemText) {
|
||||||
|
//The iterator has to store two values: The descriptor index (4bit)
|
||||||
|
//and the item loop index (max overall length 256, min item length 16 => max number 128 => 7bit)
|
||||||
|
valid=false;
|
||||||
|
|
||||||
|
int index=(it.i & 0x780) >> 7; // 0x780 == 1111 000 0000
|
||||||
|
it.i &= 0x7F; //0x7F == 111 1111
|
||||||
|
|
||||||
|
for (;index<length;index++) {
|
||||||
|
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[index];
|
||||||
|
if (!d)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ExtendedEventDescriptor::Item item;
|
||||||
|
if (d->itemLoop.hasNext(it)) {
|
||||||
|
item=d->itemLoop.getNext(it);
|
||||||
|
|
||||||
|
item.item.getText(itemDescription);
|
||||||
|
item.itemDescription.getText(itemText);
|
||||||
|
valid=true;
|
||||||
|
} else {
|
||||||
|
it.reset();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it.i &= 0x7F;
|
||||||
|
it.i |= (index & 0xF) << 7; //0xF == 1111
|
||||||
|
|
||||||
|
return index<length;
|
||||||
|
}
|
||||||
|
|
||||||
int TimeShiftedEventDescriptor::getReferenceServiceId() const {
|
int TimeShiftedEventDescriptor::getReferenceServiceId() const {
|
||||||
return HILO(s->reference_service_id);
|
return HILO(s->reference_service_id);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
* (at your option) any later version. *
|
* (at your option) any later version. *
|
||||||
* *
|
* *
|
||||||
* $Id: descriptor.h 1.6 2004/02/22 10:16:47 kls Exp $
|
* $Id: descriptor.h 1.7 2004/03/07 11:13:54 kls Exp $
|
||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
@ -50,14 +50,29 @@ private:
|
|||||||
|
|
||||||
class ExtendedEventDescriptors : public DescriptorGroup {
|
class ExtendedEventDescriptors : public DescriptorGroup {
|
||||||
public:
|
public:
|
||||||
//don't use
|
|
||||||
int getTextLength();
|
|
||||||
//really fast
|
|
||||||
int getMaximumTextLength();
|
int getMaximumTextLength();
|
||||||
|
//Returns a concatenated version of first the non-itemized and then the itemized text
|
||||||
//same semantics as with SI::String
|
//same semantics as with SI::String
|
||||||
char *getText();
|
char *getText(const char *separation1="\t", const char *separation2="\n");
|
||||||
//buffer must at least be getTextLength(), getMaximumTextLength() is a good choice
|
//buffer must at least be getTextLength(), getMaximumTextLength() is a good choice
|
||||||
char *getText(char *buffer);
|
char *getText(char *buffer, const char *separation1="\t", const char *separation2="\n");
|
||||||
|
|
||||||
|
//these only return the non-itemized text fields in concatenated form
|
||||||
|
int getMaximumTextPlainLength();
|
||||||
|
char *getTextPlain();
|
||||||
|
char *getTextPlain(char *buffer);
|
||||||
|
|
||||||
|
//these only return the itemized text fields in concatenated form.
|
||||||
|
//Between the description and the text the separation1 character is used,
|
||||||
|
//separation2 used between two pairs. Example:
|
||||||
|
//Director\tSteven Spielberg\nActor\tMichael Mendl\n
|
||||||
|
int getMaximumTextItemizedLength();
|
||||||
|
char *getTextItemized(const char *separation1="\t", const char *separation2="\n");
|
||||||
|
char *getTextItemized(char *buffer, const char *separation1="\t", const char *separation2="\n");
|
||||||
|
//returns the itemized text pair by pair. Maximum length for buffers is 256.
|
||||||
|
//Return value is false if and only if the end of the list is reached.
|
||||||
|
//The argument valid indicates whether the buffers contain valid content.
|
||||||
|
bool getTextItemized(Loop::Iterator &it, bool &valid, char *itemDescription, char *itemText);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TimeShiftedEventDescriptor : public Descriptor {
|
class TimeShiftedEventDescriptor : public Descriptor {
|
||||||
|
83
libsi/si.c
83
libsi/si.c
@ -6,7 +6,7 @@
|
|||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
* (at your option) any later version. *
|
* (at your option) any later version. *
|
||||||
* *
|
* *
|
||||||
* $Id: si.c 1.8 2004/02/22 10:14:12 kls Exp $
|
* $Id: si.c 1.9 2004/03/07 10:50:09 kls Exp $
|
||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ DescriptorTag Descriptor::getDescriptorTag(const unsigned char *d) {
|
|||||||
|
|
||||||
Descriptor *DescriptorLoop::getNext(Iterator &it) {
|
Descriptor *DescriptorLoop::getNext(Iterator &it) {
|
||||||
if (it.i<getLength()) {
|
if (it.i<getLength()) {
|
||||||
return createDescriptor(it.i);
|
return createDescriptor(it.i, true);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -115,19 +115,18 @@ Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag tag, bool return
|
|||||||
const unsigned char *end=p+getLength();
|
const unsigned char *end=p+getLength();
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
if (Descriptor::getDescriptorTag(p) == tag) {
|
if (Descriptor::getDescriptorTag(p) == tag) {
|
||||||
d=createDescriptor(it.i);
|
d=createDescriptor(it.i, returnUnimplemetedDescriptor);
|
||||||
|
if (d)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
it.i+=Descriptor::getLength(p);
|
it.i+=Descriptor::getLength(p);
|
||||||
p+=Descriptor::getLength(p);
|
p+=Descriptor::getLength(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (d && d->getDescriptorTag()==UnimplementedDescriptorTag)
|
|
||||||
return returnUnimplemetedDescriptor ? d : 0;
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor) {
|
Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplementedDescriptor) {
|
||||||
Descriptor *d=0;
|
Descriptor *d=0;
|
||||||
if (it.i<getLength()) {
|
if (it.i<getLength()) {
|
||||||
const unsigned char *p=data.getData(it.i);
|
const unsigned char *p=data.getData(it.i);
|
||||||
@ -135,27 +134,38 @@ Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int array
|
|||||||
while (p < end) {
|
while (p < end) {
|
||||||
for (int u=0; u<arrayLength;u++)
|
for (int u=0; u<arrayLength;u++)
|
||||||
if (Descriptor::getDescriptorTag(p) == tags[u]) {
|
if (Descriptor::getDescriptorTag(p) == tags[u]) {
|
||||||
d=createDescriptor(it.i);
|
d=createDescriptor(it.i, returnUnimplementedDescriptor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (d)
|
if (d)
|
||||||
break;
|
break; //length is added to it.i by createDescriptor, break here
|
||||||
it.i+=Descriptor::getLength(p);
|
it.i+=Descriptor::getLength(p);
|
||||||
p+=Descriptor::getLength(p);
|
p+=Descriptor::getLength(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (d && d->getDescriptorTag()==UnimplementedDescriptorTag)
|
|
||||||
return returnUnimplemetedDescriptor ? d : 0;
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Descriptor *DescriptorLoop::createDescriptor(int &i) {
|
Descriptor *DescriptorLoop::createDescriptor(int &i, bool returnUnimplemetedDescriptor) {
|
||||||
Descriptor *d=Descriptor::getDescriptor(data+i, domain);
|
Descriptor *d=Descriptor::getDescriptor(data+i, domain, returnUnimplemetedDescriptor);
|
||||||
|
if (!d)
|
||||||
|
return 0;
|
||||||
i+=d->getLength();
|
i+=d->getLength();
|
||||||
d->CheckParse();
|
d->CheckParse();
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DescriptorLoop::getNumberOfDescriptors() {
|
||||||
|
const unsigned char *p=data.getData();
|
||||||
|
const unsigned char *end=p+getLength();
|
||||||
|
int count=0;
|
||||||
|
while (p < end) {
|
||||||
|
count++;
|
||||||
|
p+=Descriptor::getLength(p);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
DescriptorGroup::DescriptorGroup(bool del) {
|
DescriptorGroup::DescriptorGroup(bool del) {
|
||||||
array=0;
|
array=0;
|
||||||
length=0;
|
length=0;
|
||||||
@ -211,6 +221,16 @@ char *String::getText(char *buffer) {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//taken from VDR, Copyright Klaus Schmidinger <kls@cadsoft.de>
|
||||||
|
char *String::getText(char *buffer, char *shortVersion) {
|
||||||
|
if (getLength() < 0 || getLength() >4095) {
|
||||||
|
strncpy(buffer, "text error", getLength()+1);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
decodeText(buffer, shortVersion);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
//taken from libdtv, Copyright Rolf Hakenes <hakenes@hippomi.de>
|
//taken from libdtv, Copyright Rolf Hakenes <hakenes@hippomi.de>
|
||||||
void String::decodeText(char *buffer) {
|
void String::decodeText(char *buffer) {
|
||||||
const unsigned char *from=data.getData(0);
|
const unsigned char *from=data.getData(0);
|
||||||
@ -228,18 +248,47 @@ void String::decodeText(char *buffer) {
|
|||||||
if ( ((' ' <= *from) && (*from <= '~'))
|
if ( ((' ' <= *from) && (*from <= '~'))
|
||||||
|| (*from == '\n')
|
|| (*from == '\n')
|
||||||
|| (0xA0 <= *from)
|
|| (0xA0 <= *from)
|
||||||
|
|| (*from == 0x86 || *from == 0x87)
|
||||||
)
|
)
|
||||||
*to++ = *from;
|
*to++ = *from;
|
||||||
else if (*from == 0x8A)
|
else if (*from == 0x8A)
|
||||||
*to++ = '\n';
|
*to++ = '\n';
|
||||||
else if (*from == 0x86 || *from == 0x87) //&& !(GDT_NAME_DESCRIPTOR & type))
|
|
||||||
*to++ = *from;
|
|
||||||
from++;
|
from++;
|
||||||
}
|
}
|
||||||
*to = '\0';
|
*to = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain) {
|
void String::decodeText(char *buffer, char *shortVersion) {
|
||||||
|
const unsigned char *from=data.getData(0);
|
||||||
|
char *to=buffer;
|
||||||
|
char *toShort=shortVersion;
|
||||||
|
int IsShortName=0;
|
||||||
|
|
||||||
|
for (int i = 0; i < getLength(); i++) {
|
||||||
|
if (*from == 0)
|
||||||
|
break;
|
||||||
|
if ( ((' ' <= *from) && (*from <= '~'))
|
||||||
|
|| (*from == '\n')
|
||||||
|
|| (0xA0 <= *from)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
*to++ = *from;
|
||||||
|
if (IsShortName)
|
||||||
|
*toShort++ = *from;
|
||||||
|
}
|
||||||
|
else if (*from == 0x8A)
|
||||||
|
*to++ = '\n';
|
||||||
|
else if (*from == 0x86)
|
||||||
|
IsShortName++;
|
||||||
|
else if (*from == 0x87)
|
||||||
|
IsShortName--;
|
||||||
|
from++;
|
||||||
|
}
|
||||||
|
*to = '\0';
|
||||||
|
*toShort = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor) {
|
||||||
Descriptor *d=0;
|
Descriptor *d=0;
|
||||||
switch (domain) {
|
switch (domain) {
|
||||||
case SI:
|
case SI:
|
||||||
@ -383,6 +432,8 @@ Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain)
|
|||||||
case AdaptationFieldDataDescriptorTag:
|
case AdaptationFieldDataDescriptorTag:
|
||||||
case TransportStreamDescriptorTag:
|
case TransportStreamDescriptorTag:
|
||||||
default:
|
default:
|
||||||
|
if (!returnUnimplemetedDescriptor)
|
||||||
|
return 0;
|
||||||
d=new UnimplementedDescriptor();
|
d=new UnimplementedDescriptor();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -417,6 +468,8 @@ Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain)
|
|||||||
case MHP_DelegatedApplicationDescriptorTag:
|
case MHP_DelegatedApplicationDescriptorTag:
|
||||||
case MHP_ApplicationStorageDescriptorTag:
|
case MHP_ApplicationStorageDescriptorTag:
|
||||||
default:
|
default:
|
||||||
|
if (!returnUnimplemetedDescriptor)
|
||||||
|
return 0;
|
||||||
d=new UnimplementedDescriptor();
|
d=new UnimplementedDescriptor();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
63
libsi/si.h
63
libsi/si.h
@ -6,7 +6,7 @@
|
|||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
* (at your option) any later version. *
|
* (at your option) any later version. *
|
||||||
* *
|
* *
|
||||||
* $Id: si.h 1.8 2004/02/23 17:02:33 kls Exp $
|
* $Id: si.h 1.9 2004/03/07 10:09:49 kls Exp $
|
||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
@ -252,8 +252,11 @@ protected:
|
|||||||
//returns a subclass of descriptor according to the data given.
|
//returns a subclass of descriptor according to the data given.
|
||||||
//The object is allocated with new and must be delete'd.
|
//The object is allocated with new and must be delete'd.
|
||||||
//setData() will have been called, CheckParse() not.
|
//setData() will have been called, CheckParse() not.
|
||||||
//Never returns null - maybe the UnimplementedDescriptor.
|
//if returnUnimplemetedDescriptor==true:
|
||||||
static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain);
|
// Never returns null - maybe the UnimplementedDescriptor.
|
||||||
|
//if returnUnimplemetedDescriptor==false:
|
||||||
|
// Never returns the UnimplementedDescriptor - maybe null
|
||||||
|
static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Loop : public VariableLengthPart {
|
class Loop : public VariableLengthPart {
|
||||||
@ -266,6 +269,7 @@ public:
|
|||||||
template <class T> friend class StructureLoop;
|
template <class T> friend class StructureLoop;
|
||||||
friend class DescriptorLoop;
|
friend class DescriptorLoop;
|
||||||
template <class T> friend class TypeLoop;
|
template <class T> friend class TypeLoop;
|
||||||
|
friend class ExtendedEventDescriptors;
|
||||||
int i;
|
int i;
|
||||||
};
|
};
|
||||||
protected:
|
protected:
|
||||||
@ -311,14 +315,46 @@ public:
|
|||||||
//returns null if no more descriptors available
|
//returns null if no more descriptors available
|
||||||
Descriptor *getNext(Iterator &it);
|
Descriptor *getNext(Iterator &it);
|
||||||
//return the next descriptor with given tag, or 0 if not available.
|
//return the next descriptor with given tag, or 0 if not available.
|
||||||
//if the descriptor found is not implemented,
|
//if returnUnimplemetedDescriptor==true:
|
||||||
// an UnimplementedDescriptor will be returned if returnUnimplemetedDescriptor==true,
|
// an UnimplementedDescriptor may be returned if the next matching descriptor is unimplemented,
|
||||||
// 0 will be returned if returnUnimplemetedDescriptor==false
|
// 0 will be returned if and only if no matching descriptor is found.
|
||||||
|
//if returnUnimplemetedDescriptor==false:
|
||||||
|
// if 0 is returned, either no descriptor with the given tag was found,
|
||||||
|
// or descriptors were found, but the descriptor type is not implemented
|
||||||
|
//In either case, a return value of 0 indicates that no further calls to this method
|
||||||
|
//with the iterator shall be made.
|
||||||
Descriptor *getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor=false);
|
Descriptor *getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor=false);
|
||||||
//return the next descriptor with one of the given tags, or 0 if not available.
|
//return the next descriptor with one of the given tags, or 0 if not available.
|
||||||
|
//if returnUnimplemetedDescriptor==true:
|
||||||
|
// returns 0 if and only if no descriptor with one of the given tags was found.
|
||||||
|
// The UnimplementedDescriptor may be returned.
|
||||||
|
//if returnUnimplemetedDescriptor==false:
|
||||||
|
// if 0 is returned, either no descriptor with one of the given tags was found,
|
||||||
|
// or descriptors were found, but none of them are implemented.
|
||||||
|
// The UnimplementedDescriptor will never be returned.
|
||||||
|
//In either case, a return value of 0 indicates that no further calls to this method
|
||||||
|
//with the iterator shall be made.
|
||||||
Descriptor *getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor=false);
|
Descriptor *getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor=false);
|
||||||
|
//returns the number of descriptors in this loop
|
||||||
|
int getNumberOfDescriptors();
|
||||||
|
//writes the tags of the descriptors in this loop in the array,
|
||||||
|
// which must at least have the size getNumberOfDescriptors().
|
||||||
|
//The number of descriptors, i.e. getNumberOfDescriptors(), is returned.
|
||||||
|
// You can specify the array type (Descriptor tags are 8 Bit,
|
||||||
|
// you might e.g. choose a char, short, int or DescriptorTag array)
|
||||||
|
template <typename T> int getDescriptorTags(T *tags)
|
||||||
|
{
|
||||||
|
const unsigned char *p=data.getData();
|
||||||
|
const unsigned char *end=p+getLength();
|
||||||
|
int count=0;
|
||||||
|
while (p < end) {
|
||||||
|
tags[count++]=(T)Descriptor::getDescriptorTag(p);
|
||||||
|
p+=Descriptor::getLength(p);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
Descriptor *createDescriptor(int &i);
|
Descriptor *createDescriptor(int &i, bool returnUnimplemetedDescriptor);
|
||||||
DescriptorTagDomain domain;
|
DescriptorTagDomain domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -385,7 +421,7 @@ class String : public VariableLengthPart {
|
|||||||
public:
|
public:
|
||||||
//A note to the length: getLength() returns the length of the raw data.
|
//A note to the length: getLength() returns the length of the raw data.
|
||||||
//The text may be shorter. Its length can be obtained with one of the
|
//The text may be shorter. Its length can be obtained with one of the
|
||||||
//above functions and strlen.
|
//getText functions and strlen.
|
||||||
|
|
||||||
//returns text. Data is allocated with new and must be delete'd by the user.
|
//returns text. Data is allocated with new and must be delete'd by the user.
|
||||||
char *getText();
|
char *getText();
|
||||||
@ -394,10 +430,19 @@ public:
|
|||||||
//In most descriptors the string length is an 8-bit field,
|
//In most descriptors the string length is an 8-bit field,
|
||||||
//so the maximum there is 256.
|
//so the maximum there is 256.
|
||||||
//returns the given buffer for convenience.
|
//returns the given buffer for convenience.
|
||||||
char * getText(char *buffer);
|
//The emphasis marks 0x86 and 0x87 are still available.
|
||||||
|
char *getText(char *buffer);
|
||||||
|
//The same semantics as for getText(char*) apply.
|
||||||
|
//The short version of the text according to ETSI TR 101 211 (chapter 4.6)
|
||||||
|
//will be written into the shortVersion buffer (which should, therefore, have the same
|
||||||
|
//length as buffer). If no shortVersion is available, shortVersion will contain
|
||||||
|
//an empty string.
|
||||||
|
//The emphasis marks 0x86 and 0x87 are still available in buffer, but not in shortVersion.
|
||||||
|
char *getText(char *buffer, char *shortVersion);
|
||||||
protected:
|
protected:
|
||||||
virtual void Parse() {}
|
virtual void Parse() {}
|
||||||
void decodeText(char *buffer);
|
void decodeText(char *buffer);
|
||||||
|
void decodeText(char *buffer, char *shortVersion);
|
||||||
};
|
};
|
||||||
|
|
||||||
} //end of namespace
|
} //end of namespace
|
||||||
|
27
sdt.c
27
sdt.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: sdt.c 1.7 2004/01/17 17:27:49 kls Exp $
|
* $Id: sdt.c 1.8 2004/03/07 10:46:08 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sdt.h"
|
#include "sdt.h"
|
||||||
@ -57,34 +57,17 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
|
|||||||
//XXX TODO case 0x04: // NVOD reference service
|
//XXX TODO case 0x04: // NVOD reference service
|
||||||
//XXX TODO case 0x05: // NVOD time-shifted service
|
//XXX TODO case 0x05: // NVOD time-shifted service
|
||||||
{
|
{
|
||||||
char buffer[1024];
|
|
||||||
char *p = sd->serviceName.getText(buffer);
|
|
||||||
char NameBuf[1024];
|
char NameBuf[1024];
|
||||||
char ShortNameBuf[1024];
|
char ShortNameBuf[1024];
|
||||||
char *pn = NameBuf;
|
sd->serviceName.getText(NameBuf, ShortNameBuf);
|
||||||
char *ps = ShortNameBuf;
|
char *pn = compactspace(NameBuf);
|
||||||
int IsShortName = 0;
|
char *ps = compactspace(ShortNameBuf);
|
||||||
while (*p) {
|
|
||||||
if ((uchar)*p == 0x86)
|
|
||||||
IsShortName++;
|
|
||||||
else if ((uchar)*p == 0x87)
|
|
||||||
IsShortName--;
|
|
||||||
else {
|
|
||||||
*pn++ = *p;
|
|
||||||
if (IsShortName)
|
|
||||||
*ps++ = *p;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
*pn = *ps = 0;
|
|
||||||
pn = NameBuf;
|
|
||||||
if (*NameBuf && *ShortNameBuf && strcmp(NameBuf, ShortNameBuf) != 0) {
|
if (*NameBuf && *ShortNameBuf && strcmp(NameBuf, ShortNameBuf) != 0) {
|
||||||
|
ps = ShortNameBuf + strlen(ShortNameBuf);
|
||||||
*ps++ = ',';
|
*ps++ = ',';
|
||||||
strcpy(ps, NameBuf);
|
strcpy(ps, NameBuf);
|
||||||
pn = ShortNameBuf;
|
pn = ShortNameBuf;
|
||||||
}
|
}
|
||||||
pn = compactspace(pn);
|
|
||||||
ps = compactspace(ps);
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
channel->SetId(sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
|
channel->SetId(sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
|
||||||
if (Setup.UpdateChannels >= 1)
|
if (Setup.UpdateChannels >= 1)
|
||||||
|
Loading…
Reference in New Issue
Block a user