static void cc_handler (vbi_event * ev, void * user_data) { vbi_page page; vbi_bool success; int row; user_data = user_data; if (pgno != -1 && ev->ev.caption.pgno != pgno) return; /* Fetching & rendering in the handler is a bad idea, but this is only a test */ success = vbi_fetch_cc_page (vbi, &page, ev->ev.caption.pgno, TRUE); assert (success); #if 1 /* optional */ if (abs (page.dirty.roll) > page.rows) { clear (&page); } else if (page.dirty.roll == -1) { roll_up (&page, page.dirty.y0, page.dirty.y1); } else { #endif for (row = page.dirty.y0; row <= page.dirty.y1; ++row) render (&page, row); } vbi_unref_page (&page); }
/* Process GLOBAL CODES */ void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_decoder_608_context *context, struct cc_subtitle *sub) { int changes=0; // Handle channel change context->channel = context->new_channel; if (context->channel != context->my_channel) return; enum command_code command = COM_UNKNOWN; if (c1==0x15) c1=0x14; if ((c1==0x14 || c1==0x1C) && c2==0x2C) command = COM_ERASEDISPLAYEDMEMORY; if ((c1==0x14 || c1==0x1C) && c2==0x20) command = COM_RESUMECAPTIONLOADING; if ((c1==0x14 || c1==0x1C) && c2==0x2F) command = COM_ENDOFCAPTION; if ((c1==0x14 || c1==0x1C) && c2==0x22) command = COM_ALARMOFF; if ((c1==0x14 || c1==0x1C) && c2==0x23) command = COM_ALARMON; if ((c1==0x14 || c1==0x1C) && c2==0x24) command = COM_DELETETOENDOFROW; if ((c1==0x17 || c1==0x1F) && c2==0x21) command = COM_TABOFFSET1; if ((c1==0x17 || c1==0x1F) && c2==0x22) command = COM_TABOFFSET2; if ((c1==0x17 || c1==0x1F) && c2==0x23) command = COM_TABOFFSET3; if ((c1==0x14 || c1==0x1C) && c2==0x25) command = COM_ROLLUP2; if ((c1==0x14 || c1==0x1C) && c2==0x26) command = COM_ROLLUP3; if ((c1==0x14 || c1==0x1C) && c2==0x27) command = COM_ROLLUP4; if ((c1==0x14 || c1==0x1C) && c2==0x29) command = COM_RESUMEDIRECTCAPTIONING; if ((c1==0x14 || c1==0x1C) && c2==0x2D) command = COM_CARRIAGERETURN; if ((c1==0x14 || c1==0x1C) && c2==0x2E) command = COM_ERASENONDISPLAYEDMEMORY; if ((c1==0x14 || c1==0x1C) && c2==0x21) command = COM_BACKSPACE; if ((c1==0x14 || c1==0x1C) && c2==0x2b) command = COM_RESUMETEXTDISPLAY; if ((command == COM_ROLLUP2 || command == COM_ROLLUP3 || command == COM_ROLLUP4) && context->settings->force_rollup == 1) command=COM_FAKE_RULLUP1; if ((command == COM_ROLLUP3 || command == COM_ROLLUP4) && context->settings->force_rollup == 2) command=COM_ROLLUP2; else if (command == COM_ROLLUP4 && context->settings->force_rollup == 3) command=COM_ROLLUP3; ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCommand begin: %02X %02X (%s)\n", c1, c2, command_type[command]); ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCurrent mode: %d Position: %d,%d VisBuf: %d\n", context->mode, context->cursor_row, context->cursor_column, context->visible_buffer); switch (command) { case COM_BACKSPACE: if (context->cursor_column>0) { context->cursor_column--; get_writing_buffer(context)->characters[context->cursor_row][context->cursor_column] = ' '; } break; case COM_TABOFFSET1: if (context->cursor_column<CCX_DECODER_608_SCREEN_WIDTH - 1) context->cursor_column++; break; case COM_TABOFFSET2: context->cursor_column += 2; if (context->cursor_column>CCX_DECODER_608_SCREEN_WIDTH - 1) context->cursor_column = CCX_DECODER_608_SCREEN_WIDTH - 1; break; case COM_TABOFFSET3: context->cursor_column += 3; if (context->cursor_column>CCX_DECODER_608_SCREEN_WIDTH - 1) context->cursor_column = CCX_DECODER_608_SCREEN_WIDTH - 1; break; case COM_RESUMECAPTIONLOADING: context->mode = MODE_POPON; break; case COM_RESUMETEXTDISPLAY: context->mode = MODE_TEXT; break; case COM_FAKE_RULLUP1: case COM_ROLLUP2: case COM_ROLLUP3: case COM_ROLLUP4: if (context->mode == MODE_POPON || context->mode == MODE_PAINTON) { /* CEA-608 C.10 Style Switching (regulatory) [...]if pop-up or paint-on captioning is already present in either memory it shall be erased[...] */ if (write_cc_buffer(context, sub)) context->screenfuls_counter++; erase_memory(context, true); } erase_memory(context, false); // If the reception of data for a row is interrupted by data for the alternate // data channel or for text mode, the display of caption text will resume from the same // cursor position if a roll-up caption command is received and no PAC is given [...] if (context->mode != MODE_TEXT && context->have_cursor_position == 0) { // If no Preamble Address Code is received, the base row shall default to row 15 context->cursor_row = 14; // Default if the previous mode wasn't roll up already. context->cursor_column = 0; context->have_cursor_position = 1; } switch (command) { case COM_FAKE_RULLUP1: context->mode = MODE_FAKE_ROLLUP_1; break; case COM_ROLLUP2: context->mode = MODE_ROLLUP_2; break; case COM_ROLLUP3: context->mode = MODE_ROLLUP_3; break; case COM_ROLLUP4: context->mode = MODE_ROLLUP_4; break; default: // Impossible, but remove compiler warnings break; } break; case COM_CARRIAGERETURN: if (context->mode == MODE_PAINTON) // CR has no effect on painton mode according to zvbis' code break; if (context->mode == MODE_POPON) // CFS: Not sure about this. Is there a valid reason for CR in popup? { context->cursor_column = 0; if (context->cursor_row<15) context->cursor_row++; break; } if (context->output_format == CCX_OF_TRANSCRIPT) { write_cc_line(context,sub); } // In transcript mode, CR doesn't write the whole screen, to avoid // repeated lines. changes = check_roll_up(context); if (changes) { // Only if the roll up would actually cause a line to disappear we write the buffer if (context->output_format != CCX_OF_TRANSCRIPT) { if (write_cc_buffer(context, sub)) context->screenfuls_counter++; if (context->settings->no_rollup) erase_memory(context, true); // Make sure the lines we just wrote aren't written again } } roll_up(context); // The roll must be done anyway of course. context->ts_start_of_current_line = -1; // Unknown. if (changes) context->current_visible_start_ms = get_visible_start(); context->cursor_column = 0; break; case COM_ERASENONDISPLAYEDMEMORY: erase_memory(context, false); break; case COM_ERASEDISPLAYEDMEMORY: // Write it to disk before doing this, and make a note of the new // time it became clear. if (context->output_format == CCX_OF_TRANSCRIPT && (context->mode == MODE_FAKE_ROLLUP_1 || context->mode == MODE_ROLLUP_2 || context->mode == MODE_ROLLUP_3 || context->mode == MODE_ROLLUP_4)) { // In transcript mode we just write the cursor line. The previous lines // should have been written already, so writing everything produces // duplicate lines. write_cc_line(context, sub); } else { if (context->output_format == CCX_OF_TRANSCRIPT) context->ts_start_of_current_line = context->current_visible_start_ms; if (write_cc_buffer(context, sub)) context->screenfuls_counter++; } erase_memory(context, true); context->current_visible_start_ms = get_visible_start(); break; case COM_ENDOFCAPTION: // Switch buffers // The currently *visible* buffer is leaving, so now we know its ending // time. Time to actually write it to file. if (write_cc_buffer(context, sub)) context->screenfuls_counter++; context->visible_buffer = (context->visible_buffer == 1) ? 2 : 1; context->current_visible_start_ms = get_visible_start(); context->cursor_column = 0; context->cursor_row = 0; context->current_color = context->settings->default_color; context->font = FONT_REGULAR; context->mode = MODE_POPON; break; case COM_DELETETOENDOFROW: delete_to_end_of_row(context); break; case COM_ALARMOFF: case COM_ALARMON: // These two are unused according to Robson's, and we wouldn't be able to do anything useful anyway break; case COM_RESUMEDIRECTCAPTIONING: context->mode = MODE_PAINTON; //ccx_common_logging.log_ftn ("\nWarning: Received ResumeDirectCaptioning, this mode is almost impossible.\n"); //ccx_common_logging.log_ftn ("to transcribe to a text file.\n"); break; default: ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rNot yet implemented.\n"); break; } ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCurrent mode: %d Position: %d,%d VisBuf: %d\n", context->mode, context->cursor_row, context->cursor_column, context->visible_buffer); ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCommand end: %02X %02X (%s)\n", c1, c2, command_type[command]); }