Skip to content
Merged
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
4 changes: 2 additions & 2 deletions CastIt.Application/CastIt.Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.29" />
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="4.0.0" />
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.0.0" />
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="4.1.0" />
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.Management" Version="5.0.0" />
Expand Down
2 changes: 1 addition & 1 deletion CastIt.Application/FFmpeg/FFmpegService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public string GetThumbnail(string mrl)
}

var filename = Path.GetFileName(mrl);
var thumbnailPath = _fileService.GetThumbnailFilePath(filename, 0);
var thumbnailPath = _fileService.GetFirstThumbnailFilePath(filename);
if (File.Exists(thumbnailPath))
{
return thumbnailPath;
Expand Down
3 changes: 3 additions & 0 deletions CastIt.Application/FilePaths/FileService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ public string GetSubTitleFolder()
return CreateDirectory(basePath, SubTitlesFolderName);
}

public string GetFirstThumbnailFilePath(string filename)
=> GetThumbnailFilePath(filename, 0);

public string GetThumbnailFilePath(string filename, long second)
{
return Path.Combine(GetPreviewsPath(), $"{filename}_{second:D2}.jpg");
Expand Down
2 changes: 2 additions & 0 deletions CastIt.Application/Interfaces/IFileService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public interface IFileService : ICommonFileService

string GetPreviewsPath();

string GetFirstThumbnailFilePath(string filename);

string GetThumbnailFilePath(string filename, long second);

string GetPreviewThumbnailFilePath(string filename);
Expand Down
39 changes: 23 additions & 16 deletions CastIt.Application/Youtube/YoutubeUrlDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -455,27 +455,29 @@ private Dictionary<int, string> GetVideoQualities(string body)
_logger.LogInformation($"{nameof(GetVideoQualities)}: Getting video qualities...");
var formatPattern = @"(\\""formats\\"":\[.*?])";
var formatMatch = Regex.Match(body, formatPattern);

if (formatMatch.Length == 0)
{
_logger.LogInformation($"{nameof(GetVideoQualities)}: Couldn't retrieve formats, checking if we have adaptiveFormats...");
formatPattern = @"(\\""adaptiveFormats\\"":\[.*?])";
_logger.LogInformation(
$"{nameof(GetVideoQualities)}: Couldn't retrieve formats, " +
"checking if the formats is not between slashes using the format keyword...");
formatPattern = @"(\""formats\"":\[.*?])";
formatMatch = Regex.Match(body, formatPattern);
}

if (formatMatch.Length == 0)
{
_logger.LogInformation(
$"{nameof(GetVideoQualities)}: Couldn't retrieve formats, " +
"checking if the formats is not between slashes using the format keyword...");
formatPattern = @"(\""formats\"":\[.*?])";
$"{nameof(GetVideoQualities)}: Couldn't retrieve formats, checking if we have adaptive formats...");
formatPattern = @"(\\""adaptiveFormats\\"":\[.*?])";
formatMatch = Regex.Match(body, formatPattern);
}

if (formatMatch.Length == 0)
{
_logger.LogInformation(
$"{nameof(GetVideoQualities)}: Couldn't retrieve formats, " +
"checking if the formats is not between slashes using the adaptiveFormats keyword...");
$"{nameof(GetVideoQualities)}: Couldn't retrieve adaptive formats, " +
"checking if the formats is not between slashes using the format keyword...");
formatPattern = @"(\""adaptiveFormats\"":\[.*?])";
formatMatch = Regex.Match(body, formatPattern);
}
Expand All @@ -491,24 +493,29 @@ private Dictionary<int, string> GetVideoQualities(string body)
string heightPatternA = @"(?<=\\""height\\"":).+?(?=,)";
string heightPatternB = @"(?<=\""height\"":).+?(?=,)";
var streams = Regex.Matches(streamMap, "{(.*?)}").AsQueryable().OfType<Match>().ToList();
var qualities = streams.ToDictionary(k =>

var qualitiesDictionary = new Dictionary<int, string>();
foreach (var stream in streams)
{
var val = Regex.Match(k.ToString(), heightPatternA).Value;
var match = stream.Value;
var val = Regex.Match(match, heightPatternA).Value;
if (string.IsNullOrEmpty(val))
{
_logger.LogInformation($"Couldn't retrieve height, trying now without backslashes in the pattern");
val = Regex.Match(k.ToString(), heightPatternB).Value;
_logger.LogInformation("Couldn't retrieve height, trying now without backslashes in the pattern");
val = Regex.Match(match, heightPatternB).Value;
}

if (string.IsNullOrEmpty(val))
{
_logger.LogWarning($"Couldn't retrieve height from = {k}");
_logger.LogWarning($"Couldn't retrieve height from = {match}");
}

return int.Parse(string.IsNullOrEmpty(val) ? "-1" : val);
}, v => v.ToString());

