Remove VTT voice span classes

This commit is contained in:
Michał Sikora 2024-08-27 19:27:57 +02:00 committed by Ian Baker
parent 108a5ca2f5
commit ce52fc77ec
6 changed files with 39 additions and 72 deletions

View File

@ -36,27 +36,19 @@ public final class VoiceSpan {
/** The speaker name. */ /** The speaker name. */
public final String speakerName; public final String speakerName;
/** The classes associated with the text. It can specify things like "first", "loud", etc. */
public final Set<String> classes;
private static final String FIELD_NAME = Util.intToStringMaxRadix(0); private static final String FIELD_NAME = Util.intToStringMaxRadix(0);
private static final String FIELD_CLASSES = Util.intToStringMaxRadix(1);
public VoiceSpan(String speakerName, Set<String> classes) { public VoiceSpan(String speakerName) {
this.speakerName = speakerName; this.speakerName = speakerName;
this.classes = classes;
} }
public Bundle toBundle() { public Bundle toBundle() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(FIELD_NAME, speakerName); bundle.putString(FIELD_NAME, speakerName);
bundle.putStringArray(FIELD_CLASSES, classes.toArray(new String[0]));
return bundle; return bundle;
} }
public static VoiceSpan fromBundle(Bundle bundle) { public static VoiceSpan fromBundle(Bundle bundle) {
return new VoiceSpan( return new VoiceSpan(/* speakerName = */ checkNotNull(bundle.getString(FIELD_NAME)));
/* speakerName = */ checkNotNull(bundle.getString(FIELD_NAME)),
/* classes = */ ImmutableSet.copyOf(checkNotNull(bundle.getStringArray(FIELD_CLASSES))));
} }
} }

View File

