diff options
Diffstat (limited to 'stream/tvi_vbi.c')
-rw-r--r-- | stream/tvi_vbi.c | 1197 |
1 files changed, 0 insertions, 1197 deletions
diff --git a/stream/tvi_vbi.c b/stream/tvi_vbi.c deleted file mode 100644 index 226cf9b342..0000000000 --- a/stream/tvi_vbi.c +++ /dev/null @@ -1,1197 +0,0 @@ -#include "config.h" - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include "tv.h" -#include "tvi_vbi.h" -#include "mp_msg.h" -#include "libmpcodecs/img_format.h" - -#ifdef USE_ICONV -#include <iconv.h> -#endif - -#define VBI_TEXT_CHARSET "UTF-8" - -char* tv_param_tdevice=NULL; ///< teletext vbi device -char* tv_param_tformat="gray"; ///< format: text,bw,gray,color -int tv_param_tpage=100; ///< page number - - -#ifdef USE_ICONV -/* ------------------------------------------------------------------- - zvbi-0.2.25/src/exp-txt.c skip debug "if(1) fprintf(stderr,) " message ------------------------------------------------------------------- -*/ - -/** - * libzvbi - Text export functions - * - * Copyright (C) 2001, 2002 Michael H. Schimek - * - * Based on code from AleVT 1.5.1 - * Copyright (C) 1998, 1999 Edgar Toernig <froese@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. - **/ - -/** $Id$ **/ - -static vbi_bool -print_unicode(iconv_t cd, int endian, int unicode, char **p, int n) -{ - char in[2], *ip, *op; - size_t li, lo, r; - - in[0 + endian] = unicode; - in[1 - endian] = unicode >> 8; - ip = in; op = *p; - li = sizeof(in); lo = n; - - r = iconv(cd, &ip, &li, &op, &lo); - - if ((size_t) -1 == r - || (**p == 0x40 && unicode != 0x0040)) { - in[0 + endian] = 0x20; - in[1 - endian] = 0; - ip = in; op = *p; - li = sizeof(in); lo = n; - - r = iconv(cd, &ip, &li, &op, &lo); - - if ((size_t) -1 == r - || (r == 1 && **p == 0x40)) - goto error; - } - - *p = op; - - return TRUE; - - error: - return FALSE; -} - -static int -vbi_print_page_region_nodebug(vbi_page * pg, char *buf, int size, - const char *format, vbi_bool table, - vbi_bool rtl, int column, int row, int width, - int height) -{ - int endian = vbi_ucs2be(); - int column0, column1, row0, row1; - int x, y, spaces, doubleh, doubleh0; - iconv_t cd; - char *p; - - rtl = rtl; - -#if 0 - if (1) - fprintf (stderr, "vbi_print_page_region '%s' " - "table=%d col=%d row=%d width=%d height=%d\n", - format, table, column, row, width, height); -#endif - - column0 = column; - row0 = row; - column1 = column + width - 1; - row1 = row + height - 1; - - if (!pg || !buf || size < 0 || !format - || column0 < 0 || column1 >= pg->columns - || row0 < 0 || row1 >= pg->rows - || endian < 0) - return 0; - - if ((cd = iconv_open(format, "UCS-2")) == (iconv_t) -1) - return 0; - - p = buf; - - doubleh = 0; - - for (y = row0; y <= row1; y++) { - int x0, x1, xl; - - x0 = (table || y == row0) ? column0 : 0; - x1 = (table || y == row1) ? column1 : (pg->columns - 1); - - xl = (table || y != row0 || (y + 1) != row1) ? -1 : column1; - - doubleh0 = doubleh; - - spaces = 0; - doubleh = 0; - - for (x = x0; x <= x1; x++) { - vbi_char ac = pg->text[y * pg->columns + x]; - - if (table) { - if (ac.size > VBI_DOUBLE_SIZE) - ac.unicode = 0x0020; - } else { - switch (ac.size) { - case VBI_NORMAL_SIZE: - case VBI_DOUBLE_WIDTH: - break; - - case VBI_DOUBLE_HEIGHT: - case VBI_DOUBLE_SIZE: - doubleh++; - break; - - case VBI_OVER_TOP: - case VBI_OVER_BOTTOM: - continue; - - case VBI_DOUBLE_HEIGHT2: - case VBI_DOUBLE_SIZE2: - if (y > row0) - ac.unicode = 0x0020; - break; - } - - /* - * Special case two lines row0 ... row1, and all chars - * in row0, column0 ... column1 are double height: Skip - * row1, don't wrap around. - */ - if (x == xl && doubleh >= (x - x0)) { - x1 = xl; - y = row1; - } - - if (ac.unicode == 0x20 || !vbi_is_print(ac.unicode)) { - spaces++; - continue; - } else { - if (spaces < (x - x0) || y == row0) { - for (; spaces > 0; spaces--) - if (!print_unicode(cd, endian, 0x0020, - &p, buf + size - p)) - goto failure; - } else /* discard leading spaces */ - spaces = 0; - } - } - - if (!print_unicode(cd, endian, ac.unicode, &p, buf + size - p)) - goto failure; - } - - /* if !table discard trailing spaces and blank lines */ - - if (y < row1) { - int left = buf + size - p; - - if (left < 1) - goto failure; - - if (table) { - *p++ = '\n'; /* XXX convert this (eg utf16) */ - } else if (spaces >= (x1 - x0)) { - ; /* suppress blank line */ - } else { - /* exactly one space between adjacent rows */ - if (!print_unicode(cd, endian, 0x0020, &p, left)) - goto failure; - } - } else { - if (doubleh0 > 0) { - ; /* prentend this is a blank double height lower row */ - } else { - for (; spaces > 0; spaces--) - if (!print_unicode(cd, endian, 0x0020, &p, buf + size - p)) - goto failure; - } - } - } - - iconv_close(cd); - return p - buf; - - failure: - iconv_close(cd); - return 0; -} -#endif -/* - end of zvbi-0.2.25/src/exp-txt.c part -*/ - - -/* ------------------------------------------------------------------- - Private routines ------------------------------------------------------------------- -*/ - -/** - * \brief Decode event handler - * \param ev VBI event - * \param data pointer to user defined data - * - */ -static void event_handler(vbi_event * ev, void *data) -{ - priv_vbi_t *user_vbi = (priv_vbi_t *) data; - vbi_page pg; - char *s; - int i; - - switch (ev->type) { - case VBI_EVENT_CAPTION: - mp_msg(MSGT_TV,MSGL_DBG3,"caption\n"); - break; - case VBI_EVENT_NETWORK: - s = ev->ev.network.name; - if (s) { - pthread_mutex_lock(&(user_vbi->buffer_mutex)); - if (user_vbi->network_name) - free(user_vbi->network_name); - user_vbi->network_name = strdup(s); - pthread_mutex_unlock(&(user_vbi->buffer_mutex)); - } - break; - case VBI_EVENT_NETWORK_ID: - s = ev->ev.network.name; - if (s) { - pthread_mutex_lock(&(user_vbi->buffer_mutex)); - if (user_vbi->network_id) - free(user_vbi->network_id); - user_vbi->network_id = strdup(s); - pthread_mutex_unlock(&(user_vbi->buffer_mutex)); - } - break; - case VBI_EVENT_TTX_PAGE: - pthread_mutex_lock(&(user_vbi->buffer_mutex)); - user_vbi->curr_pgno = ev->ev.ttx_page.pgno; // page number - user_vbi->curr_subno = ev->ev.ttx_page.subno; // subpage - i = vbi_bcd2dec(ev->ev.ttx_page.pgno); - if (i > 0 && i < 1000) { - if (!user_vbi->cache[i]) - user_vbi->cache[i] = (vbi_page *) malloc(sizeof(vbi_page)); - vbi_fetch_vt_page(user_vbi->decoder, // fetch page - user_vbi->cache[i], - ev->ev.ttx_page.pgno, - ev->ev.ttx_page.subno, - VBI_WST_LEVEL_3p5, 25, TRUE); - memcpy(user_vbi->theader, user_vbi->cache[i]->text, - sizeof(user_vbi->theader)); - } - pthread_mutex_unlock(&(user_vbi->buffer_mutex)); - break; - } -} - -/** - * \brief Prepares page to be shown on screen - * \param priv_vbi private data structure - * - * This routine adds page number, current time, etc to page header - * - */ -static void process_page(priv_vbi_t * priv_vbi) -{ - char *pagesptr; - int csize, i, j, subtitle = 0, sflg, send; - void *canvas; - char cpage[5]; - vbi_page page; - - memcpy(&(page), priv_vbi->page, sizeof(vbi_page)); - if (priv_vbi->pgno != priv_vbi->page->pgno) { - //don't clear first line - for (i = page.columns; i < 1056; i++) { - page.text[i].unicode = ' '; - page.text[i].background = VBI_TRANSPARENT_COLOR; - } - snprintf(cpage, sizeof(cpage), "%03X", priv_vbi->pgno); - page.text[1].unicode = cpage[0]; - page.text[2].unicode = cpage[1]; - page.text[3].unicode = cpage[2]; - page.text[4].unicode = ' '; - page.text[5].unicode = ' '; - page.text[6].unicode = ' '; - } - - //background page number & title - j=vbi_bcd2dec(priv_vbi->curr_pgno); - if (j>0 && j<1000 && priv_vbi->cache[j]){ - for(i=8;i<priv_vbi->cache[j]->columns;i++){ - page.text[i].unicode = priv_vbi->cache[j]->text[i].unicode; - } - } - - if (page.text[1].unicode == ' ' && page.text[2].unicode == ' ' && - page.text[3].unicode == ' ' && page.text[4].unicode == ' ' && - page.text[5].unicode == ' ' && page.text[5].unicode == ' ' - && !priv_vbi->half) - subtitle = 1; // subtitle page - if (priv_vbi->pagenumdec) { - i = (priv_vbi->pagenumdec >> 12) & 0xf; - switch (i) { - case 1: - page.text[1].unicode = '0' + ((priv_vbi->pagenumdec >> 0) & 0xf); - page.text[2].unicode = '-'; - page.text[3].unicode = '-'; - break; - case 2: - page.text[1].unicode = '0' + ((priv_vbi->pagenumdec >> 4) & 0xf); - page.text[2].unicode = '0' + ((priv_vbi->pagenumdec >> 0) & 0xf); - page.text[3].unicode = '-'; - break; - } - page.text[4].unicode = ' '; - page.text[5].unicode = ' '; - page.text[6].unicode = ' '; - page.text[1].foreground = VBI_WHITE; - page.text[2].foreground = VBI_WHITE; - page.text[3].foreground = VBI_WHITE; - } - priv_vbi->columns = page.columns; - priv_vbi->rows = page.rows; - if (!subtitle) { // update time in header - memcpy(&(page.text[VBI_TIME_LINEPOS]), - &(priv_vbi->theader[VBI_TIME_LINEPOS]), - sizeof(vbi_char) * (priv_vbi->columns - VBI_TIME_LINEPOS)); - } - switch (priv_vbi->tformat) { - case VBI_TFORMAT_TEXT: // mode: text - if (priv_vbi->txtpage) { -#ifdef USE_ICONV - vbi_print_page_region_nodebug(&(page), priv_vbi->txtpage, - VBI_TXT_PAGE_SIZE, VBI_TEXT_CHARSET, TRUE, - 0, 0, 0, page.columns, page.rows); // vbi_page to text without message -#else - vbi_print_page(&(page), priv_vbi->txtpage, - VBI_TXT_PAGE_SIZE, VBI_TEXT_CHARSET, TRUE, 0); -#endif - } - priv_vbi->valid_page = 1; - break; - case VBI_TFORMAT_BW: // mode: black & white - for (i=0; i < (priv_vbi->pgno!=page.pgno?page.columns:1056); i++) { - if (priv_vbi->foreground){ - page.text[i].foreground = VBI_BLACK; - page.text[i].background = VBI_WHITE; - }else{ - page.text[i].foreground = VBI_WHITE; - page.text[i].background = VBI_BLACK; - } - } - case VBI_TFORMAT_GRAY: // mode: grayscale - case VBI_TFORMAT_COLOR: // mode: color (request color spu patch!) - - - - page.color_map[VBI_TRANSPARENT_COLOR] = 0; - if (priv_vbi->alpha) { - if (subtitle) { - for (i = 0; i < page.rows; i++) { - sflg = 0; - send = 0; - for (j = 0; j < page.columns; j++) { - if (page.text[i * page.columns + j].unicode != ' ') { - sflg = 1; - send = j; - } - if (sflg == 0) - page.text[i * page.columns + j].background = - VBI_TRANSPARENT_COLOR; - } - for (j = send + 1; j < page.columns; j++) - page.text[i * page.columns + j].background = - VBI_TRANSPARENT_COLOR; - } - } else { - for (i = 0; i < 1056; i++) - page.text[i].background = VBI_TRANSPARENT_COLOR; - } - } - csize = page.columns * page.rows * 12 * 10 * sizeof(vbi_rgba); - if (csize == 0) - break; - if (csize > priv_vbi->canvas_size) { // test canvas size - if (priv_vbi->canvas) - free(priv_vbi->canvas); - priv_vbi->canvas = malloc(csize); - priv_vbi->canvas_size = 0; - if (priv_vbi->canvas) - priv_vbi->canvas_size = csize; - } - if (priv_vbi->canvas) { - vbi_draw_vt_page(&(page), - priv_vbi->fmt, - priv_vbi->canvas, - priv_vbi->reveal, priv_vbi->flash_on); - priv_vbi->csize = csize; - } - priv_vbi->spudec_proc = 1; - priv_vbi->valid_page = 1; - break; - } -} - -/** - * \brief Update page in cache - * \param priv_vbi private data structure - * - * Routine also calls process_page to refresh currently visible page (if so) - * every time it was received from VBI by background thread. - * - */ -static void update_page(priv_vbi_t * priv_vbi) -{ - int i; - int index; - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - /* - priv_vbi->redraw=1 - page redraw requested - pgno!=page->pgno - page was switched - curr_pgno==pgno - backgound process just fetched current page, refresh it - */ - if (priv_vbi->redraw || - priv_vbi->pgno != priv_vbi->page->pgno || - priv_vbi->curr_pgno == priv_vbi->pgno) { - index = vbi_bcd2dec(priv_vbi->pgno); - if ( index <= 0 || index > 999 || !priv_vbi->cache[index]) { - // curr_pgno is last decoded page - index = vbi_bcd2dec(priv_vbi->curr_pgno); - } - - if (index <=0 || index >999 || !priv_vbi->cache[index]){ - priv_vbi->valid_page = 0; - memset(priv_vbi->page, 0, sizeof(vbi_page)); - }else - { - memcpy(priv_vbi->page, priv_vbi->cache[index], sizeof(vbi_page)); - process_page(priv_vbi);//prepare page to be shown on screen - } - } - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); -} - -/** - * \brief background grabber routine - * \param data user-defined data - * - */ -static void *grabber(void *data) -{ - priv_vbi_t *user_vbi = (priv_vbi_t *) data; - vbi_capture_buffer *sliced_buffer; - struct timeval timeout; - unsigned int n_lines; - int r, err_count = 0; - - while (!user_vbi->eof) { - timeout.tv_sec = 0; - timeout.tv_usec = 500; - r = vbi_capture_pull(user_vbi->capture, NULL, &sliced_buffer, &timeout); // grab slices - if (user_vbi->eof) - return NULL; - switch (r) { - case -1: // read error - if (err_count++ > 4) - user_vbi->eof = 1; - break; - case 0: // time out - break; - default: - err_count = 0; - } - if (r != 1) - continue; - n_lines = sliced_buffer->size / sizeof(vbi_sliced); - vbi_decode(user_vbi->decoder, (vbi_sliced *) sliced_buffer->data, - n_lines, sliced_buffer->timestamp); // decode slice - update_page(user_vbi); - } - switch (r) { - case -1: - mp_msg(MSGT_TV, MSGL_ERR, "VBI read error %d (%s)\n", - errno, strerror(errno)); - return NULL; - case 0: - mp_msg(MSGT_TV, MSGL_ERR, "VBI read timeout\n"); - return NULL; - } - return NULL; -} - -/** - * \brief calculate increased/decreased by given value page number - * \param curr current page number in hexadecimal for - * \param direction decimal value (can be negative) to add to value or curr parameter - * \return new page number in hexadecimal form - * - * VBI page numbers are represented in special hexadecimal form, e.g. - * page with number 123 (as seen by user) internally has number 0x123. - * and equation 0x123+8 should be equal to 0x131 instead of regular 0x12b. - * Page numbers 0xYYY (where Y is not belongs to (0..9) and pages below 0x100 and - * higher 0x999 are reserved for internal use. - * - */ -static int steppage(int curr, int direction) -{ - int newpage = vbi_dec2bcd(vbi_bcd2dec(curr) + direction); - if (newpage < 0x100) - newpage = 0x100; - if (newpage > 0x999) - newpage = 0x999; - return newpage; -} - -/** - * \brief toggles teletext page displaying mode - * \param priv_vbi private data structure - * \param flag new mode - * \return - * TVI_CONTROL_TRUE is success, - * TVI_CONTROL_FALSE otherwise - * - * flag: - * 0 - off - * 1 - on & opaque - * 2 - on & transparent - * 3 - on & transparent with black foreground color (only in bw mode) - * - */ -static int teletext_set_mode(priv_vbi_t * priv_vbi, int flag) -{ - if (flag<0 || flag>3) - return TVI_CONTROL_FALSE; - - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - - priv_vbi->on = flag; - - if (priv_vbi->on > 2 && priv_vbi->tformat != VBI_TFORMAT_BW) - priv_vbi->on = 0; - - priv_vbi->foreground = 0; - priv_vbi->pagenumdec = 0; - priv_vbi->spudec_proc = 1; - priv_vbi->redraw = 1; - switch (priv_vbi->on) { - case 0: - priv_vbi->csize = 0; - break; - case 1: - priv_vbi->alpha = 0; - break; - case 2: - priv_vbi->alpha = 1; - break; - case 3: - priv_vbi->alpha = 1; - priv_vbi->foreground = 1; - break; - } - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); - return TVI_CONTROL_TRUE; -} - -/** - * \brief get half page mode (only in SPU mode) - * \param priv_vbi private data structure - * \return current mode - * 0 : half mode off - * 1 : top half page - * 2 : bottom half page - */ -static int vbi_get_half(priv_vbi_t * priv_vbi) -{ - int flag = 0; - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - if (priv_vbi->valid_page) - flag = priv_vbi->half; - priv_vbi->pagenumdec = 0; - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); - return flag; -} - -/** - * \brief set half page mode (only in SPU mode) - * \param priv_vbi private data structure - * \param flag new half page mode - * \return - * TVI_CONTROL_TRUE is success, - * TVI_CONTROL_FALSE otherwise - * - * - * flag: - * 0 : half mode off - * 1 : top half page - * 2 : bottom half page - */ -static int teletext_set_half_page(priv_vbi_t * priv_vbi, int flag) -{ - if (flag<0 || flag>2) - return TVI_CONTROL_FALSE; - - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - priv_vbi->half = flag; - if (priv_vbi->tformat == VBI_TFORMAT_TEXT && priv_vbi->half > 1) - priv_vbi->half = 0; - priv_vbi->redraw = 1; - priv_vbi->pagenumdec = 0; - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); - return TVI_CONTROL_TRUE; -} - -/** - * \brief displays specified page - * \param priv_vbi private data structure - * \param pgno page number to display - * \param subno subpage number - * - */ -static void vbi_setpage(priv_vbi_t * priv_vbi, int pgno, int subno) -{ - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - priv_vbi->pgno = steppage(0, pgno); - priv_vbi->subno = subno; - priv_vbi->redraw = 1; - priv_vbi->pagenumdec = 0; - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); -} - -/** - * \brief steps over pages by a given value - * \param priv_vbi private data structure - * \param direction decimal step value (can be negative) - * - */ -static void vbi_steppage(priv_vbi_t * priv_vbi, int direction) -{ - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - priv_vbi->pgno = steppage(priv_vbi->pgno, direction); - priv_vbi->redraw = 1; - priv_vbi->pagenumdec = 0; - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); -} - -/** - * \brief append just entered digit to editing page number - * \param priv_vbi private data structure - * \param dec decimal digit to append - * - * dec: - * '0'..'9' append digit - * '-' remove last digit (backspace emulation) - * - * This routine allows user to jump to arbitrary page. - * It implements simple page number editing algorithm. - * - * Subsystem can be on one of two modes: normal and page number edit mode. - * Zero value of priv_vbi->pagenumdec means normal mode - * Non-zero value means page number edit mode and equals to packed - * decimal number of already entered part of page number. - * - * How this works. - * Let's assume that current mode is normal (pagenumdec is zero), teletext page - * 100 are displayed as usual. topmost left corner of page contains page number. - * Then vbi_add_dec is sequentally called (through slave - * command of course) with 1,4,-,2,3 * values of dec parameter. - * - * +-----+------------+------------------+ - * | dec | pagenumxec | displayed number | - * +-----+------------+------------------+ - * | | 0x000 | 100 | - * +-----+------------+------------------+ - * | 1 | 0x001 | __1 | - * +-----+------------+------------------+ - * | 4 | 0x014 | _14 | - * +-----+------------+------------------+ - * | - | 0x001 | __1 | - * +-----+------------+------------------+ - * | 2 | 0x012 | _12 | - * +-----+------------+------------------+ - * | 3 | 0x123 | 123 | - * +-----+------------+------------------+ - * | | 0x000 | 123 | - * +-----+------------+------------------+ - * - * pagenumdec will automatically receive zero value after third digit of page number - * is entered and current page will be switched to another one with entered page number. - * - */ -static void vbi_add_dec(priv_vbi_t * priv_vbi, char *dec) -{ - int count, shift; - if (!dec) - return; - if (!priv_vbi->on) - return; - if ((*dec < '0' || *dec > '9') && *dec != '-') - return; - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - count = (priv_vbi->pagenumdec >> 12) & 0xf; - if (*dec == '-') { - count--; - if (count) - priv_vbi->pagenumdec = ((priv_vbi->pagenumdec >> 4) & 0xfff) | (count << 12); - else - priv_vbi->pagenumdec = 0; - } else { - shift = count * 4; - count++; - priv_vbi->pagenumdec = - (((priv_vbi->pagenumdec) << 4 | (*dec -'0')) & 0xfff) | (count << 12); - if (count == 3) { - priv_vbi->pgno = priv_vbi->pagenumdec & 0xfff; - priv_vbi->subno = 0; - priv_vbi->redraw = 1; - priv_vbi->pagenumdec = 0; - } - } - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); -} - -/** - * \brief follows link specified on current page - * \param priv_vbi private data structure - * \param linkno link number (0..6) - * \return - * TVI_CONTROL_FALSE if linkno is outside 0..6 range or if - * teletext is switched off - * TVI_CONTROL_TRUE otherwise - * - * linkno: - * 0: tpage in tv parameters (starting page, usually 100) - * 1..6: follows link on current page with given number - * - * FIXME: quick test shows that this is working strange - * FIXME: routine does not checks whether links exists on page or not - * TODO: more precise look - * - */ -static int vbi_golink(priv_vbi_t * priv_vbi, int linkno) -{ - if (linkno < 0 || linkno > 6) - return TVI_CONTROL_FALSE; - if (!priv_vbi->on) - return TVI_CONTROL_FALSE; - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - if (linkno == 0) { - priv_vbi->pgno = priv_vbi->tpage; - priv_vbi->subno = priv_vbi->page->nav_link[linkno].subno; - priv_vbi->redraw = 1; - priv_vbi->pagenumdec = 0; - } else { - linkno--; - if (priv_vbi->pgno == priv_vbi->page->pgno) { - priv_vbi->pgno = priv_vbi->page->nav_link[linkno].pgno; - priv_vbi->subno = priv_vbi->page->nav_link[linkno].subno; - priv_vbi->redraw = 1; - priv_vbi->pagenumdec = 0; - } - } - priv_vbi->pagenumdec = 0; - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); - return TVI_CONTROL_TRUE; -} - -/** - * \brief get pointer to current teletext page - * \param priv_vbi private data structure - * \return pointer to vbi_page structure if teletext is - * switched on and current page is valid, NULL - otherwise - * - */ -static vbi_page *vbi_getpage(priv_vbi_t * priv_vbi) -{ - vbi_page *page = NULL; - - if (!priv_vbi->on) - return NULL; - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - if (priv_vbi->valid_page) - if (page = malloc(sizeof(vbi_page))) - memcpy(page, priv_vbi->page, sizeof(vbi_page)); - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); - return page; -} - -/** - * \brief get pointer to current teletext page - * \param priv_vbi private data structure - * \return pointer to character string, containing text-only data of - * teletext page. If teletext is switched off, current page is invalid - * or page format if not equal to "text" then returning value is NULL. - * - */ -static char *vbi_getpagetext(priv_vbi_t * priv_vbi) -{ - char *page = NULL; - - if (!priv_vbi->on) - return NULL; - if (priv_vbi->tformat != VBI_TFORMAT_TEXT && priv_vbi->canvas) - return NULL; - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - if (priv_vbi->valid_page) - page = priv_vbi->txtpage; - if (!page) - page = priv_vbi->header; - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); - return page; -} - -/** - * \brief get current page RGBA32 image (only in SPU mode) - * \param priv_vbi private data structure - * \return pointer to tv_teletext_img_t structure, containing among - * other things rendered RGBA32 image of current teletext page. - * return NULL is image is not available for some reason. - * - */ -static tv_teletext_img_t *vbi_getpageimg(priv_vbi_t * priv_vbi) -{ - tv_teletext_img_t *img = NULL; - - if (priv_vbi->tformat == VBI_TFORMAT_TEXT) - return NULL; - if (priv_vbi->spudec_proc == 0) - return NULL; - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - if (NULL != (img = malloc(sizeof(tv_teletext_img_t)))) { - img->tformat = priv_vbi->tformat; // format: bw|gray|color - img->tformat = VBI_TFORMAT_GRAY; // format: bw|gray|color - img->half = priv_vbi->half; // half mode - img->columns = priv_vbi->columns; // page size - img->rows = priv_vbi->rows; - img->width = priv_vbi->columns * 12; - img->width = priv_vbi->rows * 10; - img->canvas = NULL; - // is page ok? - if (priv_vbi->canvas && priv_vbi->on && priv_vbi->csize && priv_vbi->valid_page) { - - if (NULL != (img->canvas = malloc(priv_vbi->csize))) - memcpy(img->canvas, priv_vbi->canvas, priv_vbi->csize); - } - } - priv_vbi->spudec_proc = 0; - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); - return img; -} - -/** - * \brief start teletext sybsystem - * \param priv_vbi private data structure - * - * initializes cache, vbi decoder and starts background thread - * - */ -static void vbi_start(priv_vbi_t * priv_vbi) -{ - if (!priv_vbi) - return; - if (NULL != (priv_vbi->txtpage = malloc(VBI_TXT_PAGE_SIZE))) // alloc vbi_page - memset(priv_vbi->txtpage, 0, VBI_TXT_PAGE_SIZE); - priv_vbi->page = malloc(sizeof(vbi_page)); - priv_vbi->cache = (vbi_page **) malloc(1000 * sizeof(vbi_page *)); - memset(priv_vbi->cache, 0, 1000 * sizeof(vbi_page *)); - priv_vbi->decoder = vbi_decoder_new(); - priv_vbi->subno = 0; - priv_vbi->fmt = VBI_PIXFMT_RGBA32_LE; - memset(priv_vbi->theader, 0, sizeof(priv_vbi->theader)); - snprintf(priv_vbi->header, sizeof(priv_vbi->header), "%s", VBI_NO_TELETEXT); - vbi_event_handler_add(priv_vbi->decoder, ~0, event_handler, (void *) priv_vbi); // add event handler - pthread_create(&priv_vbi->grabber_thread, NULL, grabber, priv_vbi); // add grab function - pthread_mutex_init(&priv_vbi->buffer_mutex, NULL); - priv_vbi->valid_page = 0; - priv_vbi->pagenumdec = 0; - mp_msg(MSGT_TV, MSGL_INFO, "Teletext device: %s\n", priv_vbi->device); -} - -/** - * \brief Teletext reset - * \param priv_vbi private data structure - * - * should be called during frequency, norm change, etc - * - */ -static void vbi_reset(priv_vbi_t * priv_vbi) -{ - int i; - pthread_mutex_lock(&(priv_vbi->buffer_mutex)); - if (priv_vbi->canvas) - free(priv_vbi->canvas); - priv_vbi->canvas = NULL; - priv_vbi->canvas_size = 0; - priv_vbi->redraw = 1; - priv_vbi->csize = 0; - priv_vbi->valid_page = 0; - priv_vbi->spudec_proc = 1; - priv_vbi->pagenumdec = 0; - if (priv_vbi->page) - memset(priv_vbi->page, 0, sizeof(vbi_page)); - if (priv_vbi->txtpage) - memset(priv_vbi->txtpage, 0, VBI_TXT_PAGE_SIZE); - memset(priv_vbi->theader, 0, sizeof(priv_vbi->theader)); - if (priv_vbi->cache) { - for (i = 0; i < 1000; i++) { - if (priv_vbi->cache[i]) - free(priv_vbi->cache[i]); - priv_vbi->cache[i] = NULL; - } - } - snprintf(priv_vbi->header, sizeof(priv_vbi->header), "%s", - VBI_NO_TELETEXT); - pthread_mutex_unlock(&(priv_vbi->buffer_mutex)); -} - -/* ---------------------------------------------------------------------------------- - Public routines ---------------------------------------------------------------------------------- -*/ - -/** - * \brief teletext subsystem init - * \note Routine uses global variables tv_param_tdevice, tv_param_tpage - * and tv_param_tformat for initialization. - * - */ -priv_vbi_t *teletext_init(void) -{ - priv_vbi_t *priv_vbi; - int formatid, startpage; - unsigned int services = VBI_SLICED_TELETEXT_B | - VBI_SLICED_CAPTION_525 | - VBI_SLICED_CAPTION_625 | - VBI_SLICED_VBI_525 | - VBI_SLICED_VBI_625 | - VBI_SLICED_WSS_625 | - VBI_SLICED_WSS_CPR1204 | - VBI_SLICED_VPS; - - if (!tv_param_tdevice) - return NULL; - - if (NULL == (priv_vbi = malloc(sizeof(priv_vbi_t)))) - return NULL; - memset(priv_vbi, 0, sizeof(priv_vbi_t)); - formatid = VBI_TFORMAT_TEXT; // default - if (tv_param_tformat != NULL) { - if (strcmp(tv_param_tformat, "text") == 0) - formatid = VBI_TFORMAT_TEXT; - if (strcmp(tv_param_tformat, "bw") == 0) - formatid = VBI_TFORMAT_BW; - if (strcmp(tv_param_tformat, "gray") == 0) - formatid = VBI_TFORMAT_GRAY; - if (strcmp(tv_param_tformat, "color") == 0) - formatid = VBI_TFORMAT_COLOR; - } - startpage = steppage(0, tv_param_tpage); // page number is HEX - if (startpage < 0x100 || startpage > 0x999) - startpage = 0x100; - priv_vbi->device = strdup(tv_param_tdevice); - priv_vbi->tformat = formatid; - priv_vbi->tpage = startpage; // page number - priv_vbi->pgno = startpage; // page number - - - if (!priv_vbi->capture) { - priv_vbi->services = services; // probe v4l2 - priv_vbi->capture = vbi_capture_v4l2_new(priv_vbi->device, // device - 20, // buffer numbers - &(priv_vbi->services), // services - 0, // strict - &(priv_vbi->errstr), // error string - 0); // trace - } - services = priv_vbi->services; - if (priv_vbi->capture == NULL) { - priv_vbi->services = services; // probe v4l - priv_vbi->capture = vbi_capture_v4l_new(priv_vbi->device, - 20, - &(priv_vbi->services), - 0, &(priv_vbi->errstr), 0); - } - - if |