Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented audio selector #92

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions OneDrive-Cloud-Player/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Client;
using OneDrive_Cloud_Player.Models.GraphData;
using OneDrive_Cloud_Player.Models.Interfaces;
using OneDrive_Cloud_Player.Services;
using OneDrive_Cloud_Player.Views;
using System;
Expand Down Expand Up @@ -83,6 +84,7 @@ IServiceProvider ConfigureDependencyInjection()
var serviceCollection = new ServiceCollection();

// Add services for dependency injection here.
serviceCollection.AddTransient<IMediaTrackService, MediaTrackService>();

return serviceCollection.BuildServiceProvider();
}
Expand Down
57 changes: 57 additions & 0 deletions OneDrive-Cloud-Player/Models/Interfaces/IMediaTrackService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using LibVLCSharp.Shared;
using LibVLCSharp.Shared.Structures;
using System.Threading.Tasks;

namespace OneDrive_Cloud_Player.Models.Interfaces
{
public interface IMediaTrackService
{
/// <summary>
/// Needs to be called before using the service and before subscribing to other libvlcsharp events.<br />
/// Due to LibVLCSharp's inability for the MediaPlayer to be put into a service, we need to get a reference to the MediaPlayer ourselves instead.<br />
/// Initialize this service by parsing the MediaPlayer object reference for its media tracks.
/// </summary>
/// <param name="mediaPlayer"></param>
/// <returns></returns>
IMediaTrackService Initialize(ref MediaPlayer mediaPlayer);

/// <summary>
/// Get the preferred subtitle track. When no preferred subtitle track is found, a default will be returned.
/// <br />
/// <i>Note: This method should not be called on a LibVLC thread.
/// <see href="https://code.videolan.org/videolan/LibVLCSharp/-/blob/3.x/docs/best_practices.md#do-not-call-libvlc-from-a-libvlc-event-without-switching-thread-first">Here</see> is more info on why.</i>
/// </summary>
/// <returns><see cref="TrackDescription"/> Preferred subtitle track or default</returns>
/// <exception cref="ServiceNotInitializedException"></exception>
TrackDescription GetPreferredSubtitleTrack();

/// <summary>
/// Get the embedded subtitle tracks in the media file.
/// <br />
/// <i>Note: This method should not be called on a LibVLC thread.
/// <see href="https://code.videolan.org/videolan/LibVLCSharp/-/blob/3.x/docs/best_practices.md#do-not-call-libvlc-from-a-libvlc-event-without-switching-thread-first">Here</see> is more info on why.</i>
/// </summary>
/// <returns>Array containing <see cref="TrackDescription"/>'s or empty when no tracks are available</returns>
TrackDescription[] GetEmbeddedSubtitleTracks();


/// <summary>
/// Get the preferred audio track. When no preferred audio track is found, a default will be returned.
/// <br />
/// <i>Note: This method should not be called on a LibVLC thread.
/// <see href="https://code.videolan.org/videolan/LibVLCSharp/-/blob/3.x/docs/best_practices.md#do-not-call-libvlc-from-a-libvlc-event-without-switching-thread-first">Here</see> is more info on why.</i>
/// </summary>
/// <returns><see cref="TrackDescription"/> Preferred audio track or default</returns>
/// <exception cref="ServiceNotInitializedException"></exception>
TrackDescription GetPreferredAudioTrack();

/// <summary>
/// Get the embedded audio tracks in the media file.
/// <br />
/// <i>Note: This method should not be called on a LibVLC thread.
/// <see href="https://code.videolan.org/videolan/LibVLCSharp/-/blob/3.x/docs/best_practices.md#do-not-call-libvlc-from-a-libvlc-event-without-switching-thread-first">Here</see> is more info on why.</i>
/// </summary>
/// <returns>Array containing <see cref="TrackDescription"/>'s or empty when no tracks are available</returns>
TrackDescription[] GetEmbeddedAudioTracks();
}
}
16 changes: 16 additions & 0 deletions OneDrive-Cloud-Player/OneDrive-Cloud-Player.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,18 @@
<Compile Include="Models\GraphData\CachedDrive.cs" />
<Compile Include="Models\GraphData\CachedDriveItem.cs" />
<Compile Include="Models\GraphData\OneDriveCache.cs" />
<Compile Include="Models\Interfaces\IMediaTrackService.cs" />
<Compile Include="Models\Interfaces\INavigable.cs" />
<Compile Include="Models\MediaWrapper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\Converters\MainPageExplorerConverter.cs" />
<Compile Include="Services\Converters\MediaTimeConverter.cs" />
<Compile Include="Services\Converters\ValueConverterGroup.cs" />
<Compile Include="Services\Helpers\CacheHelper.cs" />
<Compile Include="Services\Helpers\GraphHelper.cs" />
<Compile Include="Services\Helpers\GraphAuthHelper.cs" />
<Compile Include="Services\NavigationService.cs" />
<Compile Include="Services\MediaTrackService.cs" />
<Compile Include="Services\Utilities\JsonHandler.cs" />
<Compile Include="ViewModels\LoginPageViewModel.cs" />
<Compile Include="ViewModels\MainPageViewModel.cs" />
Expand All @@ -154,6 +157,9 @@
<Compile Include="Views\SettingsPage.xaml.cs">
<DependentUpon>SettingsPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SubtitleAudioTrackSelector.xaml.cs">
<DependentUpon>SubtitleAudioTrackSelector.xaml</DependentUpon>
</Compile>
<Compile Include="Views\VideoPlayerPage.xaml.cs">
<DependentUpon>VideoPlayerPage.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -250,6 +256,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\SubtitleAudioTrackSelector.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\VideoPlayerPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down Expand Up @@ -277,6 +287,12 @@
<PackageReference Include="Microsoft.Toolkit.Mvvm">
<Version>7.1.2</Version>
</PackageReference>
<PackageReference Include="Microsoft.Toolkit.Uwp.UI">
<Version>7.1.3</Version>
</PackageReference>
<PackageReference Include="Microsoft.UI.Xaml">
<Version>2.8.2</Version>
</PackageReference>
<PackageReference Include="Microsoft.Xaml.Behaviors.Uwp.Managed">
<Version>2.0.1</Version>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace OneDrive_Cloud_Player.Services.Converters
class MediaTimeConverter : IValueConverter
{
object IValueConverter.Convert(object timeMs, Type targetType, object parameter, string language)
{
{
TimeSpan timeSpan = TimeSpan.FromMilliseconds(Convert.ToDouble(timeMs));
return timeSpan.ToString(@"hh\:mm\:ss");
}
Expand Down
20 changes: 20 additions & 0 deletions OneDrive-Cloud-Player/Services/Converters/ValueConverterGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.UI.Xaml.Data;

namespace OneDrive_Cloud_Player.Services.Converters
{
public class ValueConverterGroup : List<IValueConverter>, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return this.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, language));
}

