/* * EPG teletext packet playback for debugging purposes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation. You find a copy of this * license in the file COPYRIGHT in the root directory of this release. * * 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. * * * Description: * * This module contains is the main module of the small utility * "vbiplay.exe" that plays back teletext pages of an EPG page that * previously have been saved to a file with vbirec.exe * * Author: Thorsten Zoerner * * $Id: vbiplay.c,v 1.7 2003/03/09 19:27:50 tom Exp tom $ */ #define DEBUG_SWITCH DEBUG_SWITCH_TVSIM #define DPRINTF_OFF #include #include #include #include #include #include #include "epgctl/mytypes.h" #include "epgctl/debug.h" #include "epgvbi/btdrv.h" #include "epgvbi/winshm.h" #include "tvsim/winshmclnt.h" volatile EPGACQ_BUF * pVbiBuf; static HANDLE playEventHandle; static CRITICAL_SECTION m_cCrit; // --------------------------------------------------------------------------- // Callback for shared memory handler: invoked when EPG app attaches or detaches // - when a EPG application attaches, playback is started // static void EpgAttach( bool attach ) { if (attach) { dprintf0("TvSimuMsg-Attach: start VBI playback\n"); // trigger an event to wake up the main loop from it's wait function SetEvent(playEventHandle); } else dprintf0("TvSimuMsg-Attach: detached\n"); } // --------------------------------------------------------------------------- // Callback for shared memory handler: invoked when EPG attach fails // - when a EPG application attaches, playback is started // static void EpgError( void ) { const uchar * pErrMsg; pErrMsg = WinSharedMemClient_GetErrorMsg(); fprintf(stderr, "%s", ((pErrMsg != NULL) ? (char*)pErrMsg : "EPG client init failed")); if (pErrMsg != NULL) xfree((void *) pErrMsg); } // --------------------------------------------------------------------------- // Trigger function for shared memory events // - called whenever the connected EPG application changed a value in shared mem // - this function is executed in a separated thread (which is used to wait for // EPG events) hence a semaphore is used to synchronize with the main loop // static void EpgEvent( void ) { WINSHMCLNT_EVENT curEvent; bool shouldExit; EnterCriticalSection (&m_cCrit); shouldExit = FALSE; do { curEvent = WinSharedMemClient_GetEpgEvent(); switch (curEvent) { case SHM_EVENT_ATTACH: EpgAttach(TRUE); break; case SHM_EVENT_DETACH: EpgAttach(FALSE); break; case SHM_EVENT_ATTACH_ERROR: EpgError(); shouldExit = TRUE; break; case SHM_EVENT_PROG_INFO: // ignored break; case SHM_EVENT_CMD_ARGV: // ignored break; case SHM_EVENT_INP_FREQ: // ignored break; case SHM_EVENT_NONE: shouldExit = TRUE; break; default: debug1("TvSimu-IdleHandler: unknown EPG event %d - ignored", curEvent); } } while (shouldExit == FALSE); LeaveCriticalSection (&m_cCrit); } // --------------------------------------------------------------------------- // structure which is passed to the shm client init function // - only the trigger and attach callbacks are used by this app // static const WINSHMCLNT_TVAPP_INFO tvSimuInfo = { "VBI playback", "", TVAPP_NONE, TVAPP_FEAT_TTX_FWD, EpgEvent, }; // --------------------------------------------------------------------------- // Playback & event loop // - this loop waits for an EPG application to attach // - while an app is attached is copies VBI lines from the file to shared mem // static void PlaybackVbi( int fdTtxFile ) { VBI_LINE * vbl; size_t rstat; bool doSleep; while (1) { doSleep = FALSE; EnterCriticalSection (&m_cCrit); if (pVbiBuf != NULL) { if (pVbiBuf->chanChangeCnf != pVbiBuf->chanChangeReq) { pVbiBuf->chanChangeCnf = pVbiBuf->chanChangeReq; pVbiBuf->reader_idx = 0; pVbiBuf->writer_idx = 0; memset((void *) &pVbiBuf->ttxStats, 0, sizeof(pVbiBuf->ttxStats)); } if ( (pVbiBuf->isEnabled) && (pVbiBuf->reader_idx != ((pVbiBuf->writer_idx + 1) % EPGACQ_BUF_COUNT)) ) { vbl = (VBI_LINE *) &pVbiBuf->line[pVbiBuf->writer_idx]; rstat = read(fdTtxFile, vbl, sizeof(VBI_LINE)); if ((rstat < 0) || (rstat < sizeof(VBI_LINE))) { // reached end of file -> terminate the loop break; } pVbiBuf->mipPageNo = vbl->pageno; pVbiBuf->writer_idx = (pVbiBuf->writer_idx + 1) % EPGACQ_BUF_COUNT; pVbiBuf->ttxStats.ttxPkgCount += 1; pVbiBuf->ttxStats.epgPkgCount += 1; if (vbl->pkgno == 0) { pVbiBuf->ttxStats.epgPagCount += 1; memcpy((char *) pVbiBuf->lastHeader.data, vbl->data, sizeof(pVbiBuf->lastHeader.data)); pVbiBuf->lastHeader.pageno = vbl->pageno; pVbiBuf->lastHeader.sub = vbl->sub; } //dprintf1("wrote pkg %d\n", vbl->pkgno); } else { // wait for the client to process the lines in the buffer doSleep = TRUE; } } LeaveCriticalSection (&m_cCrit); if (pVbiBuf == NULL) { // nxtvepg not attached -> wait for event dprintf0("Playback-Vbi: waiting for attach\n"); WaitForSingleObject(playEventHandle, INFINITE); } else if (doSleep) { // acq not enabled or buffer full -> wait some, then try again Sleep(100); } } dprintf0("TvSimuMsg-Attach: VBI playback finished\n"); } // --------------------------------------------------------------------------- // Main // int main( int argc, char ** argv ) { WINSHMCLNT_EVENT attachEvent; int fdTtxFile; InitializeCriticalSection (&m_cCrit); fdTtxFile = open("ttx.dat", O_RDONLY|O_BINARY, 0666); if (fdTtxFile != -1) { playEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL); if (playEventHandle != NULL) { pVbiBuf = NULL; dprintf0("VbiPlay-Main: init done, waiting for EPG app start\n"); if (WinSharedMemClient_Init(&tvSimuInfo, TVAPP_CARD_REQ_ALL, &attachEvent)) { if (attachEvent != SHM_EVENT_ATTACH_ERROR) { // report attach failures during initialization if (attachEvent == SHM_EVENT_ATTACH) EpgAttach(TRUE); // enter the event loop PlaybackVbi(fdTtxFile); // done -> detach from shared memory WinSharedMemClient_Exit(); } else EpgError(); } else { EpgError(); } CloseHandle(playEventHandle); } close(fdTtxFile); } else fprintf(stderr, "open %s: %s\n", "ttx.dat", strerror(errno)); return 0; }