Files
neutrino/lib/libtuxtxt/tuxtxt_common.h
vanhofen 14240c3c4a turn some comparsions for a better readability
Origin commit data
------------------
Commit: bee4cb4959
Author: vanhofen <vanhofen@gmx.de>
Date: 2024-03-25 (Mon, 25 Mar 2024)

Origin message was:
------------------
- turn some comparsions for a better readability

------------------
No further description and justification available within origin commit message!

------------------
This commit was generated by Migit
2024-03-27 07:12:41 +01:00

1139 lines
32 KiB
C

/* tuxtxt_common.h
* for license info see the other tuxtxt files
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#if TUXTXT_COMPRESS == 1
#include <zlib.h>
#endif
#include <hardware/dmx.h>
#include <system/set_threadname.h>
tuxtxt_cache_struct tuxtxt_cache;
static pthread_mutex_t tuxtxt_cache_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t tuxtxt_cache_biglock = PTHREAD_MUTEX_INITIALIZER;
int tuxtxt_get_zipsize(int p,int sp)
{
tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp];
if (!pg) return 0;
#if TUXTXT_COMPRESS == 1
return pg->ziplen;
#elif TUXTXT_COMPRESS == 2
pthread_mutex_lock(&tuxtxt_cache_lock);
int zipsize = 0,i,j;
for (i = 0; i < 23*5; i++)
for (j = 0; j < 8; j++)
zipsize += pg->bitmask[i]>>j & 0x01;
zipsize+=23*5;//bitmask
pthread_mutex_unlock(&tuxtxt_cache_lock);
return zipsize;
#else
return 23*40;
#endif
}
void tuxtxt_compress_page(int p, int sp, unsigned char* buffer)
{
pthread_mutex_lock(&tuxtxt_cache_lock);
tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp];
if (!pg)
{
printf("tuxtxt: trying to compress a not allocated page!!\n");
pthread_mutex_unlock(&tuxtxt_cache_lock);
return;
}
#if TUXTXT_COMPRESS == 1
unsigned char pagecompressed[23*40];
uLongf comprlen = 23*40;
if (compress2(pagecompressed,&comprlen,buffer,23*40,Z_BEST_SPEED) == Z_OK)
{
if (pg->pData) free(pg->pData);//realloc(pg->pData,j); realloc scheint nicht richtig zu funktionieren?
pg->pData = malloc(comprlen);
pg->ziplen = 0;
if (pg->pData)
{
pg->ziplen = comprlen;
memmove(pg->pData,pagecompressed,comprlen);
}
}
#elif TUXTXT_COMPRESS == 2
int i,j=0;
unsigned char cbuf[23*40];
memset(pg->bitmask,0,sizeof(pg->bitmask));
for (i = 0; i < 23*40; i++)
{
if (i && buffer[i] == buffer[i-1])
continue;
pg->bitmask[i>>3] |= 0x80>>(i&0x07);
cbuf[j++]=buffer[i];
}
if (pg->pData)
free(pg->pData);//realloc(pg->pData,j); realloc scheint nicht richtig zu funktionieren?
pg->pData = (unsigned char*)malloc(j);
if (pg->pData)
{
memmove(pg->pData,cbuf,j);
}
else
memset(pg->bitmask,0,sizeof(pg->bitmask));
#else
//if (pg->pData)
memmove(pg->data,buffer,23*40);
#endif
pthread_mutex_unlock(&tuxtxt_cache_lock);
}
void tuxtxt_decompress_page(int p, int sp, unsigned char* buffer)
{
pthread_mutex_lock(&tuxtxt_cache_lock);
tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp];
memset(buffer,' ',23*40);
if (!pg)
{
printf("tuxtxt: trying to decompress a not allocated page!!\n");
pthread_mutex_unlock(&tuxtxt_cache_lock);
return;
}
#if TUXTXT_COMPRESS == 1
if (pg->pData)
{
if (pg->ziplen)
{
uLongf comprlen = 23*40;
uncompress(buffer,&comprlen,pg->pData,pg->ziplen);
}
#elif TUXTXT_COMPRESS == 2
if (pg->pData)
{
int i,j=0;
char c=0x20;
for (i = 0; i < 23*40; i++)
{
if (pg->bitmask[i>>3] & 0x80>>(i&0x07))
c = pg->pData[j++];
buffer[i] = c;
}
#else
{
memmove(buffer,pg->data,23*40);
#endif
}
pthread_mutex_unlock(&tuxtxt_cache_lock);
}
void tuxtxt_next_dec(int *i) /* skip to next decimal */
{
(*i)++;
if ((*i & 0x0F) > 0x09)
*i += 0x06;
if ((*i & 0xF0) > 0x90)
*i += 0x60;
if (*i > 0x899)
*i = 0x100;
}
void tuxtxt_prev_dec(int *i) /* counting down */
{
(*i)--;
if ((*i & 0x0F) > 0x09)
*i -= 0x06;
if ((*i & 0xF0) > 0x90)
*i -= 0x60;
if (*i < 0x100)
*i = 0x899;
}
int tuxtxt_is_dec(int i)
{
return ((i & 0x00F) <= 9) && ((i & 0x0F0) <= 0x90);
}
int tuxtxt_next_hex(int i) /* return next existing non-decimal page number */
{
int startpage = i;
if (startpage < 0x100)
startpage = 0x100;
do
{
i++;
if (i > 0x8FF)
i = 0x100;
if (i == startpage)
break;
} while ((tuxtxt_cache.subpagetable[i] == 0xFF) || tuxtxt_is_dec(i));
return i;
}
/*
* TOP-Text
* Info entnommen aus videotext-0.6.19991029,
* Copyright (c) 1994-96 Martin Buck <martin-2.buck@student.uni-ulm.de>
*/
void tuxtxt_decode_btt()
{
/* basic top table */
int i, current, b1, b2, b3, b4;
unsigned char btt[23*40] = {0};
if (tuxtxt_cache.subpagetable[0x1f0] == 0xff || tuxtxt_cache.astCachetable[0x1f0][tuxtxt_cache.subpagetable[0x1f0]] == 0) /* not yet received */
return;
tuxtxt_decompress_page(0x1f0,tuxtxt_cache.subpagetable[0x1f0],btt);
if (btt[799] == ' ') /* not completely received or error */
return;
current = 0x100;
for (i = 0; i < 800; i++)
{
b1 = btt[i];
if (b1 == ' ')
b1 = 0;
else
{
b1 = dehamming[b1];
if (b1 == 0xFF) /* hamming error in btt */
{
btt[799] = ' '; /* mark btt as not received */
return;
}
}
tuxtxt_cache.basictop[current] = b1;
tuxtxt_next_dec(&current);
}
/* page linking table */
tuxtxt_cache.maxadippg = -1; /* rebuild table of adip pages */
for (i = 0; i < 10; i++)
{
b1 = dehamming[btt[800 + 8*i +0]];
if (b1 == 0xE)
continue; /* unused */
else if (b1 == 0xF)
break; /* end */
b4 = dehamming[btt[800 + 8*i +7]];
if (b4 != 2) /* only adip, ignore multipage (1) */
continue;
b2 = dehamming[btt[800 + 8*i +1]];
b3 = dehamming[btt[800 + 8*i +2]];
if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF)
{
printf("TuxTxt <Biterror in btt/plt index %d>\n", i);
btt[799] = ' '; /* mark btt as not received */
return;
}
b1 = b1<<8 | b2<<4 | b3; /* page number */
tuxtxt_cache.adippg[++tuxtxt_cache.maxadippg] = b1;
}
#if TUXTXT_DEBUG
printf("TuxTxt <BTT decoded>\n");
#endif
tuxtxt_cache.bttok = 1;
}
void tuxtxt_decode_adip() /* additional information table */
{
int i, p, j, b1, b2, b3, charfound;
unsigned char padip[23*40];
for (i = 0; i <= tuxtxt_cache.maxadippg; i++)
{
p = tuxtxt_cache.adippg[i];
if (!p || tuxtxt_cache.subpagetable[p] == 0xff || tuxtxt_cache.astCachetable[p][tuxtxt_cache.subpagetable[p]] == 0) /* not cached (avoid segfault) */
continue;
tuxtxt_decompress_page(p,tuxtxt_cache.subpagetable[p],padip);
for (j = 0; j < 44; j++)
{
b1 = dehamming[padip[20*j+0]];
if (b1 == 0xE)
continue; /* unused */
if (b1 == 0xF)
break; /* end */
b2 = dehamming[padip[20*j+1]];
b3 = dehamming[padip[20*j+2]];
if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF)
{
printf("TuxTxt <Biterror in ait %03x %d %02x %02x %02x %02x %02x %02x>\n", p, j,
padip[20*j+0],
padip[20*j+1],
padip[20*j+2],
b1, b2, b3
);
return;
}
if (b1>8 || b2>9 || b3>9) /* ignore extries with invalid or hex page numbers */
{
continue;
}
b1 = b1<<8 | b2<<4 | b3; /* page number */
charfound = 0; /* flag: no printable char found */
for (b2 = 11; b2 >= 0; b2--)
{
b3 = deparity[padip[20*j + 8 + b2]];
if (b3 < ' ')
b3 = ' ';
if (b3 == ' ' && !charfound)
tuxtxt_cache.adip[b1][b2] = '\0';
else
{
tuxtxt_cache.adip[b1][b2] = b3;
charfound = 1;
}
}
} /* next link j */
tuxtxt_cache.adippg[i] = 0; /* completely decoded: clear entry */
#if TUXTXT_DEBUG
printf("TuxTxt <ADIP %03x decoded>\n", p);
#endif
} /* next adip page i */
while ((tuxtxt_cache.maxadippg >= 0) && !tuxtxt_cache.adippg[tuxtxt_cache.maxadippg]) /* and shrink table */
tuxtxt_cache.maxadippg--;
}
/******************************************************************************
* GetSubPage *
******************************************************************************/
int tuxtxt_GetSubPage(int page, int subpage, int offset)
{
int loop;
for (loop = subpage + offset; loop != subpage; loop += offset)
{
if (loop < 0)
loop = 0x79;
else if (loop > 0x79)
loop = 0;
if (loop == subpage)
break;
if (tuxtxt_cache.astCachetable[page][loop])
{
#if TUXTXT_DEBUG
printf("TuxTxt <NextSubPage: %.3X-%.2X>\n", page, subpage);
#endif
return loop;
}
}
#if TUXTXT_DEBUG
printf("TuxTxt <NextSubPage: no other SubPage>\n");
#endif
return subpage;
}
/******************************************************************************
* clear_cache *
******************************************************************************/
void tuxtxt_clear_cache(void)
{
pthread_mutex_lock(&tuxtxt_cache_biglock);
pthread_mutex_lock(&tuxtxt_cache_lock);
int clear_page, clear_subpage, d26;
tuxtxt_cache.maxadippg = -1;
tuxtxt_cache.bttok = 0;
tuxtxt_cache.cached_pages = 0;
tuxtxt_cache.page_receiving = -1;
tuxtxt_cache.vtxtpid = -1;
memset(&tuxtxt_cache.subpagetable, 0xFF, sizeof(tuxtxt_cache.subpagetable));
memset(&tuxtxt_cache.basictop, 0, sizeof(tuxtxt_cache.basictop));
memset(&tuxtxt_cache.adip, 0, sizeof(tuxtxt_cache.adip));
memset(&tuxtxt_cache.flofpages, 0 , sizeof(tuxtxt_cache.flofpages));
memset(&tuxtxt_cache.timestring, 0x20, 8);
unsigned char magazine;
for (magazine = 1; magazine < 9; magazine++)
{
tuxtxt_cache.current_page [magazine] = -1;
tuxtxt_cache.current_subpage [magazine] = -1;
}
for (clear_page = 0; clear_page < 0x900; clear_page++)
for (clear_subpage = 0; clear_subpage < 0x80; clear_subpage++)
if (tuxtxt_cache.astCachetable[clear_page][clear_subpage])
{
tstPageinfo *p = &(tuxtxt_cache.astCachetable[clear_page][clear_subpage]->pageinfo);
if (p->p24)
free(p->p24);
if (p->ext)
{
if (p->ext->p27)
free(p->ext->p27);
for (d26=0; d26 < 16; d26++)
if (p->ext->p26[d26])
free(p->ext->p26[d26]);
free(p->ext);
}
#if TUXTXT_COMPRESS >0
if (tuxtxt_cache.astCachetable[clear_page][clear_subpage]->pData)
free(tuxtxt_cache.astCachetable[clear_page][clear_subpage]->pData);
#endif
free(tuxtxt_cache.astCachetable[clear_page][clear_subpage]);
tuxtxt_cache.astCachetable[clear_page][clear_subpage] = 0;
}
for (clear_page = 0; clear_page < 9; clear_page++)
{
if (tuxtxt_cache.astP29[clear_page])
{
if (tuxtxt_cache.astP29[clear_page]->p27)
free(tuxtxt_cache.astP29[clear_page]->p27);
for (d26=0; d26 < 16; d26++)
if (tuxtxt_cache.astP29[clear_page]->p26[d26])
free(tuxtxt_cache.astP29[clear_page]->p26[d26]);
free(tuxtxt_cache.astP29[clear_page]);
tuxtxt_cache.astP29[clear_page] = 0;
}
tuxtxt_cache.current_page [clear_page] = -1;
tuxtxt_cache.current_subpage [clear_page] = -1;
}
memset(&tuxtxt_cache.astCachetable, 0, sizeof(tuxtxt_cache.astCachetable));
memset(&tuxtxt_cache.astP29, 0, sizeof(tuxtxt_cache.astP29));
#if TUXTXT_DEBUG
printf("TuxTxt cache cleared\n");
#endif
pthread_mutex_unlock(&tuxtxt_cache_lock);
pthread_mutex_unlock(&tuxtxt_cache_biglock);
}
/******************************************************************************
* init_demuxer *
******************************************************************************/
static cDemux * dmx = NULL;
int tuxtxt_init_demuxer(int source = 0);
int tuxtxt_init_demuxer(int source)
{
if(dmx == NULL) {
dmx = new cDemux(source);
dmx->Open(DMX_PES_CHANNEL, NULL, 2* 3008 * 62 /*64*1024*/);
printf("TuxTxt: source demux %d\n", source);
}
#if TUXTXT_DEBUG
printf("TuxTxt: initialized\n");
#endif
/* init successfull */
return 1;
}
/******************************************************************************
* CacheThread support functions *
******************************************************************************/
void tuxtxt_decode_p2829(unsigned char *vtxt_row, tstExtData **ptExtData)
{
int bitsleft, colorindex;
unsigned char *p;
int t1 = deh24(&vtxt_row[7-4]);
int t2 = deh24(&vtxt_row[10-4]);
if (t1 < 0 || t2 < 0)
{
#if TUXTXT_DEBUG
printf("TuxTxt <Biterror in p28>\n");
#endif
return;
}
if (!(*ptExtData))
(*ptExtData) = (tstExtData*)calloc(1, sizeof(tstExtData));
if (!(*ptExtData))
return;
(*ptExtData)->p28Received = 1;
(*ptExtData)->DefaultCharset = (t1>>7) & 0x7f;
(*ptExtData)->SecondCharset = ((t1>>14) & 0x0f) | ((t2<<4) & 0x70);
(*ptExtData)->LSP = !!(t2 & 0x08);
(*ptExtData)->RSP = !!(t2 & 0x10);
(*ptExtData)->SPL25 = !!(t2 & 0x20);
(*ptExtData)->LSPColumns = (t2>>6) & 0x0f;
bitsleft = 8; /* # of bits not evaluated in val */
t2 >>= 10; /* current data */
p = &vtxt_row[13-4]; /* pointer to next data triplet */
for (colorindex = 0; colorindex < 16; colorindex++)
{
if (bitsleft < 12)
{
t2 |= deh24(p) << bitsleft;
if (t2 < 0) /* hamming error */
break;
p += 3;
bitsleft += 18;
}
(*ptExtData)->bgr[colorindex] = t2 & 0x0fff;
bitsleft -= 12;
t2 >>= 12;
}
if (t2 < 0 || bitsleft != 14)
{
#if TUXTXT_DEBUG
printf("TuxTxt <Biterror in p28/29 t2=%d b=%d>\n", t2, bitsleft);
#endif
(*ptExtData)->p28Received = 0;
return;
}
(*ptExtData)->DefScreenColor = t2 & 0x1f;
t2 >>= 5;
(*ptExtData)->DefRowColor = t2 & 0x1f;
(*ptExtData)->BlackBgSubst = !!(t2 & 0x20);
t2 >>= 6;
(*ptExtData)->ColorTableRemapping = t2 & 0x07;
}
void tuxtxt_erase_page(int magazine)
{
tstCachedPage* pg = tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]];
if (pg)
{
memset(&(pg->pageinfo), 0, sizeof(tstPageinfo)); /* struct pageinfo */
memset(pg->p0, ' ', 24);
#if TUXTXT_COMPRESS == 1
if (pg->pData) {
free(pg->pData);
pg->pData = NULL;
}
#elif TUXTXT_COMPRESS == 2
memset(pg->bitmask, 0, 23*5);
#else
memset(pg->data, ' ', 23*40);
#endif
}
}
void tuxtxt_clear_p26(tstExtData* extData)
{
pthread_mutex_lock(&tuxtxt_cache_lock);
for(int i = 0; i < 16; ++i)
{
if(extData->p26[i] != 0)
{
memset(extData->p26[i], 0x00, 13 * 3);
}
}
pthread_mutex_unlock(&tuxtxt_cache_lock);
}
void tuxtxt_allocate_cache(int magazine)
{
// Lock here as we have a possible race here with
// tuxtxt_clear_cache(). We should not be allocating and
// freeing at the same time.
// *** this is probably worked around by tuxtxt_cacehe_biglock now *** --seife
pthread_mutex_lock(&tuxtxt_cache_lock);
/* check cachetable and allocate memory if needed */
if (tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]] == 0)
{
tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]] = (tstCachedPage*) malloc(sizeof(tstCachedPage));
if (tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]] )
{
#if TUXTXT_COMPRESS >0
tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->pData = 0;
#endif
tuxtxt_erase_page(magazine);
tuxtxt_cache.cached_pages++;
}
else // Be a little verbose in case a crash is going to happen.
{
printf("tuxtxt: memory allocation failed!!! expect a crash\n");
}
}
pthread_mutex_unlock(&tuxtxt_cache_lock);
}
/******************************************************************************
* CacheThread *
******************************************************************************/
static int stop_cache = 0;
void *tuxtxt_CacheThread(void * /*arg*/)
{
const unsigned char rev_lut[32] = {
0x00,0x08,0x04,0x0c, /* upper nibble */
0x02,0x0a,0x06,0x0e,
0x01,0x09,0x05,0x0d,
0x03,0x0b,0x07,0x0f,
0x00,0x80,0x40,0xc0, /* lower nibble */
0x20,0xa0,0x60,0xe0,
0x10,0x90,0x50,0xd0,
0x30,0xb0,0x70,0xf0 };
unsigned char pes_packet[184*20];
unsigned char vtxt_row[42];
int line, byte/*, bit*/;
int b1, b2, b3, b4;
int packet_number;
int doupdate=0;
unsigned char magazine = 0xff;
unsigned char pagedata[9][23*40];
tstPageinfo *pageinfo_thread;
set_threadname("tuxtxt:cache");
int err = nice(3);
printf("TuxTxt running thread...(%04x)%s\n",tuxtxt_cache.vtxtpid,err!=0?" nice error":"");
tuxtxt_cache.receiving = 1;
while (!stop_cache)
{
/* check stopsignal */
pthread_testcancel();
if (!tuxtxt_cache.receiving)
continue;
/* read packet */
ssize_t readcnt = 0;
readcnt = dmx->Read(pes_packet, sizeof (pes_packet), 1000);
//if (readcnt != sizeof(pes_packet))
if ((readcnt <= 0) || (readcnt % 184))
{
#if TUXTXT_DEBUG
if(readcnt > 0)
printf ("TuxTxt: readerror: %d\n", readcnt);
#endif
continue;
}
/* this "big hammer lock" is a hack: it avoids a crash if
* tuxtxt_clear_cache() is called while the cache thread is in the
* middle of the following loop, leading to tuxtxt_cache.current_page[]
* etc. being set to -1 and tuxtxt_cache.astCachetable[] etc. being set
* to NULL
* it probably also avoids the possible race in tuxtxt_allocate_cache() */
pthread_mutex_lock(&tuxtxt_cache_biglock);
/* analyze it */
for (line = 0; line < readcnt/0x2e /*4*/; line++)
{
unsigned char *vtx_rowbyte = &pes_packet[line*0x2e];
if ((vtx_rowbyte[1] == 0x2C) && (vtx_rowbyte[0] == 0x02 || vtx_rowbyte[0] == 0x03))
{
/* clear rowbuffer */
/* convert row from lsb to msb (begin with magazin number) */
for (byte = 4; byte < 46; byte++)
{
unsigned char upper,lower;
upper = (vtx_rowbyte[byte] >> 4) & 0xf;
lower = vtx_rowbyte[byte] & 0xf;
vtxt_row[byte-4] = (rev_lut[upper]) | (rev_lut[lower+16]);
}
/* get packet number */
b1 = dehamming[vtxt_row[0]];
b2 = dehamming[vtxt_row[1]];
if (b1 == 0xFF || b2 == 0xFF)
{
#if TUXTXT_DEBUG
printf("TuxTxt <Biterror in Packet>\n");
#endif
continue;
}
b1 &= 8;
packet_number = b1>>3 | b2<<1;
/* get magazine number */
magazine = dehamming[vtxt_row[0]] & 7;
if (!magazine) magazine = 8;
if (packet_number == 0 && tuxtxt_cache.current_page[magazine] != -1 && tuxtxt_cache.current_subpage[magazine] != -1)
tuxtxt_compress_page(tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine],pagedata[magazine]);
//printf("********************** receiving packet %d page %03x subpage %02x\n",packet_number, tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine]);//FIXME
/* analyze row */
if (packet_number == 0)
{
/* get pagenumber */
b2 = dehamming[vtxt_row[3]];
b3 = dehamming[vtxt_row[2]];
if (b2 == 0xFF || b3 == 0xFF)
{
tuxtxt_cache.current_page[magazine] = tuxtxt_cache.page_receiving = -1;
#if TUXTXT_DEBUG
printf("TuxTxt <Biterror in Page>\n");
#endif
continue;
}
tuxtxt_cache.current_page[magazine] = tuxtxt_cache.page_receiving = magazine<<8 | b2<<4 | b3;
if (b2 == 0x0f && b3 == 0x0f)
{
tuxtxt_cache.current_subpage[magazine] = -1; /* ?ff: ignore data transmissions */
continue;
}
/* get subpagenumber */
b1 = dehamming[vtxt_row[7]];
b2 = dehamming[vtxt_row[6]];
b3 = dehamming[vtxt_row[5]];
b4 = dehamming[vtxt_row[4]];
if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF || b4 == 0xFF)
{
#if TUXTXT_DEBUG
printf("TuxTxt <Biterror in SubPage>\n");
#endif
tuxtxt_cache.current_subpage[magazine] = -1;
continue;
}
#if 0 /* ? */
b1 &= 3;
#endif
b3 &= 7;
if (tuxtxt_is_dec(tuxtxt_cache.page_receiving)) /* ignore other subpage bits for hex pages */
{
#if 0 /* ? */
if (b1 != 0 || b2 != 0)
{
#if TUXTXT_DEBUG
printf("TuxTxt <invalid subpage data p%03x %02x %02x %02x %02x>\n", tuxtxt_cache.page_receiving, b1, b2, b3, b4);
#endif
tuxtxt_cache.current_subpage[magazine] = -1;
continue;
}
else
#endif
tuxtxt_cache.current_subpage[magazine] = b3<<4 | b4;
}
else
tuxtxt_cache.current_subpage[magazine] = b4; /* max 16 subpages for hex pages */
/* store current subpage for this page */
tuxtxt_cache.subpagetable[tuxtxt_cache.current_page[magazine]] = tuxtxt_cache.current_subpage[magazine];
tuxtxt_allocate_cache(magazine);
tuxtxt_decompress_page(tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine],pagedata[magazine]);
pageinfo_thread = &(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->pageinfo);
if ((tuxtxt_cache.page_receiving & 0xff) == 0xfe) /* ?fe: magazine organization table (MOT) */
pageinfo_thread->function = FUNC_MOT;
/* check controlbits */
if (dehamming[vtxt_row[5]] & 8) /* C4 -> erase page */
{
#if TUXTXT_COMPRESS == 1
tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->ziplen = 0;
#elif TUXTXT_COMPRESS == 2
memset(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->bitmask, 0, 23*5);
#else
memset(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->data, ' ', 23*40);
#endif
memset(pagedata[magazine],' ', 23*40);
}
if (dehamming[vtxt_row[9]] & 8) /* C8 -> update page */
doupdate = tuxtxt_cache.page_receiving;
pageinfo_thread->boxed = !!(dehamming[vtxt_row[7]] & 0x0c);
/* get country control bits */
b1 = dehamming[vtxt_row[9]];
if (b1 == 0xFF)
{
#if TUXTXT_DEBUG
printf("TuxTxt <Biterror in CountryFlags>\n");
#endif
}
else
{
//pageinfo_thread->nationalvalid = 1;// FIXME without full eval some is broken
pageinfo_thread->national = rev_lut[b1] & 0x07;
//printf("TuxTxt 0: b1=%x\n", rev_lut[b1]);
}
/* check parity, copy line 0 to cache (start and end 8 bytes are not needed and used otherwise) */
unsigned char *p = tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->p0;
for (byte = 10; byte < 42-8; byte++)
*p++ = deparity[vtxt_row[byte]];
if (!tuxtxt_is_dec(tuxtxt_cache.page_receiving))
continue; /* valid hex page number: just copy headline, ignore timestring */
/* copy timestring */
p = tuxtxt_cache.timestring;
for (; byte < 42; byte++)
*p++ = deparity[vtxt_row[byte]];
} /* (packet_number == 0) */
else if (packet_number == 29 && dehamming[vtxt_row[2]]== 0) /* packet 29/0 replaces 28/0 for a whole magazine */
{
tuxtxt_decode_p2829(vtxt_row, &(tuxtxt_cache.astP29[magazine]));
}
else if (tuxtxt_cache.current_page[magazine] != -1 && tuxtxt_cache.current_subpage[magazine] != -1)
/* packet>0, 0 has been correctly received, buffer allocated */
{
pageinfo_thread = &(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->pageinfo);
/* pointer to current info struct */
if (packet_number <= 25)
{
unsigned char *p = NULL;
if (packet_number < 24)
p = pagedata[magazine] + 40*(packet_number-1);
else
{
if (!(pageinfo_thread->p24))
pageinfo_thread->p24 = (unsigned char*) calloc(2, 40);
if (pageinfo_thread->p24)
p = pageinfo_thread->p24 + (packet_number - 24) * 40;
}
if (p)
{
if (tuxtxt_is_dec(tuxtxt_cache.current_page[magazine]))
for (byte = 2; byte < 42; byte++)
*p++ = deparity[vtxt_row[byte]]; /* check/remove parity bit */
else if ((tuxtxt_cache.current_page[magazine] & 0xff) == 0xfe)
for (byte = 2; byte < 42; byte++)
*p++ = dehamming[vtxt_row[byte]]; /* decode hamming 8/4 */
else /* other hex page: no parity check, just copy */
memmove(p, &vtxt_row[2], 40);
}
}
else if (packet_number == 27)
{
int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */
if (descode == 0xff)
{
#if TUXTXT_DEBUG
printf("TuxTxt <Biterror in p27>\n");
#endif
continue;
}
if (descode == 0) // reading FLOF-Pagelinks
{
b1 = dehamming[vtxt_row[0]];
if (b1 != 0xff)
{
b1 &= 7;
for (byte = 0; byte < FLOFSIZE; byte++)
{
b2 = dehamming[vtxt_row[4+byte*6]];
b3 = dehamming[vtxt_row[3+byte*6]];
if (b2 != 0xff && b3 != 0xff)
{
b4 = ((b1 ^ (dehamming[vtxt_row[8+byte*6]]>>1)) & 6) |
((b1 ^ (dehamming[vtxt_row[6+byte*6]]>>3)) & 1);
if (b4 == 0)
b4 = 8;
if (b2 <= 9 && b3 <= 9)
tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine] ][byte] = b4<<8 | b2<<4 | b3;
}
}
/* copy last 2 links to adip for TOP-Index */
if (pageinfo_thread->p24) /* packet 24 received */
{
int a, a1, e=39, l=3;
char *p = (char*) pageinfo_thread->p24;
do
{
for (;
l >= 2 && tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l] == 0;
l--)
; /* find used linkindex */
for (;
e >= 1 && !isalnum(p[e]);
e--)
; /* find end */
for (a = a1 = e - 1;
a >= 0 && p[a] >= ' ';
a--) /* find start */
if (p[a] > ' ')
a1 = a; /* first non-space */
if (a >= 0 && l >= 2)
{
strncpy((char *) tuxtxt_cache.adip[tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]],
&p[a1],
12);
if (e-a1 < 11)
tuxtxt_cache.adip[tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]][e-a1+1] = '\0';
#if 0 //TUXTXT_DEBUG
printf(" %03x/%02x %d %d %d %d %03x %s\n",
tuxtxt_cache.current_page[magazine], tuxtxt_cache.current_subpage[magazine],
l, a, a1, e,
tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l],
tuxtxt_cache.adip[tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]]
);
#endif
}
e = a - 1;
l--;
} while (l >= 2);
}
}
}
else if (descode == 4) /* level 2.5 links (ignore level 3.5 links of /4 and /5) */
{
int i;
tstp27 *p;
if (!pageinfo_thread->ext)
pageinfo_thread->ext = (tstExtData*) calloc(1, sizeof(tstExtData));
if (!pageinfo_thread->ext)
continue;
if (!(pageinfo_thread->ext->p27))
pageinfo_thread->ext->p27 = (tstp27*) calloc(4, sizeof(tstp27));
if (!(pageinfo_thread->ext->p27))
continue;
p = pageinfo_thread->ext->p27;
for (i = 0; i < 4; i++)
{
int d1 = deh24(&vtxt_row[6*i + 3]);
int d2 = deh24(&vtxt_row[6*i + 6]);
if (d1 < 0 || d2 < 0)
{
#if TUXTXT_DEBUG
printf("TuxTxt <Biterror in p27/4-5>\n");
#endif
continue;
}
p->local = i & 0x01;
p->drcs = !!(i & 0x02);
p->l25 = !!(d1 & 0x04);
p->l35 = !!(d1 & 0x08);
p->page =
(((d1 & 0x000003c0) >> 6) |
((d1 & 0x0003c000) >> (14-4)) |
((d1 & 0x00003800) >> (11-8))) ^
(dehamming[vtxt_row[0]] << 8);
if (p->page < 0x100)
p->page += 0x800;
p->subpage = d2 >> 2;
if ((p->page & 0xff) == 0xff)
p->page = 0;
else if (p->page > 0x899)
{
// workaround for crash on RTL
printf("[TuxTxt] page > 0x899 ... ignore!!!!!!\n");
continue;
}
else if (tuxtxt_cache.astCachetable[p->page][0]) /* link valid && linked page cached */
{
tstPageinfo *pageinfo_link = &(tuxtxt_cache.astCachetable[p->page][0]->pageinfo);
if (p->local)
pageinfo_link->function = p->drcs ? FUNC_DRCS : FUNC_POP;
else
pageinfo_link->function = p->drcs ? FUNC_GDRCS : FUNC_GPOP;
}
p++; /* */
}
}
}
else if (packet_number == 26)
{
int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */
if (descode == 0xff)
{
#if TUXTXT_DEBUG
printf("TuxTxt <Biterror in p26>\n");
#endif
continue;
}
if (!pageinfo_thread->ext)
pageinfo_thread->ext = (tstExtData*) calloc(1, sizeof(tstExtData));
if (!pageinfo_thread->ext)
continue;
if (!(pageinfo_thread->ext->p26[descode]))
pageinfo_thread->ext->p26[descode] = (unsigned char*) malloc(13 * 3);
if (pageinfo_thread->ext->p26[descode])
memmove(pageinfo_thread->ext->p26[descode], &vtxt_row[3], 13 * 3);
#if 0//TUXTXT_DEBUG
int i, t, m;
printf("P%03x/%02x %02d/%x",
tuxtxt_cache.current_page[magazine], tuxtxt_cache.current_subpage[magazine],
packet_number, dehamming[vtxt_row[2]]);
for (i=7-4; i <= 45-4; i+=3) /* dump all triplets */
{
t = deh24(&vtxt_row[i]); /* mode/adr/data */
m = (t>>6) & 0x1f;
printf(" M%02xA%02xD%03x", m, t & 0x3f, (t>>11) & 0x7f);
if (m == 0x1f) /* terminator */
break;
}
putchar('\n');
#endif
}
else if (packet_number == 28)
{
int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */
if (descode == 0xff)
{
#if TUXTXT_DEBUG
printf("TuxTxt <Biterror in p28>\n");
#endif
continue;
}
if (descode != 2)
{
int t1 = deh24(&vtxt_row[7-4]);
pageinfo_thread->function = t1 & 0x0f;
if (!pageinfo_thread->nationalvalid)
{
//printf("TuxTxt 28: t1=%x\n", t1>>4);
// pageinfo_thread->nationalvalid = 1; // FIXME without full eval some is broken
pageinfo_thread->national = (t1>>4) & 0x07;
}
}
switch (descode) /* designation code */
{
case 0: /* basic level 1 page */
{
tuxtxt_decode_p2829(vtxt_row, &(pageinfo_thread->ext));
break;
}
case 1: /* G0/G1 designation for older decoders, level 3.5: DCLUT4/16, colors for multicolored bitmaps */
{
break; /* ignore */
}
case 2: /* page key */
{
break; /* ignore */
}
case 3: /* types of PTUs in DRCS */
{
break; /* TODO */
}
case 4: /* CLUTs 0/1, only level 3.5 */
{
break; /* ignore */
}
default:
{
break; /* invalid, ignore */
}
} /* switch designation code */
}
else if (packet_number == 30)
{
#if 0//TUXTXT_DEBUG
int i;
printf("p%03x/%02x %02d/%x ",
tuxtxt_cache.current_page[magazine], tuxtxt_cache.current_subpage[magazine],
packet_number, dehamming[vtxt_row[2]]);
for (i=26-4; i <= 45-4; i++) /* station ID */
putchar(deparity[vtxt_row[i]]);
putchar('\n');
#endif
}
}
/* set update flag */
if (tuxtxt_cache.current_page[magazine] == tuxtxt_cache.page && tuxtxt_cache.current_subpage[magazine] != -1)
{
tuxtxt_compress_page(tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine],pagedata[magazine]);
tuxtxt_cache.pageupdate = 1+(doupdate == tuxtxt_cache.page ? 1: 0);
doupdate=0;
if (!tuxtxt_cache.zap_subpage_manual)
tuxtxt_cache.subpage = tuxtxt_cache.current_subpage[magazine];
}
}
#if 0
else
printf("line %d row %X %X, continue\n", line, vtx_rowbyte[0], vtx_rowbyte[1]);
#endif
}
pthread_mutex_unlock(&tuxtxt_cache_biglock);
}
pthread_exit(NULL);
}
/******************************************************************************
* start_thread *
******************************************************************************/
int tuxtxt_start_thread(int source = 0);
int tuxtxt_start_thread(int source)
{
if (tuxtxt_cache.vtxtpid == -1)
return 0;
tuxtxt_cache.thread_starting = 1;
tuxtxt_init_demuxer(source);
dmx->pesFilter(tuxtxt_cache.vtxtpid);
dmx->Start();
stop_cache = 0;
/* create decode-thread */
if (pthread_create(&tuxtxt_cache.thread_id, NULL, tuxtxt_CacheThread, NULL) != 0)
{
perror("TuxTxt <pthread_create>");
tuxtxt_cache.thread_starting = 0;
return 0;
}
#if 1//TUXTXT_DEBUG
printf("TuxTxt service started %x\n", tuxtxt_cache.vtxtpid);
#endif
tuxtxt_cache.receiving = 1;
tuxtxt_cache.thread_starting = 0;
return 1;
}
/******************************************************************************
* stop_thread *
******************************************************************************/
int tuxtxt_stop_thread()
{
/* stop decode-thread */
if (tuxtxt_cache.thread_id != 0)
{
#if 0
if (pthread_cancel(tuxtxt_cache.thread_id) != 0)
{
perror("TuxTxt <pthread_cancel>");
return 0;
}
#endif
stop_cache = 1;
if (pthread_join(tuxtxt_cache.thread_id, &tuxtxt_cache.thread_result) != 0)
{
perror("TuxTxt <pthread_join>");
return 0;
}
tuxtxt_cache.thread_id = 0;
}
if(dmx) {
dmx->Stop();
delete dmx;
dmx = NULL;
}
#if 1//TUXTXT_DEBUG
printf("TuxTxt stopped service %x\n", tuxtxt_cache.vtxtpid);
#endif
return 1;
}