Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions source/androidx.media3/media3-common/Additions/Tracks.cs
Original file line number Diff line number Diff line change
@@ -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<Tracks.Group>
{
/// <summary>
/// Gets an immutable list of track groups.
/// This implements the missing getGroups() method from the Java API.
/// </summary>
/// <returns>An immutable list of track groups.</returns>
/// <remarks>
/// 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&lt;Tracks.Group&gt; getGroups()
/// </remarks>
public unsafe IList<Tracks.Group>? GetGroups()
{
// Call the native Java getGroups() method
// Based on the AndroidX Media3 documentation, this should return ImmutableList<Group>
const string __id = "getGroups.()Lcom/google/common/collect/ImmutableList;";
try
{
var __rm = _members.InstanceMethods.InvokeNonvirtualObjectMethod(__id, this, null);
return global::Android.Runtime.JavaList<Tracks.Group>.FromJniHandle(__rm.Handle, JniHandleOwnership.TransferLocalRef);
}
finally
{
global::System.GC.KeepAlive(this);
}
}

/// <summary>
/// Gets the track group at the specified index.
/// This method provides access to individual track groups within the Tracks collection.
/// </summary>
/// <param name="index">The index of the group to retrieve.</param>
/// <returns>The track group at the specified index.</returns>
/// <remarks>
/// Each group contains tracks that present the same content but in different formats
/// (different qualities, codecs, languages, etc.).
/// </remarks>
public Tracks.Group? GetGroup(int index)
{
var groups = GetGroups();
if (groups == null || index < 0 || index >= groups.Count)
return null;

return groups[index];
}

/// <summary>
/// Gets the track group at the specified index using indexer syntax.
/// </summary>
/// <param name="index">The index of the group to retrieve.</param>
/// <returns>The track group at the specified index.</returns>
public Tracks.Group? this[int index] => GetGroup(index);

/// <summary>
/// Gets the number of track groups.
/// </summary>
public int Count
{
get
{
var groups = GetGroups();
return groups?.Count ?? 0;
}
}

/// <summary>
/// Returns an enumerator that iterates through the track groups.
/// </summary>
/// <returns>An enumerator for the track groups.</returns>
public IEnumerator<Tracks.Group> GetEnumerator()
{
var groups = GetGroups();
if (groups == null)
return Enumerable.Empty<Tracks.Group>().GetEnumerator();

return groups.GetEnumerator();
}

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.Group!>!
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
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?
Expand All @@ -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<AndroidX.Media3.Common.Tracks.Group!>? 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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Sets the DRM session manager provider and returns the Factory for fluent chaining.
/// </summary>
public static DashMediaSource.Factory SetDrmSessionManagerProviderChained(this DashMediaSource.Factory factory, IDrmSessionManagerProvider? provider)
{
factory.SetDrmSessionManagerProvider(provider);
return factory;
}

/// <summary>
/// Sets the load error handling policy and returns the Factory for fluent chaining.
/// </summary>
public static DashMediaSource.Factory SetLoadErrorHandlingPolicyChained(this DashMediaSource.Factory factory, ILoadErrorHandlingPolicy? policy)
{
factory.SetLoadErrorHandlingPolicy(policy);
return factory;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<AndroidX.Media3.ExoPlayer.Dash.Manifest.BaseUrl!>? 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<string!, string!>? httpRequestHeaders) -> AndroidX.Media3.DataSource.DataSpec?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
<metadata>
<!-- Covariant return type -->
<attr
path="/api/package[@name='androidx.media3.exoplayer.dash']/class[@name='DashMediaSource.Factory']/method[@name='setDrmSessionManagerProvider' and count(parameter)=1 and parameter[1][@type='androidx.media3.exoplayer.drm.DrmSessionManagerProvider']]"
name="managedReturn"
>
AndroidX.Media3.ExoPlayer.Source.IMediaSourceMediaSourceIFactory
</attr>
<attr
path="/api/package[@name='androidx.media3.exoplayer.dash']/class[@name='DashMediaSource.Factory']/method[@name='setLoadErrorHandlingPolicy' and count(parameter)=1 and parameter[1][@type='androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy']]"
name="managedReturn"
>
AndroidX.Media3.ExoPlayer.Source.IMediaSourceMediaSourceIFactory
</attr>
<attr
path="/api/package[@name='androidx.media3.exoplayer.dash.manifest']/class[@name='DashManifestParser']/method[@name='parse' and count(parameter)=2 and parameter[1][@type='android.net.Uri'] and parameter[2][@type='java.io.InputStream']]"
name="managedReturn"
Expand Down Expand Up @@ -48,18 +60,6 @@
>
AndroidX.Media3.ExoPlayer.Source.IMediaSource
</attr>
<attr
path="/api/package[@name='androidx.media3.exoplayer.dash']/class[@name='DashMediaSource.Factory']/method[@name='setDrmSessionManagerProvider' and count(parameter)=1 and parameter[1][@type='androidx.media3.exoplayer.drm.DrmSessionManagerProvider']]"
name="managedReturn"
>
AndroidX.Media3.ExoPlayer.Source.IMediaSourceMediaSourceIFactory
</attr>
<attr
path="/api/package[@name='androidx.media3.exoplayer.dash']/class[@name='DashMediaSource.Factory']/method[@name='setLoadErrorHandlingPolicy' and count(parameter)=1 and parameter[1][@type='androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy']]"
name="managedReturn"
>
AndroidX.Media3.ExoPlayer.Source.IMediaSourceMediaSourceIFactory
</attr>


</metadata>
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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<ITrackSelection?>
{
public ITrackSelection? this[int index] => Get(index);

public IEnumerator<ITrackSelection?> GetEnumerator()
{
for (int i = 0; i < Length; i++)
{
yield return Get(i);
}
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.ITrackSelection?>!
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?
Expand Down