@ -42,7 +42,7 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class CustomCueBundlerTest { public class CustomCueBundlerTest {
private static final VoiceSpan VOICE_SPAN = new VoiceSpan("name", Set.of("first", "loud")); private static final VoiceSpan VOICE_SPAN = new VoiceSpan("name");
private static final RubySpan RUBY_SPAN = private static final RubySpan RUBY_SPAN =
new RubySpan("ruby text", TextAnnotation.POSITION_AFTER); new RubySpan("ruby text", TextAnnotation.POSITION_AFTER);
private static final TextEmphasisSpan TEXT_EMPHASIS_SPAN = private static final TextEmphasisSpan TEXT_EMPHASIS_SPAN =
@ -98,7 +98,7 @@ public class CustomCueBundlerTest {
.hasVoiceSpanBetween( .hasVoiceSpanBetween(
ALL_SPANS_TO_START_END_INDEX.get(VOICE_SPAN).first, ALL_SPANS_TO_START_END_INDEX.get(VOICE_SPAN).first,
ALL_SPANS_TO_START_END_INDEX.get(VOICE_SPAN).second) ALL_SPANS_TO_START_END_INDEX.get(VOICE_SPAN).second)
.withSpeakerNameAndClasses(VOICE_SPAN.speakerName, VOICE_SPAN.classes); .withSpeakerName(VOICE_SPAN.speakerName);
} }
@Test @Test

View File

@ -557,7 +557,7 @@ public final class WebvttCueParser {
applyDefaultColors(text, startTag.classes, start, end); applyDefaultColors(text, startTag.classes, start, end);
break; break;
case TAG_VOICE: case TAG_VOICE:
applyVoiceSpan(text, startTag.voice, startTag.classes, start, end); applyVoiceSpan(text, startTag.voice, start, end);
break; break;
case TAG_LANG: case TAG_LANG:
case "": // Case of the "whole cue" virtual tag. case "": // Case of the "whole cue" virtual tag.
@ -662,8 +662,8 @@ public final class WebvttCueParser {
} }
private static void applyVoiceSpan( private static void applyVoiceSpan(
SpannableStringBuilder text, String voice, Set<String> classes, int start, int end) { SpannableStringBuilder text, String voice, int start, int end) {
text.setSpan(new VoiceSpan(voice, classes), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); text.setSpan(new VoiceSpan(voice), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} }
private static void applyStyleToText( private static void applyStyleToText(

View File

@ -22,7 +22,6 @@ import android.graphics.Color;
import android.text.Spanned; import android.text.Spanned;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.util.Collections; import java.util.Collections;
import java.util.Set;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -250,7 +249,7 @@ public final class WebvttCueParserTest {
assertThat(text.toString()).isEqualTo("Text with a single voice span"); assertThat(text.toString()).isEqualTo("Text with a single voice span");
assertThat(text) assertThat(text)
.hasVoiceSpanBetween(0, "Text with a single voice span".length()) .hasVoiceSpanBetween(0, "Text with a single voice span".length())
.withSpeakerNameAndClasses("", Collections.emptySet()); .withSpeakerName("");
} }
@Test @Test
@ -260,7 +259,7 @@ public final class WebvttCueParserTest {
assertThat(text.toString()).isEqualTo("Text with a single voice span"); assertThat(text.toString()).isEqualTo("Text with a single voice span");
assertThat(text) assertThat(text)
.hasVoiceSpanBetween(0, "Text with a single voice span".length()) .hasVoiceSpanBetween(0, "Text with a single voice span".length())
.withSpeakerNameAndClasses("Esme", Collections.emptySet()); .withSpeakerName("Esme");
} }
@Test @Test
@ -270,17 +269,17 @@ public final class WebvttCueParserTest {
assertThat(text.toString()).isEqualTo("Text with a single voice span"); assertThat(text.toString()).isEqualTo("Text with a single voice span");
assertThat(text) assertThat(text)
.hasVoiceSpanBetween(0, "Text with a single voice span".length()) .hasVoiceSpanBetween(0, "Text with a single voice span".length())
.withSpeakerNameAndClasses("", Set.of("first", "loud")); .withSpeakerName("");
} }
@Test @Test
public void parseVoiceSpanWithNameAndClasses() throws Exception { public void ignoreVoiceSpanClasses() throws Exception {
Spanned text = parseCueText("<v.first.loud Esme>Text with a single voice span"); Spanned text = parseCueText("<v.first.loud Esme>Text with a single voice span");
assertThat(text.toString()).isEqualTo("Text with a single voice span"); assertThat(text.toString()).isEqualTo("Text with a single voice span");
assertThat(text) assertThat(text)
.hasVoiceSpanBetween(0, "Text with a single voice span".length()) .hasVoiceSpanBetween(0, "Text with a single voice span".length())
.withSpeakerNameAndClasses("Esme", Set.of("first", "loud")); .withSpeakerName("Esme");
} }
@Test @Test
@ -288,12 +287,10 @@ public final class WebvttCueParserTest {
Spanned text = parseCueText("<v.loud Esme>Text with </v><v.quiet Mary>multiple voice spans"); Spanned text = parseCueText("<v.loud Esme>Text with </v><v.quiet Mary>multiple voice spans");
assertThat(text.toString()).isEqualTo("Text with multiple voice spans"); assertThat(text.toString()).isEqualTo("Text with multiple voice spans");
assertThat(text) assertThat(text).hasVoiceSpanBetween(0, "Text with ".length()).withSpeakerName("Esme");
.hasVoiceSpanBetween(0, "Text with ".length())
.withSpeakerNameAndClasses("Esme", Set.of("loud"));
assertThat(text) assertThat(text)
.hasVoiceSpanBetween("Text with ".length(), "Text with multiple voice spans".length()) .hasVoiceSpanBetween("Text with ".length(), "Text with multiple voice spans".length())
.withSpeakerNameAndClasses("Mary", Set.of("quiet")); .withSpeakerName("Mary");
} }
private static Spanned parseCueText(String string) { private static Spanned parseCueText(String string) {

View File

@ -1315,18 +1315,15 @@ public final class SpannedSubject extends Subject {
/** Allows assertions about a span's voice its position. */ /** Allows assertions about a span's voice its position. */
public interface VoiceText { public interface VoiceText {
/** /**
* Checks that at least one of the matched spans has the expected {@code name} and {@code * Checks that at least one of the matched spans has the expected {@code name}.
* classes}.
* *
* @param name The expected name of the voice. * @param name The expected name of the voice.
* @param classes The classes used to style the voice.
* @return A {@link AndSpanFlags} object for optional additional assertions on the flags. * @return A {@link AndSpanFlags} object for optional additional assertions on the flags.
*/ */
AndSpanFlags withSpeakerNameAndClasses(String name, Set<String> classes); AndSpanFlags withSpeakerName(String name);
} }
private static final VoiceText ALREADY_FAILED_WITH_NAME_AND_CLASSES = private static final VoiceText ALREADY_FAILED_WITH_NAME_AND_CLASSES = (name) -> ALREADY_FAILED_AND_FLAGS;
(name, classes) -> ALREADY_FAILED_AND_FLAGS;
private static Factory<VoiceSpanSubject, List<VoiceSpan>> voiceSpanSubjects( private static Factory<VoiceSpanSubject, List<VoiceSpan>> voiceSpanSubjects(
Spanned actualSpanned) { Spanned actualSpanned) {
@ -1349,29 +1346,27 @@ public final class SpannedSubject extends Subject {
} }
@Override @Override
public AndSpanFlags withSpeakerNameAndClasses(String name, Set<String> classes) { public AndSpanFlags withSpeakerName(String name) {
List<Integer> matchingSpanFlags = new ArrayList<>(); List<Integer> matchingSpanFlags = new ArrayList<>();
List<SpeakerNameAndClasses> voiceSpeakerNameAndClasses = new ArrayList<>(); List<SpeakerName> voiceSpeakerName = new ArrayList<>();
for (VoiceSpan span : checkNotNull(actualSpans)) { for (VoiceSpan span : checkNotNull(actualSpans)) {
voiceSpeakerNameAndClasses.add(new SpeakerNameAndClasses(span.speakerName, span.classes)); voiceSpeakerNameAndClasses.add(new SpeakerName(span.speakerName));
if (span.speakerName.equals(name) && span.classes.equals(classes)) { if (span.speakerName.equals(name)) {
matchingSpanFlags.add(actualSpanned.getSpanFlags(span)); matchingSpanFlags.add(actualSpanned.getSpanFlags(span));
} }
} }
check("voiceSpeakerNameAndClasses") check("voiceSpeakerName")
.that(voiceSpeakerNameAndClasses) .that(voiceSpeakerNameAndClasses)
.containsExactly(new SpeakerNameAndClasses(name, classes)); .containsExactly(new SpeakerName(name));
return check("flags").about(spanFlags()).that(matchingSpanFlags); return check("flags").about(spanFlags()).that(matchingSpanFlags);
} }
private static final class SpeakerNameAndClasses { private static final class SpeakerName {
private final String speakerName; private final String speakerName;
private final Set<String> classes;
private SpeakerNameAndClasses(String name, Set<String> classes) { private SpeakerName(String name) {
this.speakerName = name; this.speakerName = name;
this.classes = classes;
} }
@Override @Override
@ -1383,18 +1378,18 @@ public final class SpannedSubject extends Subject {
return false; return false;
} }
SpeakerNameAndClasses that = (SpeakerNameAndClasses) o; SpeakerName that = (SpeakerName) o;
return (speakerName.equals(that.speakerName)) && classes.equals(that.classes); return name.equals(that.name);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(speakerName, classes); return Objects.hash(speakerName);
} }
@Override @Override
public String toString() { public String toString() {
return String.format("{speakerName=%s,classes=%s}", speakerName, classes); return String.format("{speakerName=%s}", speakerName);
} }
} }
} }

