def test_scc_mid_row_codes_valid_blue(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[8]), SccMidRowCode.BLUE, NamedColors.blue.value, None, None) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[9]), SccMidRowCode.BLUE, NamedColors.blue.value, None, None)
def test_scc_mid_row_codes_valid_green(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[4]), SccMidRowCode.GREEN, NamedColors.green.value, None, None) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[5]), SccMidRowCode.GREEN, NamedColors.green.value, None, None)
def test_scc_mid_row_codes_valid_magenta(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[24]), SccMidRowCode.MAGENTA, NamedColors.magenta.value, None, None) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[25]), SccMidRowCode.MAGENTA, NamedColors.magenta.value, None, None)
def test_scc_mid_row_codes_valid_white(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[0]), SccMidRowCode.WHITE, NamedColors.white.value, None, None) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[1]), SccMidRowCode.WHITE, NamedColors.white.value, None, None)
def test_scc_mid_row_codes_valid_yellow(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[20]), SccMidRowCode.YELLOW, NamedColors.yellow.value, None, None) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[21]), SccMidRowCode.YELLOW, NamedColors.yellow.value, None, None)
def test_scc_mid_row_codes_valid_red(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[16]), SccMidRowCode.RED, NamedColors.red.value, None, None) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[17]), SccMidRowCode.RED, NamedColors.red.value, None, None)
def test_scc_mid_row_codes_valid_cyan(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[12]), SccMidRowCode.CYAN, NamedColors.cyan.value, None, None) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[13]), SccMidRowCode.CYAN, NamedColors.cyan.value, None, None)
def test_scc_mid_row_codes_valid_italics(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[28]), SccMidRowCode.ITALICS, None, FontStyleType.italic, None) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[29]), SccMidRowCode.ITALICS, None, FontStyleType.italic, None)
def test_scc_mid_row_codes_valid_green_underline(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[6]), SccMidRowCode.GREEN_UNDERLINE, NamedColors.green.value, None, TextDecorationType(underline=True)) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[7]), SccMidRowCode.GREEN_UNDERLINE, NamedColors.green.value, None, TextDecorationType(underline=True))
def test_scc_mid_row_codes_valid_italics_underline(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[30]), SccMidRowCode.ITALICS_UNDERLINE, None, FontStyleType.italic, TextDecorationType(underline=True)) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[31]), SccMidRowCode.ITALICS_UNDERLINE, None, FontStyleType.italic, TextDecorationType(underline=True))
def test_scc_mid_row_codes_valid_magenta_underline(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[26]), SccMidRowCode.MAGENTA_UNDERLINE, NamedColors.magenta.value, None, TextDecorationType(underline=True)) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[27]), SccMidRowCode.MAGENTA_UNDERLINE, NamedColors.magenta.value, None, TextDecorationType(underline=True))
def test_scc_mid_row_codes_valid_yellow_underline(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[22]), SccMidRowCode.YELLOW_UNDERLINE, NamedColors.yellow.value, None, TextDecorationType(underline=True)) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[23]), SccMidRowCode.YELLOW_UNDERLINE, NamedColors.yellow.value, None, TextDecorationType(underline=True))
def test_scc_mid_row_codes_valid_cyan_underline(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[14]), SccMidRowCode.CYAN_UNDERLINE, NamedColors.cyan.value, None, TextDecorationType(underline=True)) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[15]), SccMidRowCode.CYAN_UNDERLINE, NamedColors.cyan.value, None, TextDecorationType(underline=True))
def test_scc_mid_row_codes_valid_blue_underline(self): self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[10]), SccMidRowCode.BLUE_UNDERLINE, NamedColors.blue.value, None, TextDecorationType(underline=True)) self.check_mid_row_code(SccMidRowCode.find(MID_ROW_CODE_VALUES[11]), SccMidRowCode.BLUE_UNDERLINE, NamedColors.blue.value, None, TextDecorationType(underline=True))
def to_disassembly(self) -> str: """Converts SCC line into the disassembly format""" disassembly_line = str(self.time_code) + "\t" for scc_word in self.scc_words: if scc_word.value == 0x0000: disassembly_line += "{}" continue if scc_word.byte_1 < 0x20: attribute_code = SccAttributeCode.find(scc_word.value) control_code = SccControlCode.find(scc_word.value) mid_row_code = SccMidRowCode.find(scc_word.value) pac = SccPreambleAddressCode.find(scc_word.byte_1, scc_word.byte_2) spec_char = SccSpecialAndExtendedCharacter.find(scc_word.value) if pac is not None: disassembly_line += f"{{{pac.get_row():02}" color = pac.get_color() indent = pac.get_indent() if indent is not None and indent > 0: disassembly_line += f"{indent :02}" elif color is not None: disassembly_line += get_color_disassembly(color) disassembly_line += get_font_style_disassembly(pac.get_font_style()) disassembly_line += get_text_decoration_disassembly(pac.get_text_decoration()) else: disassembly_line += "00" disassembly_line += "}" elif attribute_code is not None: disassembly_line += "{" disassembly_line += "B" if attribute_code.is_background() else "" disassembly_line += get_color_disassembly(attribute_code.get_color()) disassembly_line += get_text_decoration_disassembly(attribute_code.get_text_decoration()) disassembly_line += "}" elif mid_row_code is not None: disassembly_line += "{" disassembly_line += get_color_disassembly(mid_row_code.get_color()) disassembly_line += get_font_style_disassembly(mid_row_code.get_font_style()) disassembly_line += get_text_decoration_disassembly(mid_row_code.get_text_decoration()) disassembly_line += "}" elif control_code is not None: disassembly_line += "{" + control_code.get_name() + "}" elif spec_char is not None: disassembly_line += spec_char.get_unicode_value() else: disassembly_line += "{??}" LOGGER.warning("Unsupported SCC word: %s", hex(scc_word.value)) else: disassembly_line += scc_word.to_text() return disassembly_line
def test_scc_mid_row_codes_invalid(self): other_code_values = [ code for code in range(0x0000, 0xFFFF) if code not in MID_ROW_CODE_VALUES ] for mrc in other_code_values: self.assertIsNone(SccMidRowCode.find(mrc))
def process_line(self, line: SccLine) -> SmpteTimeCode: """Converts the SCC line to the data model""" debug = str(line.time_code) + "\t" for scc_word in line.scc_words: if self.previous_code == scc_word.value: continue line.time_code.add_frames() if scc_word.value == 0x0000: continue if scc_word.byte_1 < 0x20: control_code = SccControlCode.find(scc_word.value) if control_code is not None \ and control_code is SccControlCode.find(self.previous_code): # Skip duplicated control code from 'Field 2' line.time_code.add_frames(-1) continue attribute_code = SccAttributeCode.find(scc_word.value) mid_row_code = SccMidRowCode.find(scc_word.value) pac = SccPreambleAddressCode.find(scc_word.byte_1, scc_word.byte_2) spec_char = SccSpecialCharacter.find(scc_word.value) extended_char = SccExtendedCharacter.find(scc_word.value) if pac is not None: debug += "[PAC|" + str(pac.get_row()) + "|" + str( pac.get_indent()) if pac.get_color() is not None: debug += "|" + str(pac.get_color()) if pac.get_font_style() is not None: debug += "|I" if pac.get_text_decoration() is not None: debug += "|U" debug += "/" + hex(scc_word.value) + "]" self.process_preamble_address_code(pac, line.time_code) self.previous_code_type = type(pac) elif attribute_code is not None: debug += "[ATC/" + hex(scc_word.value) + "]" self.process_attribute_code(attribute_code) self.previous_code_type = type(attribute_code) elif mid_row_code is not None: debug += "[MRC|" + mid_row_code.get_name() + "/" + hex( scc_word.value) + "]" self.process_mid_row_code(mid_row_code, line.time_code) self.previous_code_type = type(mid_row_code) elif control_code is not None: debug += "[CC|" + control_code.get_name() + "/" + hex( scc_word.value) + "]" self.process_control_code(control_code, line.time_code) self.previous_code_type = type(control_code) elif spec_char is not None: word = spec_char.get_unicode_value() debug += word self.process_text(word, line.time_code) self.previous_code_type = type(spec_char) elif extended_char is not None: if self.current_style in (SccCaptionStyle.PaintOn, SccCaptionStyle.RollUp): self.active_caption.get_current_text().backspace() else: self.buffered_caption.get_current_text().backspace() word = extended_char.get_unicode_value() debug += word self.process_text(word, line.time_code) self.previous_code_type = type(extended_char) else: debug += "[??/" + hex(scc_word.value) + "]" LOGGER.warning("Unsupported SCC word: %s", hex(scc_word.value)) self.previous_code_type = None else: word = scc_word.to_text() debug += word self.process_text(word, line.time_code) self.previous_code_type = str self.previous_code = scc_word.value LOGGER.debug(debug) return line.time_code
def to_model(self, context: _SccContext) -> SccTimeCode: """Converts the SCC line to the data model""" debug = str(self.time_code) + "\t" for scc_word in self.scc_words: if context.previous_code == scc_word.value: continue self.time_code.add_frames() if scc_word.value == 0x0000: continue if scc_word.byte_1 < 0x20: attribute_code = SccAttributeCode.find(scc_word.value) control_code = SccControlCode.find(scc_word.value) mid_row_code = SccMidRowCode.find(scc_word.value) pac = SccPreambleAddressCode.find(scc_word.byte_1, scc_word.byte_2) spec_char = SccSpecialAndExtendedCharacter.find(scc_word.value) if pac is not None: debug += "[PAC|" + str(pac.get_row()) + "|" + str(pac.get_indent()) if pac.get_color() is not None: debug += "|" + str(pac.get_color()) if pac.get_font_style() is not None: debug += "|I" if pac.get_text_decoration() is not None: debug += "|U" debug += "/" + hex(scc_word.value) + "]" context.process_preamble_address_code(pac, self.time_code) elif attribute_code is not None: debug += "[ATC/" + hex(scc_word.value) + "]" context.process_attribute_code(attribute_code) elif mid_row_code is not None: debug += "[MRC|" + mid_row_code.get_name() + "/" + hex(scc_word.value) + "]" context.process_mid_row_code(mid_row_code) elif control_code is not None: debug += "[CC|" + control_code.get_name() + "/" + hex(scc_word.value) + "]" context.process_control_code(control_code, self.time_code) elif spec_char is not None: word = spec_char.get_unicode_value() debug += word context.process_text(word, self.time_code) else: debug += "[??/" + hex(scc_word.value) + "]" LOGGER.warning("Unsupported SCC word: %s", hex(scc_word.value)) context.previous_code = scc_word.value else: word = scc_word.to_text() debug += word context.process_text(word, self.time_code) context.previous_code = scc_word.value LOGGER.debug(debug) return self.time_code