diff --git a/source/androidx.media3/media3-common/Additions/Tracks.cs b/source/androidx.media3/media3-common/Additions/Tracks.cs new file mode 100644 index 000000000..7bcb146ae --- /dev/null +++ b/source/androidx.media3/media3-common/Additions/Tracks.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using System.Linq; +using Java.Interop; +using Android.Runtime; + +namespace AndroidX.Media3.Common; + +// Convenience additions to make the modern Media3 Tracks API usable following API guidelines. +// Enables: player.getCurrentTracks().getGroups() and iteration over track groups. +public partial class Tracks : System.Collections.Generic.IEnumerable +{ + /// + /// Gets an immutable list of track groups. + /// This implements the missing getGroups() method from the Java API. + /// + /// An immutable list of track groups. + /// + /// This method provides access to the track groups, where each group contains tracks that + /// present the same content but in different formats (different qualities, codecs, languages, etc.). + /// + /// This matches the Java API: public ImmutableList<Tracks.Group> getGroups() + /// + public unsafe IList? GetGroups() + { + // Call the native Java getGroups() method + // Based on the AndroidX Media3 documentation, this should return ImmutableList + const string __id = "getGroups.()Lcom/google/common/collect/ImmutableList;"; + try + { + var __rm = _members.InstanceMethods.InvokeNonvirtualObjectMethod(__id, this, null); + return global::Android.Runtime.JavaList.FromJniHandle(__rm.Handle, JniHandleOwnership.TransferLocalRef); + } + finally + { + global::System.GC.KeepAlive(this); + } + } + + /// + /// Gets the track group at the specified index. + /// This method provides access to individual track groups within the Tracks collection. + /// + /// The index of the group to retrieve. + /// The track group at the specified index. + /// + /// Each group contains tracks that present the same content but in different formats + /// (different qualities, codecs, languages, etc.). + /// + public Tracks.Group? GetGroup(int index) + { + var groups = GetGroups(); + if (groups == null || index < 0 || index >= groups.Count) + return null; + + return groups[index]; + } + + /// + /// Gets the track group at the specified index using indexer syntax. + /// + /// The index of the group to retrieve. + /// The track group at the specified index. + public Tracks.Group? this[int index] => GetGroup(index); + + /// + /// Gets the number of track groups. + /// + public int Count + { + get + { + var groups = GetGroups(); + return groups?.Count ?? 0; + } + } + + /// + /// Returns an enumerator that iterates through the track groups. + /// + /// An enumerator for the track groups. + public IEnumerator GetEnumerator() + { + var groups = GetGroups(); + if (groups == null) + return Enumerable.Empty().GetEnumerator(); + + return groups.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); +} diff --git a/source/androidx.media3/media3-common/PublicAPI/PublicAPI.Unshipped.txt b/source/androidx.media3/media3-common/PublicAPI/PublicAPI.Unshipped.txt index 2633e6e03..1aa4ab231 100644 --- a/source/androidx.media3/media3-common/PublicAPI/PublicAPI.Unshipped.txt +++ b/source/androidx.media3/media3-common/PublicAPI/PublicAPI.Unshipped.txt @@ -1965,6 +1965,10 @@ AndroidX.Media3.Common.TrackSelectionParametersChangedEventArgs.Parameters.get - AndroidX.Media3.Common.TrackSelectionParametersChangedEventArgs.TrackSelectionParametersChangedEventArgs(AndroidX.Media3.Common.TrackSelectionParameters? parameters) -> void AndroidX.Media3.Common.Tracks AndroidX.Media3.Common.Tracks.ContainsType(int trackType) -> bool +AndroidX.Media3.Common.Tracks.Count.get -> int +AndroidX.Media3.Common.Tracks.GetEnumerator() -> System.Collections.Generic.IEnumerator! +AndroidX.Media3.Common.Tracks.GetGroup(int index) -> AndroidX.Media3.Common.Tracks.Group? +AndroidX.Media3.Common.Tracks.GetGroups() -> System.Collections.Generic.IList? AndroidX.Media3.Common.Tracks.Group AndroidX.Media3.Common.Tracks.Group.CopyWithId(string? groupId) -> AndroidX.Media3.Common.Tracks.Group? AndroidX.Media3.Common.Tracks.Group.GetTrackFormat(int trackIndex) -> AndroidX.Media3.Common.Format? @@ -1990,6 +1994,7 @@ AndroidX.Media3.Common.Tracks.IsTypeSupportedOrEmpty(int trackType) -> bool AndroidX.Media3.Common.Tracks.IsTypeSupportedOrEmpty(int trackType, bool allowExceedsCapabilities) -> bool AndroidX.Media3.Common.Tracks.ToBundle() -> Android.OS.Bundle? AndroidX.Media3.Common.Tracks.Tracks(System.Collections.Generic.IList? groups) -> void +AndroidX.Media3.Common.Tracks.this[int index].get -> AndroidX.Media3.Common.Tracks.Group? AndroidX.Media3.Common.TracksChangedEventArgs AndroidX.Media3.Common.TracksChangedEventArgs.Tracks.get -> AndroidX.Media3.Common.Tracks? AndroidX.Media3.Common.TracksChangedEventArgs.TracksChangedEventArgs(AndroidX.Media3.Common.Tracks? tracks) -> void diff --git a/source/androidx.media3/media3-exoplayer-dash/Additions/DashMediaSource.Factory.cs b/source/androidx.media3/media3-exoplayer-dash/Additions/DashMediaSource.Factory.cs new file mode 100644 index 000000000..30bf89d32 --- /dev/null +++ b/source/androidx.media3/media3-exoplayer-dash/Additions/DashMediaSource.Factory.cs @@ -0,0 +1,46 @@ +using AndroidX.Media3.ExoPlayer.Drm; +using AndroidX.Media3.ExoPlayer.Source; +using AndroidX.Media3.ExoPlayer.Upstream; + +namespace AndroidX.Media3.ExoPlayer.Dash +{ + public sealed partial class DashMediaSource + { + public sealed partial class Factory + { + // Extension methods for fluent API chaining with concrete return type + public Factory SetDrmSessionManagerProviderFluent(IDrmSessionManagerProvider? drmSessionManagerProvider) + { + SetDrmSessionManagerProvider(drmSessionManagerProvider); + return this; + } + + public Factory SetLoadErrorHandlingPolicyFluent(ILoadErrorHandlingPolicy? loadErrorHandlingPolicy) + { + SetLoadErrorHandlingPolicy(loadErrorHandlingPolicy); + return this; + } + } + } + + public static class DashMediaSourceFactoryExtensions + { + /// + /// Sets the DRM session manager provider and returns the Factory for fluent chaining. + /// + public static DashMediaSource.Factory SetDrmSessionManagerProviderChained(this DashMediaSource.Factory factory, IDrmSessionManagerProvider? provider) + { + factory.SetDrmSessionManagerProvider(provider); + return factory; + } + + /// + /// Sets the load error handling policy and returns the Factory for fluent chaining. + /// + public static DashMediaSource.Factory SetLoadErrorHandlingPolicyChained(this DashMediaSource.Factory factory, ILoadErrorHandlingPolicy? policy) + { + factory.SetLoadErrorHandlingPolicy(policy); + return factory; + } + } +} diff --git a/source/androidx.media3/media3-exoplayer-dash/PublicAPI/PublicAPI.Unshipped.txt b/source/androidx.media3/media3-exoplayer-dash/PublicAPI/PublicAPI.Unshipped.txt index 79ee261b4..5cd51282f 100644 --- a/source/androidx.media3/media3-exoplayer-dash/PublicAPI/PublicAPI.Unshipped.txt +++ b/source/androidx.media3/media3-exoplayer-dash/PublicAPI/PublicAPI.Unshipped.txt @@ -20,13 +20,16 @@ AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.GetSupportedTypes() -> in AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.SetCmcdConfigurationFactory(AndroidX.Media3.ExoPlayer.Upstream.CmcdConfiguration.IFactory? cmcdConfigurationFactory) -> AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory? AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.SetCompositeSequenceableLoaderFactory(AndroidX.Media3.ExoPlayer.Source.ICompositeSequenceableLoaderFactory? compositeSequenceableLoaderFactory) -> AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory? AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.SetDrmSessionManagerProvider(AndroidX.Media3.ExoPlayer.Drm.IDrmSessionManagerProvider? drmSessionManagerProvider) -> AndroidX.Media3.ExoPlayer.Source.IMediaSourceMediaSourceIFactory? +AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.SetDrmSessionManagerProviderFluent(AndroidX.Media3.ExoPlayer.Drm.IDrmSessionManagerProvider? drmSessionManagerProvider) -> AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory! AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.SetFallbackTargetLiveOffsetMs(long fallbackTargetLiveOffsetMs) -> AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory? AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.SetLoadErrorHandlingPolicy(AndroidX.Media3.ExoPlayer.Upstream.ILoadErrorHandlingPolicy? loadErrorHandlingPolicy) -> AndroidX.Media3.ExoPlayer.Source.IMediaSourceMediaSourceIFactory? +AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.SetLoadErrorHandlingPolicyFluent(AndroidX.Media3.ExoPlayer.Upstream.ILoadErrorHandlingPolicy? loadErrorHandlingPolicy) -> AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory! AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.SetManifestParser(AndroidX.Media3.ExoPlayer.Upstream.ParsingLoadable.IParser? manifestParser) -> AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory? AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.SetMinLiveStartPositionUs(long minLiveStartPositionUs) -> AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory? AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory.SetSubtitleParserFactory(AndroidX.Media3.Extractor.Text.ISubtitleParserFactory? subtitleParserFactory) -> AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory? AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.ReplaceManifestUri(Android.Net.Uri? manifestUri) -> void AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.UpdateMediaItem(AndroidX.Media3.Common.MediaItem? mediaItem) -> void +AndroidX.Media3.ExoPlayer.Dash.DashMediaSourceFactoryExtensions AndroidX.Media3.ExoPlayer.Dash.DashUtil AndroidX.Media3.ExoPlayer.Dash.DashWrappingSegmentIndex AndroidX.Media3.ExoPlayer.Dash.DashWrappingSegmentIndex.DashWrappingSegmentIndex(AndroidX.Media3.Extractor.ChunkIndex? chunkIndex, long timeOffsetUs) -> void @@ -395,6 +398,8 @@ override AndroidX.Media3.ExoPlayer.Dash.Offline.DashDownloader.JniPeerMembers.ge override AndroidX.Media3.ExoPlayer.Dash.PlayerEmsgHandler.JniPeerMembers.get -> Java.Interop.JniPeerMembers! override AndroidX.Media3.ExoPlayer.Dash.PlayerEmsgHandler.PlayerTrackEmsgHandler.JniPeerMembers.get -> Java.Interop.JniPeerMembers! static AndroidX.Media3.ExoPlayer.Dash.BaseUrlExclusionList.GetPriorityCount(System.Collections.Generic.IList? baseUrls) -> int +static AndroidX.Media3.ExoPlayer.Dash.DashMediaSourceFactoryExtensions.SetDrmSessionManagerProviderChained(this AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory! factory, AndroidX.Media3.ExoPlayer.Drm.IDrmSessionManagerProvider? provider) -> AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory! +static AndroidX.Media3.ExoPlayer.Dash.DashMediaSourceFactoryExtensions.SetLoadErrorHandlingPolicyChained(this AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory! factory, AndroidX.Media3.ExoPlayer.Upstream.ILoadErrorHandlingPolicy? policy) -> AndroidX.Media3.ExoPlayer.Dash.DashMediaSource.Factory! static AndroidX.Media3.ExoPlayer.Dash.DashUtil.BuildDataSpec(AndroidX.Media3.ExoPlayer.Dash.Manifest.Representation? representation, AndroidX.Media3.ExoPlayer.Dash.Manifest.RangedUri? requestUri, int flags) -> AndroidX.Media3.DataSource.DataSpec? static AndroidX.Media3.ExoPlayer.Dash.DashUtil.BuildDataSpec(AndroidX.Media3.ExoPlayer.Dash.Manifest.Representation? representation, string? baseUrl, AndroidX.Media3.ExoPlayer.Dash.Manifest.RangedUri? requestUri, int flags) -> AndroidX.Media3.DataSource.DataSpec? static AndroidX.Media3.ExoPlayer.Dash.DashUtil.BuildDataSpec(AndroidX.Media3.ExoPlayer.Dash.Manifest.Representation? representation, string? baseUrl, AndroidX.Media3.ExoPlayer.Dash.Manifest.RangedUri? requestUri, int flags, System.Collections.Generic.IDictionary? httpRequestHeaders) -> AndroidX.Media3.DataSource.DataSpec? diff --git a/source/androidx.media3/media3-exoplayer-dash/Transforms/Metadata.xml b/source/androidx.media3/media3-exoplayer-dash/Transforms/Metadata.xml index 00011b88c..a4e59bca1 100644 --- a/source/androidx.media3/media3-exoplayer-dash/Transforms/Metadata.xml +++ b/source/androidx.media3/media3-exoplayer-dash/Transforms/Metadata.xml @@ -1,5 +1,17 @@  + + AndroidX.Media3.ExoPlayer.Source.IMediaSourceMediaSourceIFactory + + + AndroidX.Media3.ExoPlayer.Source.IMediaSourceMediaSourceIFactory + AndroidX.Media3.ExoPlayer.Source.IMediaSource - - AndroidX.Media3.ExoPlayer.Source.IMediaSourceMediaSourceIFactory - - - AndroidX.Media3.ExoPlayer.Source.IMediaSourceMediaSourceIFactory - \ No newline at end of file diff --git a/source/androidx.media3/media3-exoplayer/Additions/TrackGroupArray.cs b/source/androidx.media3/media3-exoplayer/Additions/TrackGroupArray.cs new file mode 100644 index 000000000..d184d80b0 --- /dev/null +++ b/source/androidx.media3/media3-exoplayer/Additions/TrackGroupArray.cs @@ -0,0 +1,12 @@ +using AndroidX.Media3.Common; + +namespace AndroidX.Media3.ExoPlayer.Source; + +// Convenience additions to match common ExoPlayer Java samples (trackGroups.get(i)) +// and the intuitive GetGroup(...) naming some developers attempt to use. +public partial class TrackGroupArray +{ + + // Indexer for more idiomatic C# access: trackGroups[i] + public TrackGroup? this[int index] => Get(index); +} diff --git a/source/androidx.media3/media3-exoplayer/Additions/TrackSelectionArray.additions.cs b/source/androidx.media3/media3-exoplayer/Additions/TrackSelectionArray.additions.cs new file mode 100644 index 000000000..bdbdf756b --- /dev/null +++ b/source/androidx.media3/media3-exoplayer/Additions/TrackSelectionArray.additions.cs @@ -0,0 +1,23 @@ +// Additions to improve .NET ergonomics for TrackSelectionArray +// Provides indexer and IEnumerable implementation for iterating track selections. + +using System.Collections; +using System.Collections.Generic; + +namespace AndroidX.Media3.ExoPlayer.TrackSelection +{ + public partial class TrackSelectionArray : IEnumerable + { + public ITrackSelection? this[int index] => Get(index); + + public IEnumerator GetEnumerator() + { + for (int i = 0; i < Length; i++) + { + yield return Get(i); + } + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} diff --git a/source/androidx.media3/media3-exoplayer/PublicAPI/PublicAPI.Unshipped.txt b/source/androidx.media3/media3-exoplayer/PublicAPI/PublicAPI.Unshipped.txt index f8251de38..a2c1575fa 100644 --- a/source/androidx.media3/media3-exoplayer/PublicAPI/PublicAPI.Unshipped.txt +++ b/source/androidx.media3/media3-exoplayer/PublicAPI/PublicAPI.Unshipped.txt @@ -3452,6 +3452,7 @@ AndroidX.Media3.ExoPlayer.Source.TrackGroupArray.Length.get -> int AndroidX.Media3.ExoPlayer.Source.TrackGroupArray.Length.set -> void AndroidX.Media3.ExoPlayer.Source.TrackGroupArray.ToBundle() -> Android.OS.Bundle? AndroidX.Media3.ExoPlayer.Source.TrackGroupArray.TrackGroupArray(params AndroidX.Media3.Common.TrackGroup![]? trackGroups) -> void +AndroidX.Media3.ExoPlayer.Source.TrackGroupArray.this[int index].get -> AndroidX.Media3.Common.TrackGroup? AndroidX.Media3.ExoPlayer.Source.UnrecognizedInputFormatException AndroidX.Media3.ExoPlayer.Source.UnrecognizedInputFormatException.UnrecognizedInputFormatException(nint javaReference, Android.Runtime.JniHandleOwnership transfer) -> void AndroidX.Media3.ExoPlayer.Source.UnrecognizedInputFormatException.UnrecognizedInputFormatException(string? message, Android.Net.Uri? uri) -> void @@ -3705,9 +3706,11 @@ AndroidX.Media3.ExoPlayer.TrackSelection.RandomTrackSelection.RandomTrackSelecti AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionArray AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionArray.Get(int index) -> AndroidX.Media3.ExoPlayer.TrackSelection.ITrackSelection? AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionArray.GetAll() -> AndroidX.Media3.ExoPlayer.TrackSelection.ITrackSelection![]? +AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionArray.GetEnumerator() -> System.Collections.Generic.IEnumerator! AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionArray.Length.get -> int AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionArray.Length.set -> void AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionArray.TrackSelectionArray(params AndroidX.Media3.ExoPlayer.TrackSelection.ITrackSelection![]? trackSelections) -> void +AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionArray.this[int index].get -> AndroidX.Media3.ExoPlayer.TrackSelection.ITrackSelection? AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionUtil AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionUtil.IAdaptiveTrackSelectionFactory AndroidX.Media3.ExoPlayer.TrackSelection.TrackSelectionUtil.IAdaptiveTrackSelectionFactory.CreateAdaptiveTrackSelection(AndroidX.Media3.ExoPlayer.TrackSelection.ExoTrackSelectionDefinition? p0) -> AndroidX.Media3.ExoPlayer.TrackSelection.IExoTrackSelection?