diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 514c179c93..1d23830c86 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -36,6 +36,11 @@ * Set `compileSdkVersion` to 29 to use Android Q APIs. * Add `enable` and `disable` methods to `MediaSource` to improve resource management in playlists. +* Text selection logic: + * Allow to set preferred role flags using + `DefaultTrackSelector.ParametersBuilder.setPreferredTextRoleFlags`. + * Default text language and role flags to accessibility captioning settings + ([#5749](https://github.com/google/ExoPlayer/issues/5749)). * Remove `AnalyticsCollector.Factory`. Instances can be created directly and the `Player` set later using `AnalyticsCollector.setPlayer`. * Replace `ExoPlayerFactory` by `SimpleExoPlayer.Builder` and diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java index dbbf5deca0..ad606d78dd 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java @@ -474,6 +474,13 @@ public class DefaultTrackSelector extends MappingTrackSelector { // Text + @Override + public ParametersBuilder setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings( + Context context) { + super.setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(context); + return this; + } + @Override public ParametersBuilder setPreferredTextLanguage(@Nullable String preferredTextLanguage) { super.setPreferredTextLanguage(preferredTextLanguage); @@ -499,6 +506,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { super.setDisabledTextTrackSelectionFlags(disabledTextTrackSelectionFlags); return this; } + // General /** @@ -757,6 +765,10 @@ public class DefaultTrackSelector extends MappingTrackSelector { * */ public static final Parameters DEFAULT_WITHOUT_CONTEXT = new Parameters(); @@ -778,6 +790,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { return DEFAULT_WITHOUT_CONTEXT .buildUpon() .setViewportSizeToPhysicalDisplaySize(context, /* viewportOrientationMayChange= */ true) + .setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(context) .build(); } @@ -932,7 +945,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { /* viewportHeight= */ Integer.MAX_VALUE, /* viewportOrientationMayChange= */ true, // Audio - TrackSelectionParameters.DEFAULT.preferredAudioLanguage, + TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT.preferredAudioLanguage, /* maxAudioChannelCount= */ Integer.MAX_VALUE, /* maxAudioBitrate= */ Integer.MAX_VALUE, /* exceedAudioConstraintsIfNecessary= */ true, @@ -940,10 +953,10 @@ public class DefaultTrackSelector extends MappingTrackSelector { /* allowAudioMixedSampleRateAdaptiveness= */ false, /* allowAudioMixedChannelCountAdaptiveness= */ false, // Text - TrackSelectionParameters.DEFAULT.preferredTextLanguage, - TrackSelectionParameters.DEFAULT.preferredTextRoleFlags, - TrackSelectionParameters.DEFAULT.selectUndeterminedTextLanguage, - TrackSelectionParameters.DEFAULT.disabledTextTrackSelectionFlags, + TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT.preferredTextLanguage, + TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT.preferredTextRoleFlags, + TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT.selectUndeterminedTextLanguage, + TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT.disabledTextTrackSelectionFlags, // General /* forceLowestBitrate= */ false, /* forceHighestSupportedBitrate= */ false, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java index e31c4f51b8..dca9aef209 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java @@ -15,12 +15,16 @@ */ package com.google.android.exoplayer2.trackselection; +import android.annotation.TargetApi; +import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.view.accessibility.CaptioningManager; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Util; +import java.util.Locale; /** Constraint parameters for track selection. */ public class TrackSelectionParameters implements Parcelable { @@ -37,9 +41,22 @@ public class TrackSelectionParameters implements Parcelable { /* package */ boolean selectUndeterminedTextLanguage; @C.SelectionFlags /* package */ int disabledTextTrackSelectionFlags; - /** Creates a builder with default initial values. */ + /** + * Creates a builder with default initial values. + * + * @param context Any context. + */ + public Builder(Context context) { + this(TrackSelectionParameters.getDefaults(context)); + } + + /** + * @deprecated {@link Context} constraints will not be set when using this constructor. Use + * {@link #Builder(Context)} instead. + */ + @Deprecated public Builder() { - this(DEFAULT); + this(DEFAULT_WITHOUT_CONTEXT); } /** @@ -66,6 +83,23 @@ public class TrackSelectionParameters implements Parcelable { return this; } + /** + * Sets the preferred language and role flags for text tracks based on the accessibility + * settings of {@link CaptioningManager}. + * + *

Does nothing for API levels < 19 or when the {@link CaptioningManager} is disabled. + * + * @param context A {@link Context}. + * @return This builder. + */ + public Builder setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings( + Context context) { + if (Util.SDK_INT >= 19) { + setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettingsV19(context); + } + return this; + } + /** * Sets the preferred language for text tracks. * @@ -127,10 +161,52 @@ public class TrackSelectionParameters implements Parcelable { selectUndeterminedTextLanguage, disabledTextTrackSelectionFlags); } + + @TargetApi(19) + private void setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettingsV19( + Context context) { + CaptioningManager captioningManager = + (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE); + if (captioningManager == null || !captioningManager.isEnabled()) { + return; + } + preferredTextRoleFlags = C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND; + Locale preferredLocale = captioningManager.getLocale(); + if (preferredLocale != null) { + preferredTextLanguage = Util.getLocaleLanguageTag(preferredLocale); + } + } } - /** An instance with default values. */ - public static final TrackSelectionParameters DEFAULT = new TrackSelectionParameters(); + /** + * An instance with default values, except those obtained from the {@link Context}. + * + *

If possible, use {@link #getDefaults(Context)} instead. + * + *

This instance will not have the following settings: + * + *

+ */ + public static final TrackSelectionParameters DEFAULT_WITHOUT_CONTEXT = + new TrackSelectionParameters(); + + /** + * @deprecated This instance is not configured using {@link Context} constraints. Use {@link + * #getDefaults(Context)} instead. + */ + @Deprecated public static final TrackSelectionParameters DEFAULT = new TrackSelectionParameters(); + + /** Returns an instance configured with default values. */ + public static TrackSelectionParameters getDefaults(Context context) { + return DEFAULT_WITHOUT_CONTEXT + .buildUpon() + .setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(context) + .build(); + } /** * The preferred language for audio and forced text tracks as an IETF BCP 47 conformant tag. @@ -140,12 +216,15 @@ public class TrackSelectionParameters implements Parcelable { @Nullable public final String preferredAudioLanguage; /** * The preferred language for text tracks as an IETF BCP 47 conformant tag. {@code null} selects - * the default track if there is one, or no track otherwise. The default value is {@code null}. + * the default track if there is one, or no track otherwise. The default value is {@code null}, or + * the language of the accessibility {@link CaptioningManager} if enabled. */ @Nullable public final String preferredTextLanguage; /** * The preferred {@link C.RoleFlags} for text tracks. {@code 0} selects the default track if there - * is one, or no track otherwise. The default value is {@code 0}. + * is one, or no track otherwise. The default value is {@code 0}, or {@link C#ROLE_FLAG_SUBTITLE} + * | {@link C#ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND} if the accessibility {@link CaptioningManager} + * is enabled. */ @C.RoleFlags public final int preferredTextRoleFlags; /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/Util.java b/library/core/src/main/java/com/google/android/exoplayer2/util/Util.java index e7a1f2e92e..cbd246cf22 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -459,6 +459,20 @@ public final class Util { parcel.writeInt(value ? 1 : 0); } + /** + * Returns the language tag for a {@link Locale}. + * + *

For API levels ≥ 21, this tag is IETF BCP 47 compliant. Use {@link + * #normalizeLanguageCode(String)} to retrieve a normalized IETF BCP 47 language tag for all API + * levels if needed. + * + * @param locale A {@link Locale}. + * @return The language tag. + */ + public static String getLocaleLanguageTag(Locale locale) { + return SDK_INT >= 21 ? getLocaleLanguageTagV21(locale) : locale.toString(); + } + /** * Returns a normalized IETF BCP 47 language tag for {@code language}. * @@ -1963,7 +1977,7 @@ public final class Util { Configuration config = Resources.getSystem().getConfiguration(); return SDK_INT >= 24 ? getSystemLocalesV24(config) - : SDK_INT >= 21 ? getSystemLocaleV21(config) : new String[] {config.locale.toString()}; + : new String[] {getLocaleLanguageTag(config.locale)}; } @TargetApi(24) @@ -1972,8 +1986,8 @@ public final class Util { } @TargetApi(21) - private static String[] getSystemLocaleV21(Configuration config) { - return new String[] {config.locale.toLanguageTag()}; + private static String getLocaleLanguageTagV21(Locale locale) { + return locale.toLanguageTag(); } @TargetApi(21)