var qualitiesDictionary = qualities.Where(kvp => kvp.Key > 0).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
int quality = int.Parse(string.IsNullOrEmpty(val) ? "-1" : val);
if (!qualitiesDictionary.ContainsKey(quality) && quality > 0)
{
qualitiesDictionary.Add(quality, match);
}
}

_logger.LogInformation($"{nameof(GetVideoQualities)}: Got = {qualitiesDictionary.Count} video qualities");

Expand Down
4 changes: 2 additions & 2 deletions CastIt.Cli/CastIt.Cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

<ItemGroup>
<PackageReference Include="ConsoleTables" Version="2.4.2" />
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="3.0.0" />
<PackageReference Include="McMaster.Extensions.Hosting.CommandLine" Version="3.0.0" />
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="3.1.0" />
<PackageReference Include="McMaster.Extensions.Hosting.CommandLine" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Refit.HttpClientFactory" Version="5.2.4" />
Expand Down
10 changes: 8 additions & 2 deletions CastIt.Domain/Models/FFmpeg/Info/FileInfoStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,18 @@ public class FileInfoStream
[JsonProperty(PropertyName = "sample_rate")]
public long SampleRate { get; set; }

[JsonProperty(PropertyName = "nb_frames")]
public long NumberOfFrames { get; set; }

[JsonProperty(PropertyName = "avg_frame_rate")]
public string AverageFrameRate { get; set; }

[JsonProperty(PropertyName = "tags")]
public FileInfoTag Tag { get; set; }

//The CodecType in an audio returns may return video if the stream is a png img
//The CodecType in an audio file may return video if the stream is a png img
public bool IsVideo
=> CodecType == "video" && Level > 0;
=> CodecType == "video" && Level != 0 && (NumberOfFrames > 1 || AverageFrameRate != "0/0");

public bool IsAudio
=> CodecType == "audio";
Expand Down
1 change: 1 addition & 0 deletions CastIt.Infrastructure/Interfaces/IAppSettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public interface IAppSettingsService
bool EnableHardwareAcceleration { get; set; }
bool MinimizeToTray { get; set; }
bool ShowPlayListTotalDuration { get; set; }
bool UseGridViewForPlayLists { get; set; }

SubtitleFgColorType CurrentSubtitleFgColor { get; set; }
SubtitleBgColorType CurrentSubtitleBgColor { get; set; }
Expand Down
2 changes: 2 additions & 0 deletions CastIt.Infrastructure/Models/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ internal class AppSettings
public bool EnableHardwareAcceleration { get; set; }
public bool MinimizeToTray { get; set; }
public bool ShowPlayListTotalDuration { get; set; }
public bool UseGridViewForPlayLists { get; set; }

public SubtitleFgColorType CurrentSubtitleFgColor { get; set; }
public SubtitleBgColorType CurrentSubtitleBgColor { get; set; }
public SubtitleFontScaleType CurrentSubtitleFontScale { get; set; }
Expand Down
6 changes: 6 additions & 0 deletions CastIt.Infrastructure/Services/AppSettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ public bool ShowPlayListTotalDuration
set => _appSettings.ShowPlayListTotalDuration = value;
}

public bool UseGridViewForPlayLists
{
get => _appSettings.UseGridViewForPlayLists;
set => _appSettings.UseGridViewForPlayLists = value;
}

public SubtitleFgColorType CurrentSubtitleFgColor
{
get => _appSettings.CurrentSubtitleFgColor;
Expand Down
3 changes: 3 additions & 0 deletions CastIt/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<converters:FileOptionsMultiConverter x:Key="FileOptionsMultiConverter" />
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" />
<converters:BooleanOrConverter x:Key="BooleanOrConverter" />
<converters:PlayListCardItemMultiConverter x:Key="PlayListCardItemMultiConverter" />
<converters:NumberComparerToBooleanConverter x:Key="EqualToBooleanConverter" Equal="True" />
<converters:NumberComparerToBooleanConverter x:Key="GreaterThanToBooleanConverter" GreaterThan="True" />

<SolidColorBrush x:Key="FontColorOnDarkBackgroundBrush" Color="White" />
<BitmapImage x:Key="NoImgFound" UriSource="/Resources/NoImg.png" />
Expand Down
6 changes: 3 additions & 3 deletions CastIt/CastIt.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="10.1.1" />
<PackageReference Include="Dragablz.NetCore" Version="0.3.3" />
<PackageReference Include="FluentMigrator" Version="3.2.10" />
<PackageReference Include="FluentMigrator.Runner" Version="3.2.10" />
<PackageReference Include="FluentMigrator" Version="3.2.11" />
<PackageReference Include="FluentMigrator.Runner" Version="3.2.11" />
<PackageReference Include="FreeSql.Provider.Sqlite" Version="2.0.105" />
<PackageReference Include="MaterialDesignThemes" Version="3.2.0-ci1901" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.31" />
<PackageReference Include="MvvmCross.Platforms.Wpf" Version="7.1.2" />
<PackageReference Include="MvvmCross.Plugin.Messenger" Version="7.1.2" />
<PackageReference Include="MvvmCross.Plugin.ResxLocalization" Version="7.1.2" />
Expand Down
82 changes: 54 additions & 28 deletions CastIt/Common/Behaviours/MultiSelectionBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,51 @@ namespace CastIt.Common.Behaviours
/// </summary>
public class MultiSelectionBehavior : Behavior<ListBox>
{
private bool _isUpdatingTarget;
private bool _isUpdatingSource;

public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(IList), typeof(MultiSelectionBehavior), new UIPropertyMetadata(null, SelectedItemsChanged));

public IList SelectedItems
{
get => (IList)GetValue(SelectedItemsProperty);
set => SetValue(SelectedItemsProperty, value);
}

protected override void OnAttached()
{
AssociatedObject.Unloaded += OnUnloaded;
base.OnAttached();
if (SelectedItems != null)
if (SelectedItems == null)
return;
AssociatedObject.SelectedItems.Clear();
foreach (var item in SelectedItems)
{
AssociatedObject.SelectedItems.Clear();
foreach (var item in SelectedItems)
{
AssociatedObject.SelectedItems.Add(item);
}
AssociatedObject.SelectedItems.Add(item);
}
}

public IList SelectedItems
private void OnUnloaded(object sender, RoutedEventArgs e)
{
get { return (IList)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
OnDetaching();
}

public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(IList), typeof(MultiSelectionBehavior), new UIPropertyMetadata(null, SelectedItemsChanged));
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Unloaded -= OnUnloaded;
AssociatedObject.SelectionChanged -= ListBoxSelectionChanged;

if (AssociatedObject.SelectedItems is INotifyCollectionChanged val)
{
val.CollectionChanged -= SourceCollectionChanged;
}
}