View File

@ -908,25 +908,25 @@ public class SpannedSubjectTest {
public void voiceSpan_success() { public void voiceSpan_success() {
SpannableString spannable = SpannableString spannable =
createSpannable( createSpannable(
new VoiceSpan("speaker", Set.of("quiet")), new VoiceSpan("speaker"),
Spanned.SPAN_INCLUSIVE_EXCLUSIVE); Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
assertThat(spannable) assertThat(spannable)
.hasVoiceSpanBetween(SPAN_START, SPAN_END) .hasVoiceSpanBetween(SPAN_START, SPAN_END)
.withSpeakerNameAndClasses("speaker", Set.of("quiet")) .withSpeakerName("speaker")
.andFlags(Spanned.SPAN_INCLUSIVE_EXCLUSIVE); .andFlags(Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
} }
@Test @Test
public void voiceSpan_wrongEndIndex() { public void voiceSpan_wrongEndIndex() {
checkHasSpanFailsDueToIndexMismatch( checkHasSpanFailsDueToIndexMismatch(
new VoiceSpan("speaker", Set.of("quiet")), new VoiceSpan("speaker"),
SpannedSubject::hasVoiceSpanBetween); SpannedSubject::hasVoiceSpanBetween);
} }
@Test @Test
public void voiceSpan_wrongSpeakerName() { public void voiceSpan_wrongSpeakerName() {
SpannableString spannable = createSpannable(new VoiceSpan("speaker", Set.of("quiet"))); SpannableString spannable = createSpannable(new VoiceSpan("speaker"));
AssertionError expected = AssertionError expected =
expectFailure( expectFailure(
@ -934,44 +934,27 @@ public class SpannedSubjectTest {
whenTesting whenTesting
.that(spannable) .that(spannable)
.hasVoiceSpanBetween(SPAN_START, SPAN_END) .hasVoiceSpanBetween(SPAN_START, SPAN_END)
.withSpeakerNameAndClasses("different speaker", Set.of("quiet"))); .withSpeakerName("different speaker"));
assertThat(expected).factValue("value of").contains("voiceSpeakerNameAndClasses"); assertThat(expected).factValue("value of").contains("voiceSpeakerName");
assertThat(expected).factValue("expected").contains("speakerName=different speaker"); assertThat(expected).factValue("expected").contains("speakerName=different speaker");
assertThat(expected).factValue("but was").contains("speakerName=speaker"); assertThat(expected).factValue("but was").contains("speakerName=speaker");
} }
@Test
public void voiceSpan_wrongClasses() {
SpannableString spannable = createSpannable(new VoiceSpan("speaker", Set.of("quiet")));
AssertionError expected =
expectFailure(
whenTesting ->
whenTesting
.that(spannable)
.hasVoiceSpanBetween(SPAN_START, SPAN_END)
.withSpeakerNameAndClasses("speaker", Set.of("loud")));
assertThat(expected).factValue("value of").contains("voiceSpeakerNameAndClasses");
assertThat(expected).factValue("expected").contains("classes=[loud]");
assertThat(expected).factValue("but was").contains("classes=[quiet]");
}
@Test @Test
public void voiceSpan_wrongFlags() { public void voiceSpan_wrongFlags() {
checkHasSpanFailsDueToFlagMismatch( checkHasSpanFailsDueToFlagMismatch(
new VoiceSpan("speaker", Set.of("quiet")), new VoiceSpan("speaker"),
(subject, start, end) -> (subject, start, end) ->
subject subject
.hasVoiceSpanBetween(start, end) .hasVoiceSpanBetween(start, end)
.withSpeakerNameAndClasses("speaker", Set.of("quiet"))); .withSpeakerName("speaker"));
} }
@Test @Test
public void noVoiceSpan_success() { public void noVoiceSpan_success() {
SpannableString spannable = SpannableString spannable =
createSpannableWithUnrelatedSpanAnd(new VoiceSpan("speaker", Set.of("quiet"))); createSpannableWithUnrelatedSpanAnd(new VoiceSpan("speaker"));
assertThat(spannable).hasNoVoiceSpanBetween(UNRELATED_SPAN_START, UNRELATED_SPAN_END); assertThat(spannable).hasNoVoiceSpanBetween(UNRELATED_SPAN_START, UNRELATED_SPAN_END);
} }
@ -979,7 +962,7 @@ public class SpannedSubjectTest {
@Test @Test
public void noVoiceSpan_failure() { public void noVoiceSpan_failure() {
checkHasNoSpanFails( checkHasNoSpanFails(
new VoiceSpan("speaker", Set.of("quiet")), new VoiceSpan("speaker"),
SpannedSubject::hasNoVoiceSpanBetween); SpannedSubject::hasNoVoiceSpanBetween);
} }