public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
}
110 changes: 110 additions & 0 deletions OneDrive-Cloud-Player/Services/MediaTrackService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using LibVLCSharp.Shared;
using LibVLCSharp.Shared.Structures;
using OneDrive_Cloud_Player.Models.Interfaces;
using System;
using System.Diagnostics;
using System.Linq;
using Windows.Storage;

namespace OneDrive_Cloud_Player.Services
{
/// <summary>
/// Manage the media tracks of the libvlcsharp media player instance.
/// </summary>
public class MediaTrackService : IMediaTrackService
{
private MediaPlayer _mediaPlayer;
private bool _isInitialized = false;
private readonly ApplicationDataContainer _userSettings;

public MediaTrackService()
{
_userSettings = ApplicationData.Current.LocalSettings;
}

/// <summary>
/// Due to LibVLCSharp's inability for the MediaPlayer to be put into a service, we need to get a reference to the MediaPlayer ourselves instead.
/// Initialize this service by parsing the MediaPlayer object reference for its media tracks.
/// </summary>
public IMediaTrackService Initialize(ref MediaPlayer mediaPlayer)
{
if (_isInitialized)
{
throw new InvalidOperationException("Service already initialized!");
}

Debug.WriteLine(String.Format("initializing {0}", GetType().Name));
_mediaPlayer = mediaPlayer;
_isInitialized = true;
return this;
}

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <exception cref="InvalidOperationException"></exception>
private void CheckInitializationState()
{
if (!_isInitialized)
{
throw new InvalidOperationException("Service not initialized!");
}
}

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns> <inheritdoc/></returns>
public TrackDescription GetPreferredSubtitleTrack()
{
CheckInitializationState();
TrackDescription[] subtitleTracks = _mediaPlayer.SpuDescription;

if (_mediaPlayer.SpuCount <= 1)
{
return default;
}

// Return default track subtitle (when possible, like in mkv) depending on the user setting.
if ((bool)_userSettings.Values["ShowDefaultSubtitles"])
{
return subtitleTracks.First(subtitleTrack => subtitleTrack.Id == _mediaPlayer.Spu);
}
else
{
// Return the "disabled" indicator track positioned at index 0.
return _mediaPlayer.SpuDescription.ElementAt(0);
}
}

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns><inheritdoc/></returns>
public TrackDescription[] GetEmbeddedSubtitleTracks()
{
CheckInitializationState();
return _mediaPlayer.SpuDescription;
}

public TrackDescription GetPreferredAudioTrack()
Copy link

@ThaMe90 ThaMe90 Jun 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing documentation, other methods do have the inheritdoc directives.

{
CheckInitializationState();
TrackDescription[] audioTracks = _mediaPlayer.AudioTrackDescription;

if (_mediaPlayer.AudioTrackCount <= 1)
{
return default;
}

// Return the first actual audio track.
return _mediaPlayer.AudioTrackDescription.ElementAt(1);
}

public TrackDescription[] GetEmbeddedAudioTracks()
Copy link

@ThaMe90 ThaMe90 Jun 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing documentation, other methods do have the inheritdoc directives.

{
CheckInitializationState();
return _mediaPlayer.AudioTrackDescription;
}
}
}
Loading