private static void SelectedItemsChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var behavior = o as MultiSelectionBehavior;
if (behavior == null)
if (!(o is MultiSelectionBehavior behavior))
return;

var oldValue = e.OldValue as INotifyCollectionChanged;
Expand All @@ -47,29 +66,35 @@ private static void SelectedItemsChanged(DependencyObject o, DependencyPropertyC
oldValue.CollectionChanged -= behavior.SourceCollectionChanged;
behavior.AssociatedObject.SelectionChanged -= behavior.ListBoxSelectionChanged;
}
if (newValue != null)
{
behavior.AssociatedObject.SelectedItems.Clear();
foreach (var item in (IEnumerable)newValue)
{
behavior.AssociatedObject.SelectedItems.Add(item);
}

behavior.AssociatedObject.SelectionChanged += behavior.ListBoxSelectionChanged;
newValue.CollectionChanged += behavior.SourceCollectionChanged;
if (newValue == null)
return;

behavior.AssociatedObject.SelectedItems.Clear();
foreach (var item in (IEnumerable)newValue)
{
behavior.AssociatedObject.SelectedItems.Add(item);
}
}

private bool _isUpdatingTarget;
private bool _isUpdatingSource;
behavior.AssociatedObject.SelectionChanged += behavior.ListBoxSelectionChanged;
newValue.CollectionChanged += behavior.SourceCollectionChanged;
}

void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_isUpdatingSource)
return;

if (AssociatedObject is null)
{
System.Diagnostics.Debug.WriteLine("Collection associated object is null");
return;
}

try
{
//TODO: TRY TO FIX THE CRASH WHEN SWITCHING VIEWS
System.Diagnostics.Debug.WriteLine("Collection changed started....");
_isUpdatingTarget = true;

if (e.OldItems != null)
Expand All @@ -96,6 +121,7 @@ void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
finally
{
_isUpdatingTarget = false;
System.Diagnostics.Debug.WriteLine("Collection changed completed");
}
}

Expand All @@ -111,7 +137,7 @@ private void ListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
try
{
_isUpdatingSource = true;

System.Diagnostics.Debug.WriteLine("Selection changed started....");
foreach (var item in e.RemovedItems)
{
selectedItems.Remove(item);
Expand All @@ -125,8 +151,8 @@ private void ListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
finally
{
_isUpdatingSource = false;
System.Diagnostics.Debug.WriteLine("Selection changed completed");
}
}

}
}
43 changes: 43 additions & 0 deletions CastIt/Common/Converters/NumberComparerToBooleanConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.Globalization;
using System.Windows.Data;

namespace CastIt.Common.Converters
{
public class NumberComparerToBooleanConverter : IValueConverter
{
public bool GreaterThan { get; set; }
public bool GreaterThanOrEqual { get; set; }
public bool Equal { get; set; }
public bool LessThan { get; set; }
public bool LessThanOrEqual { get; set; }

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var currentItems = System.Convert.ToInt32(value);
var expected = System.Convert.ToInt32(parameter);

if (GreaterThan)
return currentItems > expected;

if (GreaterThanOrEqual)
return currentItems >= expected;

if (Equal)
return currentItems == expected;

if (LessThan)
return currentItems < expected;

if (LessThanOrEqual)
return currentItems <= expected;

throw new InvalidOperationException("You need to set one of the converters properties");
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Loading